]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_vxlan.c
sharpd, staticd: Add access_list_init
[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 #ifdef GNU_LINUX
37 #include <linux/neighbour.h>
38 #endif
39
40 #include "zebra/rib.h"
41 #include "zebra/rt.h"
42 #include "zebra/zebra_ns.h"
43 #include "zebra/zserv.h"
44 #include "zebra/debug.h"
45 #include "zebra/interface.h"
46 #include "zebra/zebra_vrf.h"
47 #include "zebra/rt_netlink.h"
48 #include "zebra/zebra_vxlan_private.h"
49 #include "zebra/zebra_vxlan.h"
50 #include "zebra/zebra_memory.h"
51 #include "zebra/zebra_l2.h"
52
53 DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix");
54 DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash");
55 DEFINE_MTYPE_STATIC(ZEBRA, ZL3VNI, "L3 VNI hash");
56 DEFINE_MTYPE_STATIC(ZEBRA, ZVNI_VTEP, "VNI remote VTEP");
57 DEFINE_MTYPE_STATIC(ZEBRA, MAC, "VNI MAC");
58 DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "VNI Neighbor");
59
60 /* definitions */
61
62 /* static function declarations */
63 static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
64 uint16_t cmd);
65 static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json);
66 static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt);
67 static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
68 void **args);
69 static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty,
70 json_object *json);
71 static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty,
72 json_object *json);
73 static void zvni_print_mac(zebra_mac_t *mac, void *ctxt);
74 static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt);
75 static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt);
76 static void zvni_print(zebra_vni_t *zvni, void **ctxt);
77 static void zvni_print_hash(struct hash_backet *backet, void *ctxt[]);
78
79 static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
80 struct ipaddr *ip, uint8_t flags,
81 uint16_t cmd);
82 static unsigned int neigh_hash_keymake(void *p);
83 static int neigh_cmp(const void *p1, const void *p2);
84 static void *zvni_neigh_alloc(void *p);
85 static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
86 struct ethaddr *mac);
87 static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n);
88 static void zvni_neigh_del_from_vtep(zebra_vni_t *zvni, int uninstall,
89 struct in_addr *r_vtep_ip);
90 static void zvni_neigh_del_all(zebra_vni_t *zvni, int uninstall, int upd_client,
91 uint32_t flags);
92 static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip);
93 static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
94 struct ethaddr *macaddr,
95 uint8_t flags);
96 static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
97 struct ethaddr *macaddr,
98 uint8_t flags);
99 static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n);
100 static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n);
101 static zebra_vni_t *zvni_from_svi(struct interface *ifp,
102 struct interface *br_if);
103 static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if);
104
105 /* l3-vni next-hop neigh related APIs */
106 static zebra_neigh_t *zl3vni_nh_lookup(zebra_l3vni_t *zl3vni,
107 struct ipaddr *ip);
108 static void *zl3vni_nh_alloc(void *p);
109 static zebra_neigh_t *zl3vni_nh_add(zebra_l3vni_t *zl3vni,
110 struct ipaddr *vtep_ip,
111 struct ethaddr *rmac);
112 static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n);
113 static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n);
114 static int zl3vni_nh_uninstall(zebra_l3vni_t *zl3vni, zebra_neigh_t *n);
115
116 /* l3-vni rmac related APIs */
117 static void zl3vni_print_rmac_hash(struct hash_backet *, void *);
118 static zebra_mac_t *zl3vni_rmac_lookup(zebra_l3vni_t *zl3vni,
119 struct ethaddr *rmac);
120 static void *zl3vni_rmac_alloc(void *p);
121 static zebra_mac_t *zl3vni_rmac_add(zebra_l3vni_t *zl3vni,
122 struct ethaddr *rmac);
123 static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac);
124 static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac);
125 static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac);
126
127 /* l3-vni related APIs*/
128 static zebra_l3vni_t *zl3vni_lookup(vni_t vni);
129 static void *zl3vni_alloc(void *p);
130 static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id);
131 static int zl3vni_del(zebra_l3vni_t *zl3vni);
132 static zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t);
133 static struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni);
134 static struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni);
135 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni);
136 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni);
137
138 static unsigned int mac_hash_keymake(void *p);
139 static int mac_cmp(const void *p1, const void *p2);
140 static void *zvni_mac_alloc(void *p);
141 static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr);
142 static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac);
143 static void zvni_mac_del_from_vtep(zebra_vni_t *zvni, int uninstall,
144 struct in_addr *r_vtep_ip);
145 static void zvni_mac_del_all(zebra_vni_t *zvni, int uninstall, int upd_client,
146 uint32_t flags);
147 static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *macaddr);
148 static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
149 uint8_t flags);
150 static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr,
151 uint8_t flags);
152 static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
153 struct interface *br_if, vlanid_t vid);
154 static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac);
155 static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac, int local);
156 static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt);
157
158 static unsigned int vni_hash_keymake(void *p);
159 static int vni_hash_cmp(const void *p1, const void *p2);
160 static void *zvni_alloc(void *p);
161 static zebra_vni_t *zvni_lookup(vni_t vni);
162 static zebra_vni_t *zvni_add(vni_t vni);
163 static int zvni_del(zebra_vni_t *zvni);
164 static int zvni_send_add_to_client(zebra_vni_t *zvni);
165 static int zvni_send_del_to_client(vni_t vni);
166 static void zvni_build_hash_table();
167 static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep);
168 static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip);
169 static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip);
170 static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep);
171 static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall);
172 static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip);
173 static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip);
174 static int zvni_del_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni);
175 static int zvni_add_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni);
176 static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
177 struct ethaddr *macaddr, struct ipaddr *ip);
178 static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
179 struct ipaddr *ip);
180 struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp);
181 static int advertise_gw_macip_enabled(zebra_vni_t *zvni);
182 static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac,
183 int uninstall);
184
185 /* Private functions */
186 static int host_rb_entry_compare(const struct host_rb_entry *hle1,
187 const struct host_rb_entry *hle2)
188 {
189 if (hle1->p.family < hle2->p.family)
190 return -1;
191
192 if (hle1->p.family > hle2->p.family)
193 return 1;
194
195 if (hle1->p.prefixlen < hle2->p.prefixlen)
196 return -1;
197
198 if (hle1->p.prefixlen > hle2->p.prefixlen)
199 return 1;
200
201 if (hle1->p.family == AF_INET) {
202 if (hle1->p.u.prefix4.s_addr < hle2->p.u.prefix4.s_addr)
203 return -1;
204
205 if (hle1->p.u.prefix4.s_addr > hle2->p.u.prefix4.s_addr)
206 return 1;
207
208 return 0;
209 } else {
210 zlog_warn("%s: Unexpected family type: %d", __PRETTY_FUNCTION__,
211 hle1->p.family);
212 return 0;
213 }
214 }
215 RB_GENERATE(host_rb_tree_entry, host_rb_entry, hl_entry, host_rb_entry_compare);
216
217 static uint32_t rb_host_count(struct host_rb_tree_entry *hrbe)
218 {
219 struct host_rb_entry *hle;
220 uint32_t count = 0;
221
222 RB_FOREACH (hle, host_rb_tree_entry, hrbe)
223 count++;
224
225 return count;
226 }
227
228 /*
229 * Return number of valid MACs in a VNI's MAC hash table - all
230 * remote MACs and non-internal (auto) local MACs count.
231 */
232 static uint32_t num_valid_macs(zebra_vni_t *zvni)
233 {
234 unsigned int i;
235 uint32_t num_macs = 0;
236 struct hash *hash;
237 struct hash_backet *hb;
238 zebra_mac_t *mac;
239
240 hash = zvni->mac_table;
241 if (!hash)
242 return num_macs;
243 for (i = 0; i < hash->size; i++) {
244 for (hb = hash->index[i]; hb; hb = hb->next) {
245 mac = (zebra_mac_t *)hb->data;
246 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
247 || CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
248 || !CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
249 num_macs++;
250 }
251 }
252
253 return num_macs;
254 }
255
256 static int advertise_gw_macip_enabled(zebra_vni_t *zvni)
257 {
258 struct zebra_vrf *zvrf;
259
260 zvrf = vrf_info_lookup(VRF_DEFAULT);
261 if (zvrf && zvrf->advertise_gw_macip)
262 return 1;
263
264 if (zvni && zvni->advertise_gw_macip)
265 return 1;
266
267 return 0;
268 }
269
270 /*
271 * Helper function to determine maximum width of neighbor IP address for
272 * display - just because we're dealing with IPv6 addresses that can
273 * widely vary.
274 */
275 static void zvni_find_neigh_addr_width(struct hash_backet *backet, void *ctxt)
276 {
277 zebra_neigh_t *n;
278 char buf[INET6_ADDRSTRLEN];
279 struct neigh_walk_ctx *wctx = ctxt;
280 int width;
281
282 n = (zebra_neigh_t *)backet->data;
283 if (!n)
284 return;
285
286 ipaddr2str(&n->ip, buf, sizeof(buf)), width = strlen(buf);
287 if (width > wctx->addr_width)
288 wctx->addr_width = width;
289
290 }
291
292 /*
293 * Print a specific neighbor entry.
294 */
295 static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
296 {
297 struct vty *vty;
298 char buf1[ETHER_ADDR_STRLEN];
299 char buf2[INET6_ADDRSTRLEN];
300
301 ipaddr2str(&n->ip, buf2, sizeof(buf2));
302 prefix_mac2str(&n->emac, buf1, sizeof(buf1));
303 vty = (struct vty *)ctxt;
304 if (json == NULL) {
305 vty_out(vty, "IP: %s\n",
306 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
307 vty_out(vty, " MAC: %s",
308 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
309 } else {
310 json_object_string_add(json, "ip", buf2);
311 json_object_string_add(json, "mac", buf1);
312 }
313 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
314 if (json == NULL) {
315 vty_out(vty, " Remote VTEP: %s",
316 inet_ntoa(n->r_vtep_ip));
317 } else
318 json_object_string_add(json, "remoteVtep",
319 inet_ntoa(n->r_vtep_ip));
320 }
321 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
322 if (!json) {
323 vty_out(vty, "\n");
324 vty_out(vty, " State: %s",
325 IS_ZEBRA_NEIGH_ACTIVE(n) ? "Active"
326 : "Inactive");
327 }
328 }
329 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW)) {
330 if (!json)
331 vty_out(vty, " Default-gateway");
332 else
333 json_object_boolean_true_add(json, "defaultGateway");
334 }
335 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)) {
336 if (!json)
337 vty_out(vty, " Router");
338 }
339 if (json == NULL)
340 vty_out(vty, "\n");
341 }
342
343 /*
344 * Print neighbor hash entry - called for display of all neighbors.
345 */
346 static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt)
347 {
348 struct vty *vty;
349 json_object *json_vni = NULL, *json_row = NULL;
350 zebra_neigh_t *n;
351 char buf1[ETHER_ADDR_STRLEN];
352 char buf2[INET6_ADDRSTRLEN];
353 struct neigh_walk_ctx *wctx = ctxt;
354
355 vty = wctx->vty;
356 json_vni = wctx->json;
357 n = (zebra_neigh_t *)backet->data;
358 if (!n)
359 return;
360
361 if (json_vni)
362 json_row = json_object_new_object();
363
364 prefix_mac2str(&n->emac, buf1, sizeof(buf1));
365 ipaddr2str(&n->ip, buf2, sizeof(buf2));
366 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)
367 && !(wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)) {
368 if (json_vni == NULL) {
369 vty_out(vty, "%*s %-6s %-17s\n", -wctx->addr_width,
370 buf2, "local", buf1);
371 } else {
372 json_object_string_add(json_row, "type", "local");
373 json_object_string_add(json_row, "mac", buf1);
374 }
375 wctx->count++;
376 } else {
377 if (wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) {
378 if (IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip)) {
379 if (json_vni == NULL) {
380 if (wctx->count == 0)
381 vty_out(vty,
382 "%*s %-6s %-17s %-21s\n",
383 -wctx->addr_width,
384 "Neighbor", "Type",
385 "MAC", "Remote VTEP");
386 vty_out(vty, "%*s %-6s %-17s %-21s\n",
387 -wctx->addr_width, buf2,
388 "remote", buf1,
389 inet_ntoa(n->r_vtep_ip));
390 } else {
391 json_object_string_add(json_row, "type",
392 "remote");
393 json_object_string_add(json_row, "mac",
394 buf1);
395 json_object_string_add(
396 json_row, "remoteVtep",
397 inet_ntoa(n->r_vtep_ip));
398 }
399 wctx->count++;
400 }
401 } else {
402 if (json_vni == NULL) {
403 vty_out(vty, "%*s %-6s %-17s %-21s\n",
404 -wctx->addr_width, buf2, "remote", buf1,
405 inet_ntoa(n->r_vtep_ip));
406 } else {
407 json_object_string_add(json_row, "type",
408 "remote");
409 json_object_string_add(json_row, "mac", buf1);
410 json_object_string_add(json_row, "remoteVtep",
411 inet_ntoa(n->r_vtep_ip));
412 }
413 wctx->count++;
414 }
415 }
416
417 if (json_vni)
418 json_object_object_add(json_vni, buf2, json_row);
419 }
420
421 /*
422 * Print neighbors for all VNI.
423 */
424 static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
425 void **args)
426 {
427 struct vty *vty;
428 json_object *json = NULL, *json_vni = NULL;
429 zebra_vni_t *zvni;
430 uint32_t num_neigh;
431 struct neigh_walk_ctx wctx;
432 char vni_str[VNI_STR_LEN];
433
434 vty = (struct vty *)args[0];
435 json = (json_object *)args[1];
436
437 zvni = (zebra_vni_t *)backet->data;
438 if (!zvni) {
439 if (json)
440 vty_out(vty, "{}\n");
441 return;
442 }
443 num_neigh = hashcount(zvni->neigh_table);
444 if (json == NULL) {
445 vty_out(vty,
446 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
447 zvni->vni, num_neigh);
448 } else {
449 json_vni = json_object_new_object();
450 json_object_int_add(json_vni, "numArpNd", num_neigh);
451 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
452 }
453 if (!num_neigh) {
454 if (json)
455 json_object_object_add(json, vni_str, json_vni);
456 return;
457 }
458
459 /* Since we have IPv6 addresses to deal with which can vary widely in
460 * size, we try to be a bit more elegant in display by first computing
461 * the maximum width.
462 */
463 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
464 wctx.zvni = zvni;
465 wctx.vty = vty;
466 wctx.addr_width = 15;
467 wctx.json = json_vni;
468 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
469
470 if (json == NULL) {
471 vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP",
472 "Type", "MAC", "Remote VTEP");
473 }
474 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
475
476 if (json)
477 json_object_object_add(json, vni_str, json_vni);
478 }
479
480 /* print a specific next hop for an l3vni */
481 static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty,
482 json_object *json)
483 {
484 char buf1[ETHER_ADDR_STRLEN];
485 char buf2[INET6_ADDRSTRLEN];
486 json_object *json_hosts = NULL;
487 struct host_rb_entry *hle;
488
489 if (!json) {
490 vty_out(vty, "Ip: %s\n",
491 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
492 vty_out(vty, " RMAC: %s\n",
493 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
494 vty_out(vty, " Refcount: %d\n",
495 rb_host_count(&n->host_rb));
496 vty_out(vty, " Prefixes:\n");
497 RB_FOREACH (hle, host_rb_tree_entry, &n->host_rb)
498 vty_out(vty, " %s\n",
499 prefix2str(&hle->p, buf2, sizeof(buf2)));
500 } else {
501 json_hosts = json_object_new_array();
502 json_object_string_add(
503 json, "ip", ipaddr2str(&(n->ip), buf2, sizeof(buf2)));
504 json_object_string_add(
505 json, "routerMac",
506 prefix_mac2str(&n->emac, buf2, sizeof(buf2)));
507 json_object_int_add(json, "refCount",
508 rb_host_count(&n->host_rb));
509 RB_FOREACH (hle, host_rb_tree_entry, &n->host_rb)
510 json_object_array_add(json_hosts,
511 json_object_new_string(prefix2str(
512 &hle->p, buf2, sizeof(buf2))));
513 json_object_object_add(json, "prefixList", json_hosts);
514 }
515 }
516
517 /* Print a specific RMAC entry */
518 static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty,
519 json_object *json)
520 {
521 char buf1[ETHER_ADDR_STRLEN];
522 char buf2[PREFIX_STRLEN];
523 json_object *json_hosts = NULL;
524 struct host_rb_entry *hle;
525
526 if (!json) {
527 vty_out(vty, "MAC: %s\n",
528 prefix_mac2str(&zrmac->macaddr, buf1, sizeof(buf1)));
529 vty_out(vty, " Remote VTEP: %s\n",
530 inet_ntoa(zrmac->fwd_info.r_vtep_ip));
531 vty_out(vty, " Refcount: %d\n", rb_host_count(&zrmac->host_rb));
532 vty_out(vty, " Prefixes:\n");
533 RB_FOREACH (hle, host_rb_tree_entry, &zrmac->host_rb)
534 vty_out(vty, " %s\n",
535 prefix2str(&hle->p, buf2, sizeof(buf2)));
536 } else {
537 json_hosts = json_object_new_array();
538 json_object_string_add(
539 json, "routerMac",
540 prefix_mac2str(&zrmac->macaddr, buf1, sizeof(buf1)));
541 json_object_string_add(json, "vtepIp",
542 inet_ntoa(zrmac->fwd_info.r_vtep_ip));
543 json_object_int_add(json, "refCount",
544 rb_host_count(&zrmac->host_rb));
545 RB_FOREACH (hle, host_rb_tree_entry, &zrmac->host_rb)
546 json_object_array_add(
547 json_hosts,
548 json_object_new_string(prefix2str(
549 &hle->p, buf2, sizeof(buf2))));
550 json_object_object_add(json, "prefixList", json_hosts);
551 }
552 }
553
554 /*
555 * Print a specific MAC entry.
556 */
557 static void zvni_print_mac(zebra_mac_t *mac, void *ctxt)
558 {
559 struct vty *vty;
560 zebra_neigh_t *n = NULL;
561 struct listnode *node = NULL;
562 char buf1[20];
563 char buf2[INET6_ADDRSTRLEN];
564
565 vty = (struct vty *)ctxt;
566 vty_out(vty, "MAC: %s",
567 prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1)));
568 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
569 struct zebra_ns *zns;
570 struct interface *ifp;
571 ifindex_t ifindex;
572
573 ifindex = mac->fwd_info.local.ifindex;
574 zns = zebra_ns_lookup(NS_DEFAULT);
575 ifp = if_lookup_by_index_per_ns(zns, ifindex);
576 if (!ifp) // unexpected
577 return;
578 vty_out(vty, " Intf: %s(%u)", ifp->name, ifindex);
579 if (mac->fwd_info.local.vid)
580 vty_out(vty, " VLAN: %u", mac->fwd_info.local.vid);
581 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
582 vty_out(vty, " Remote VTEP: %s",
583 inet_ntoa(mac->fwd_info.r_vtep_ip));
584 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
585 vty_out(vty, " Auto Mac ");
586 }
587
588 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
589 vty_out(vty, " Sticky Mac ");
590
591 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
592 vty_out(vty, " Default-gateway Mac ");
593
594 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW))
595 vty_out(vty, " Remote-gateway Mac ");
596
597 vty_out(vty, "\n");
598 /* print all the associated neigh */
599 vty_out(vty, " Neighbors:\n");
600 if (!listcount(mac->neigh_list))
601 vty_out(vty, " No Neighbors\n");
602 else {
603 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
604 vty_out(vty, " %s %s\n",
605 ipaddr2str(&n->ip, buf2, sizeof(buf2)),
606 CHECK_FLAG(n->flags, ZEBRA_MAC_LOCAL)
607 ? (IS_ZEBRA_NEIGH_ACTIVE(n)
608 ? "Active"
609 : "Inactive")
610 : "");
611 }
612 }
613
614 vty_out(vty, "\n");
615 }
616
617 /*
618 * Print MAC hash entry - called for display of all MACs.
619 */
620 static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt)
621 {
622 struct vty *vty;
623 json_object *json_mac_hdr = NULL, *json_mac = NULL;
624 zebra_mac_t *mac;
625 char buf1[20];
626 struct mac_walk_ctx *wctx = ctxt;
627
628 vty = wctx->vty;
629 json_mac_hdr = wctx->json;
630 mac = (zebra_mac_t *)backet->data;
631 if (!mac)
632 return;
633
634 prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
635
636 if (json_mac_hdr)
637 json_mac = json_object_new_object();
638
639 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
640 && !(wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)) {
641 struct zebra_ns *zns;
642 ifindex_t ifindex;
643 struct interface *ifp;
644 vlanid_t vid;
645
646 zns = zebra_ns_lookup(NS_DEFAULT);
647 ifindex = mac->fwd_info.local.ifindex;
648 ifp = if_lookup_by_index_per_ns(zns, ifindex);
649 if (!ifp) // unexpected
650 return;
651 vid = mac->fwd_info.local.vid;
652 if (json_mac_hdr == NULL)
653 vty_out(vty, "%-17s %-6s %-21s", buf1, "local",
654 ifp->name);
655 else {
656 json_object_string_add(json_mac, "type", "local");
657 json_object_string_add(json_mac, "intf", ifp->name);
658 }
659 if (vid) {
660 if (json_mac_hdr == NULL)
661 vty_out(vty, " %-5u", vid);
662 else
663 json_object_int_add(json_mac, "vlan", vid);
664 }
665 if (json_mac_hdr == NULL)
666 vty_out(vty, "\n");
667 else
668 json_object_object_add(json_mac_hdr, buf1, json_mac);
669 wctx->count++;
670 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
671 if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) {
672 if (IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
673 &wctx->r_vtep_ip)) {
674 if (wctx->count == 0) {
675 if (json_mac_hdr == NULL) {
676 vty_out(vty, "\nVNI %u\n\n",
677 wctx->zvni->vni);
678 vty_out(vty,
679 "%-17s %-6s %-21s %-5s\n",
680 "MAC", "Type",
681 "Intf/Remote VTEP",
682 "VLAN");
683 }
684 }
685 if (json_mac_hdr == NULL)
686 vty_out(vty, "%-17s %-6s %-21s\n", buf1,
687 "remote",
688 inet_ntoa(mac->fwd_info
689 .r_vtep_ip));
690 else {
691 json_object_string_add(json_mac, "type",
692 "remote");
693 json_object_string_add(
694 json_mac, "remoteVtep",
695 inet_ntoa(mac->fwd_info
696 .r_vtep_ip));
697 json_object_object_add(json_mac_hdr,
698 buf1, json_mac);
699 }
700 wctx->count++;
701 }
702 } else {
703 if (json_mac_hdr == NULL)
704 vty_out(vty, "%-17s %-6s %-21s\n", buf1,
705 "remote",
706 inet_ntoa(mac->fwd_info.r_vtep_ip));
707 else {
708 json_object_string_add(json_mac, "type",
709 "remote");
710 json_object_string_add(
711 json_mac, "remoteVtep",
712 inet_ntoa(mac->fwd_info.r_vtep_ip));
713 json_object_object_add(json_mac_hdr, buf1,
714 json_mac);
715 }
716 wctx->count++;
717 }
718 }
719 }
720
721 /*
722 * Print MACs for all VNI.
723 */
724 static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt)
725 {
726 struct vty *vty;
727 json_object *json = NULL, *json_vni = NULL;
728 json_object *json_mac = NULL;
729 zebra_vni_t *zvni;
730 uint32_t num_macs;
731 struct mac_walk_ctx *wctx = ctxt;
732 char vni_str[VNI_STR_LEN];
733
734 vty = (struct vty *)wctx->vty;
735 json = (struct json_object *)wctx->json;
736
737 zvni = (zebra_vni_t *)backet->data;
738 if (!zvni) {
739 if (json)
740 vty_out(vty, "{}\n");
741 return;
742 }
743 wctx->zvni = zvni;
744
745 /*We are iterating over a new VNI, set the count to 0*/
746 wctx->count = 0;
747
748 num_macs = num_valid_macs(zvni);
749 if (!num_macs)
750 return;
751
752 if (json) {
753 json_vni = json_object_new_object();
754 json_mac = json_object_new_object();
755 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
756 }
757
758 if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) {
759 if (json == NULL) {
760 vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
761 zvni->vni, num_macs);
762 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
763 "Intf/Remote VTEP", "VLAN");
764 } else
765 json_object_int_add(json_vni, "numMacs", num_macs);
766 }
767 /* assign per-vni to wctx->json object to fill macs
768 * under the vni. Re-assign primary json object to fill
769 * next vni information.
770 */
771 wctx->json = json_mac;
772 hash_iterate(zvni->mac_table, zvni_print_mac_hash, wctx);
773 wctx->json = json;
774 if (json) {
775 if (wctx->count)
776 json_object_object_add(json_vni, "macs", json_mac);
777 json_object_object_add(json, vni_str, json_vni);
778 }
779 }
780
781 static void zl3vni_print_nh_hash(struct hash_backet *backet, void *ctx)
782 {
783 struct nh_walk_ctx *wctx = NULL;
784 struct vty *vty = NULL;
785 struct json_object *json_vni = NULL;
786 struct json_object *json_nh = NULL;
787 zebra_neigh_t *n = NULL;
788 char buf1[ETHER_ADDR_STRLEN];
789 char buf2[INET6_ADDRSTRLEN];
790
791 wctx = (struct nh_walk_ctx *)ctx;
792 vty = wctx->vty;
793 json_vni = wctx->json;
794 if (json_vni)
795 json_nh = json_object_new_object();
796 n = (zebra_neigh_t *)backet->data;
797 if (!n)
798 return;
799
800 if (!json_vni) {
801 vty_out(vty, "%-15s %-17s\n",
802 ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
803 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
804 } else {
805 json_object_string_add(json_nh, "nexthopIp",
806 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
807 json_object_string_add(
808 json_nh, "routerMac",
809 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
810 json_object_object_add(json_vni,
811 ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
812 json_nh);
813 }
814 }
815
816 static void zl3vni_print_nh_hash_all_vni(struct hash_backet *backet,
817 void **args)
818 {
819 struct vty *vty = NULL;
820 json_object *json = NULL;
821 json_object *json_vni = NULL;
822 zebra_l3vni_t *zl3vni = NULL;
823 uint32_t num_nh = 0;
824 struct nh_walk_ctx wctx;
825 char vni_str[VNI_STR_LEN];
826
827 vty = (struct vty *)args[0];
828 json = (struct json_object *)args[1];
829
830 zl3vni = (zebra_l3vni_t *)backet->data;
831 if (!zl3vni) {
832 if (json)
833 vty_out(vty, "{}\n");
834 return;
835 }
836
837 num_nh = hashcount(zl3vni->nh_table);
838 if (!num_nh)
839 return;
840
841 if (json) {
842 json_vni = json_object_new_object();
843 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
844 }
845
846 if (json == NULL) {
847 vty_out(vty, "\nVNI %u #Next-Hops %u\n\n", zl3vni->vni, num_nh);
848 vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
849 } else
850 json_object_int_add(json_vni, "numNextHops", num_nh);
851
852 memset(&wctx, 0, sizeof(struct nh_walk_ctx));
853 wctx.vty = vty;
854 wctx.json = json_vni;
855 hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
856 if (json)
857 json_object_object_add(json, vni_str, json_vni);
858 }
859
860 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet *backet,
861 void **args)
862 {
863 struct vty *vty = NULL;
864 json_object *json = NULL;
865 json_object *json_vni = NULL;
866 zebra_l3vni_t *zl3vni = NULL;
867 uint32_t num_rmacs;
868 struct rmac_walk_ctx wctx;
869 char vni_str[VNI_STR_LEN];
870
871 vty = (struct vty *)args[0];
872 json = (struct json_object *)args[1];
873
874 zl3vni = (zebra_l3vni_t *)backet->data;
875 if (!zl3vni) {
876 if (json)
877 vty_out(vty, "{}\n");
878 return;
879 }
880
881 num_rmacs = hashcount(zl3vni->rmac_table);
882 if (!num_rmacs)
883 return;
884
885 if (json) {
886 json_vni = json_object_new_object();
887 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
888 }
889
890 if (json == NULL) {
891 vty_out(vty, "\nVNI %u #RMACs %u\n\n", zl3vni->vni, num_rmacs);
892 vty_out(vty, "%-17s %-21s\n", "RMAC", "Remote VTEP");
893 } else
894 json_object_int_add(json_vni, "numRmacs", num_rmacs);
895
896 /* assign per-vni to wctx->json object to fill macs
897 * under the vni. Re-assign primary json object to fill
898 * next vni information.
899 */
900 memset(&wctx, 0, sizeof(struct rmac_walk_ctx));
901 wctx.vty = vty;
902 wctx.json = json_vni;
903 hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
904 if (json)
905 json_object_object_add(json, vni_str, json_vni);
906 }
907
908 static void zl3vni_print_rmac_hash(struct hash_backet *backet, void *ctx)
909 {
910 zebra_mac_t *zrmac = NULL;
911 struct rmac_walk_ctx *wctx = NULL;
912 struct vty *vty = NULL;
913 struct json_object *json = NULL;
914 struct json_object *json_rmac = NULL;
915 char buf[ETHER_ADDR_STRLEN];
916
917 wctx = (struct rmac_walk_ctx *)ctx;
918 vty = wctx->vty;
919 json = wctx->json;
920 if (json)
921 json_rmac = json_object_new_object();
922 zrmac = (zebra_mac_t *)backet->data;
923 if (!zrmac)
924 return;
925
926 if (!json) {
927 vty_out(vty, "%-17s %-21s\n",
928 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
929 inet_ntoa(zrmac->fwd_info.r_vtep_ip));
930 } else {
931 json_object_string_add(
932 json_rmac, "routerMac",
933 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)));
934 json_object_string_add(json_rmac, "vtepIp",
935 inet_ntoa(zrmac->fwd_info.r_vtep_ip));
936 json_object_object_add(
937 json, prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
938 json_rmac);
939 }
940 }
941
942 /* print a specific L3 VNI entry */
943 static void zl3vni_print(zebra_l3vni_t *zl3vni, void **ctx)
944 {
945 char buf[ETHER_ADDR_STRLEN];
946 struct vty *vty = NULL;
947 json_object *json = NULL;
948 zebra_vni_t *zvni = NULL;
949 json_object *json_vni_list = NULL;
950 struct listnode *node = NULL, *nnode = NULL;
951
952 vty = ctx[0];
953 json = ctx[1];
954
955 if (!json) {
956 vty_out(vty, "VNI: %u\n", zl3vni->vni);
957 vty_out(vty, " Type: %s\n", "L3");
958 vty_out(vty, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni));
959 vty_out(vty, " Local Vtep Ip: %s\n",
960 inet_ntoa(zl3vni->local_vtep_ip));
961 vty_out(vty, " Vxlan-Intf: %s\n",
962 zl3vni_vxlan_if_name(zl3vni));
963 vty_out(vty, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni));
964 vty_out(vty, " State: %s\n", zl3vni_state2str(zl3vni));
965 vty_out(vty, " VNI Filter: %s\n",
966 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
967 ? "prefix-routes-only"
968 : "none");
969 vty_out(vty, " Router MAC: %s\n",
970 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
971 vty_out(vty, " L2 VNIs: ");
972 for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zvni))
973 vty_out(vty, "%u ", zvni->vni);
974 vty_out(vty, "\n");
975 } else {
976 json_vni_list = json_object_new_array();
977 json_object_int_add(json, "vni", zl3vni->vni);
978 json_object_string_add(json, "type", "L3");
979 json_object_string_add(json, "localVtepIp",
980 inet_ntoa(zl3vni->local_vtep_ip));
981 json_object_string_add(json, "vxlanIntf",
982 zl3vni_vxlan_if_name(zl3vni));
983 json_object_string_add(json, "sviIntf",
984 zl3vni_svi_if_name(zl3vni));
985 json_object_string_add(json, "state", zl3vni_state2str(zl3vni));
986 json_object_string_add(json, "vrf", zl3vni_vrf_name(zl3vni));
987 json_object_string_add(
988 json, "routerMac",
989 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
990 json_object_string_add(
991 json, "vniFilter",
992 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
993 ? "prefix-routes-only"
994 : "none");
995 for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zvni)) {
996 json_object_array_add(json_vni_list,
997 json_object_new_int(zvni->vni));
998 }
999 json_object_object_add(json, "l2Vnis", json_vni_list);
1000 }
1001 }
1002
1003 /*
1004 * Print a specific VNI entry.
1005 */
1006 static void zvni_print(zebra_vni_t *zvni, void **ctxt)
1007 {
1008 struct vty *vty;
1009 zebra_vtep_t *zvtep;
1010 uint32_t num_macs;
1011 uint32_t num_neigh;
1012 json_object *json = NULL;
1013 json_object *json_vtep_list = NULL;
1014 json_object *json_ip_str = NULL;
1015
1016 vty = ctxt[0];
1017 json = ctxt[1];
1018
1019 if (json == NULL) {
1020 vty_out(vty, "VNI: %u\n", zvni->vni);
1021 vty_out(vty, " Type: %s\n", "L2");
1022 vty_out(vty, " Tenant VRF: %s\n", vrf_id_to_name(zvni->vrf_id));
1023 } else {
1024 json_object_int_add(json, "vni", zvni->vni);
1025 json_object_string_add(json, "type", "L2");
1026 json_object_string_add(json, "vrf",
1027 vrf_id_to_name(zvni->vrf_id));
1028 }
1029
1030 if (!zvni->vxlan_if) { // unexpected
1031 if (json == NULL)
1032 vty_out(vty, " VxLAN interface: unknown\n");
1033 return;
1034 }
1035 num_macs = num_valid_macs(zvni);
1036 num_neigh = hashcount(zvni->neigh_table);
1037 if (json == NULL) {
1038 vty_out(vty, " VxLAN interface: %s\n", zvni->vxlan_if->name);
1039 vty_out(vty, " VxLAN ifIndex: %u\n", zvni->vxlan_if->ifindex);
1040 vty_out(vty, " Local VTEP IP: %s\n",
1041 inet_ntoa(zvni->local_vtep_ip));
1042 } else {
1043 json_object_string_add(json, "vxlanInterface",
1044 zvni->vxlan_if->name);
1045 json_object_int_add(json, "ifindex", zvni->vxlan_if->ifindex);
1046 json_object_string_add(json, "vtepIp",
1047 inet_ntoa(zvni->local_vtep_ip));
1048 json_object_string_add(json, "advertiseGatewayMacip",
1049 zvni->advertise_gw_macip ? "Yes" : "No");
1050 json_object_int_add(json, "numMacs", num_macs);
1051 json_object_int_add(json, "numArpNd", num_neigh);
1052 }
1053 if (!zvni->vteps) {
1054 if (json == NULL)
1055 vty_out(vty, " No remote VTEPs known for this VNI\n");
1056 } else {
1057 if (json == NULL)
1058 vty_out(vty, " Remote VTEPs for this VNI:\n");
1059 else
1060 json_vtep_list = json_object_new_array();
1061 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
1062 if (json == NULL)
1063 vty_out(vty, " %s\n",
1064 inet_ntoa(zvtep->vtep_ip));
1065 else {
1066 json_ip_str = json_object_new_string(
1067 inet_ntoa(zvtep->vtep_ip));
1068 json_object_array_add(json_vtep_list,
1069 json_ip_str);
1070 }
1071 }
1072 if (json)
1073 json_object_object_add(json, "numRemoteVteps",
1074 json_vtep_list);
1075 }
1076 if (json == NULL) {
1077 vty_out(vty,
1078 " Number of MACs (local and remote) known for this VNI: %u\n",
1079 num_macs);
1080 vty_out(vty,
1081 " Number of ARPs (IPv4 and IPv6, local and remote) "
1082 "known for this VNI: %u\n",
1083 num_neigh);
1084 vty_out(vty, " Advertise-gw-macip: %s\n",
1085 zvni->advertise_gw_macip ? "Yes" : "No");
1086 }
1087 }
1088
1089 /* print a L3 VNI hash entry */
1090 static void zl3vni_print_hash(struct hash_backet *backet, void *ctx[])
1091 {
1092 struct vty *vty = NULL;
1093 json_object *json = NULL;
1094 json_object *json_vni = NULL;
1095 zebra_l3vni_t *zl3vni = NULL;
1096
1097 vty = (struct vty *)ctx[0];
1098 json = (json_object *)ctx[1];
1099
1100 zl3vni = (zebra_l3vni_t *)backet->data;
1101 if (!zl3vni)
1102 return;
1103
1104 if (!json) {
1105 vty_out(vty, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1106 zl3vni->vni, "L3", zl3vni_vxlan_if_name(zl3vni),
1107 hashcount(zl3vni->rmac_table),
1108 hashcount(zl3vni->nh_table), "n/a",
1109 zl3vni_vrf_name(zl3vni));
1110 } else {
1111 char vni_str[VNI_STR_LEN];
1112
1113 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
1114 json_vni = json_object_new_object();
1115 json_object_int_add(json_vni, "vni", zl3vni->vni);
1116 json_object_string_add(json_vni, "vxlanIf",
1117 zl3vni_vxlan_if_name(zl3vni));
1118 json_object_int_add(json_vni, "numMacs",
1119 hashcount(zl3vni->rmac_table));
1120 json_object_int_add(json_vni, "numArpNd",
1121 hashcount(zl3vni->nh_table));
1122 json_object_string_add(json_vni, "numRemoteVteps", "n/a");
1123 json_object_string_add(json_vni, "type", "L3");
1124 json_object_string_add(json_vni, "tenantVrf",
1125 zl3vni_vrf_name(zl3vni));
1126 json_object_object_add(json, vni_str, json_vni);
1127 }
1128 }
1129
1130 /*
1131 * Print a VNI hash entry - called for display of all VNIs.
1132 */
1133 static void zvni_print_hash(struct hash_backet *backet, void *ctxt[])
1134 {
1135 struct vty *vty;
1136 zebra_vni_t *zvni;
1137 zebra_vtep_t *zvtep;
1138 uint32_t num_vteps = 0;
1139 uint32_t num_macs = 0;
1140 uint32_t num_neigh = 0;
1141 json_object *json = NULL;
1142 json_object *json_vni = NULL;
1143 json_object *json_ip_str = NULL;
1144 json_object *json_vtep_list = NULL;
1145
1146 vty = ctxt[0];
1147 json = ctxt[1];
1148
1149 zvni = (zebra_vni_t *)backet->data;
1150 if (!zvni)
1151 return;
1152
1153 zvtep = zvni->vteps;
1154 while (zvtep) {
1155 num_vteps++;
1156 zvtep = zvtep->next;
1157 }
1158
1159 num_macs = num_valid_macs(zvni);
1160 num_neigh = hashcount(zvni->neigh_table);
1161 if (json == NULL)
1162 vty_out(vty, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1163 zvni->vni, "L2",
1164 zvni->vxlan_if ? zvni->vxlan_if->name : "unknown",
1165 num_macs, num_neigh, num_vteps,
1166 vrf_id_to_name(zvni->vrf_id));
1167 else {
1168 char vni_str[VNI_STR_LEN];
1169 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
1170 json_vni = json_object_new_object();
1171 json_object_int_add(json_vni, "vni", zvni->vni);
1172 json_object_string_add(json_vni, "type", "L2");
1173 json_object_string_add(json_vni, "vxlanIf",
1174 zvni->vxlan_if ? zvni->vxlan_if->name
1175 : "unknown");
1176 json_object_int_add(json_vni, "numMacs", num_macs);
1177 json_object_int_add(json_vni, "numArpNd", num_neigh);
1178 json_object_int_add(json_vni, "numRemoteVteps", num_vteps);
1179 json_object_string_add(json_vni, "tenantVrf",
1180 vrf_id_to_name(zvni->vrf_id));
1181 if (num_vteps) {
1182 json_vtep_list = json_object_new_array();
1183 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
1184 json_ip_str = json_object_new_string(
1185 inet_ntoa(zvtep->vtep_ip));
1186 json_object_array_add(json_vtep_list,
1187 json_ip_str);
1188 }
1189 json_object_object_add(json_vni, "remoteVteps",
1190 json_vtep_list);
1191 }
1192 json_object_object_add(json, vni_str, json_vni);
1193 }
1194 }
1195
1196 /*
1197 * Inform BGP about local MACIP.
1198 */
1199 static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
1200 struct ipaddr *ip, uint8_t flags,
1201 uint16_t cmd)
1202 {
1203 char buf[ETHER_ADDR_STRLEN];
1204 char buf2[INET6_ADDRSTRLEN];
1205 int ipa_len;
1206 struct zserv *client = NULL;
1207 struct stream *s = NULL;
1208
1209 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
1210 /* BGP may not be running. */
1211 if (!client)
1212 return 0;
1213
1214 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
1215
1216 zclient_create_header(s, cmd, VRF_DEFAULT);
1217 stream_putl(s, vni);
1218 stream_put(s, macaddr->octet, ETH_ALEN);
1219 if (ip) {
1220 ipa_len = 0;
1221 if (IS_IPADDR_V4(ip))
1222 ipa_len = IPV4_MAX_BYTELEN;
1223 else if (IS_IPADDR_V6(ip))
1224 ipa_len = IPV6_MAX_BYTELEN;
1225
1226 stream_putl(s, ipa_len); /* IP address length */
1227 if (ipa_len)
1228 stream_put(s, &ip->ip.addr, ipa_len); /* IP address */
1229 } else
1230 stream_putl(s, 0); /* Just MAC. */
1231
1232 stream_putc(s, flags); /* sticky mac/gateway mac */
1233
1234
1235 /* Write packet size. */
1236 stream_putw_at(s, 0, stream_get_endp(s));
1237
1238 if (IS_ZEBRA_DEBUG_VXLAN)
1239 zlog_debug(
1240 "Send MACIP %s flags 0x%x MAC %s IP %s L2-VNI %u to %s",
1241 (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", flags,
1242 prefix_mac2str(macaddr, buf, sizeof(buf)),
1243 ipaddr2str(ip, buf2, sizeof(buf2)), vni,
1244 zebra_route_string(client->proto));
1245
1246 if (cmd == ZEBRA_MACIP_ADD)
1247 client->macipadd_cnt++;
1248 else
1249 client->macipdel_cnt++;
1250
1251 return zserv_send_message(client, s);
1252 }
1253
1254 /*
1255 * Make hash key for neighbors.
1256 */
1257 static unsigned int neigh_hash_keymake(void *p)
1258 {
1259 zebra_neigh_t *n = p;
1260 struct ipaddr *ip = &n->ip;
1261
1262 if (IS_IPADDR_V4(ip))
1263 return jhash_1word(ip->ipaddr_v4.s_addr, 0);
1264
1265 return jhash2(ip->ipaddr_v6.s6_addr32,
1266 ZEBRA_NUM_OF(ip->ipaddr_v6.s6_addr32), 0);
1267 }
1268
1269 /*
1270 * Compare two neighbor hash structures.
1271 */
1272 static int neigh_cmp(const void *p1, const void *p2)
1273 {
1274 const zebra_neigh_t *n1 = p1;
1275 const zebra_neigh_t *n2 = p2;
1276
1277 if (n1 == NULL && n2 == NULL)
1278 return 1;
1279
1280 if (n1 == NULL || n2 == NULL)
1281 return 0;
1282
1283 return (memcmp(&n1->ip, &n2->ip, sizeof(struct ipaddr)) == 0);
1284 }
1285
1286 /*
1287 * Callback to allocate neighbor hash entry.
1288 */
1289 static void *zvni_neigh_alloc(void *p)
1290 {
1291 const zebra_neigh_t *tmp_n = p;
1292 zebra_neigh_t *n;
1293
1294 n = XCALLOC(MTYPE_NEIGH, sizeof(zebra_neigh_t));
1295 *n = *tmp_n;
1296
1297 return ((void *)n);
1298 }
1299
1300 /*
1301 * Add neighbor entry.
1302 */
1303 static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
1304 struct ethaddr *mac)
1305 {
1306 zebra_neigh_t tmp_n;
1307 zebra_neigh_t *n = NULL;
1308 zebra_mac_t *zmac = NULL;
1309
1310 memset(&tmp_n, 0, sizeof(zebra_neigh_t));
1311 memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
1312 n = hash_get(zvni->neigh_table, &tmp_n, zvni_neigh_alloc);
1313 assert(n);
1314
1315 memcpy(&n->emac, mac, ETH_ALEN);
1316 n->state = ZEBRA_NEIGH_INACTIVE;
1317
1318 /* Associate the neigh to mac */
1319 zmac = zvni_mac_lookup(zvni, mac);
1320 if (zmac)
1321 listnode_add_sort(zmac->neigh_list, n);
1322
1323 return n;
1324 }
1325
1326 /*
1327 * Delete neighbor entry.
1328 */
1329 static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n)
1330 {
1331 zebra_neigh_t *tmp_n;
1332 zebra_mac_t *zmac = NULL;
1333
1334 zmac = zvni_mac_lookup(zvni, &n->emac);
1335 if (zmac)
1336 listnode_delete(zmac->neigh_list, n);
1337
1338 /* Free the VNI hash entry and allocated memory. */
1339 tmp_n = hash_release(zvni->neigh_table, n);
1340 if (tmp_n)
1341 XFREE(MTYPE_NEIGH, tmp_n);
1342
1343 return 0;
1344 }
1345
1346 /*
1347 * Free neighbor hash entry (callback)
1348 */
1349 static void zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg)
1350 {
1351 struct neigh_walk_ctx *wctx = arg;
1352 zebra_neigh_t *n = backet->data;
1353
1354 if (((wctx->flags & DEL_LOCAL_NEIGH) && (n->flags & ZEBRA_NEIGH_LOCAL))
1355 || ((wctx->flags & DEL_REMOTE_NEIGH)
1356 && (n->flags & ZEBRA_NEIGH_REMOTE))
1357 || ((wctx->flags & DEL_REMOTE_NEIGH_FROM_VTEP)
1358 && (n->flags & ZEBRA_NEIGH_REMOTE)
1359 && IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) {
1360 if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL))
1361 zvni_neigh_send_del_to_client(wctx->zvni->vni, &n->ip,
1362 &n->emac, 0);
1363
1364 if (wctx->uninstall)
1365 zvni_neigh_uninstall(wctx->zvni, n);
1366
1367 zvni_neigh_del(wctx->zvni, n);
1368 }
1369
1370 return;
1371 }
1372
1373 /*
1374 * Delete all neighbor entries from specific VTEP for a particular VNI.
1375 */
1376 static void zvni_neigh_del_from_vtep(zebra_vni_t *zvni, int uninstall,
1377 struct in_addr *r_vtep_ip)
1378 {
1379 struct neigh_walk_ctx wctx;
1380
1381 if (!zvni->neigh_table)
1382 return;
1383
1384 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
1385 wctx.zvni = zvni;
1386 wctx.uninstall = uninstall;
1387 wctx.flags = DEL_REMOTE_NEIGH_FROM_VTEP;
1388 wctx.r_vtep_ip = *r_vtep_ip;
1389
1390 hash_iterate(zvni->neigh_table, zvni_neigh_del_hash_entry, &wctx);
1391 }
1392
1393 /*
1394 * Delete all neighbor entries for this VNI.
1395 */
1396 static void zvni_neigh_del_all(zebra_vni_t *zvni, int uninstall, int upd_client,
1397 uint32_t flags)
1398 {
1399 struct neigh_walk_ctx wctx;
1400
1401 if (!zvni->neigh_table)
1402 return;
1403
1404 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
1405 wctx.zvni = zvni;
1406 wctx.uninstall = uninstall;
1407 wctx.upd_client = upd_client;
1408 wctx.flags = flags;
1409
1410 hash_iterate(zvni->neigh_table, zvni_neigh_del_hash_entry, &wctx);
1411 }
1412
1413 /*
1414 * Look up neighbor hash entry.
1415 */
1416 static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip)
1417 {
1418 zebra_neigh_t tmp;
1419 zebra_neigh_t *n;
1420
1421 memset(&tmp, 0, sizeof(tmp));
1422 memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
1423 n = hash_lookup(zvni->neigh_table, &tmp);
1424
1425 return n;
1426 }
1427
1428 /* Process all neigh associated to a mac upon local mac add event */
1429 static void zvni_process_neigh_on_local_mac_add(zebra_vni_t *zvni,
1430 zebra_mac_t *zmac)
1431 {
1432 zebra_neigh_t *n = NULL;
1433 struct listnode *node = NULL;
1434 char buf[ETHER_ADDR_STRLEN];
1435 char buf2[INET6_ADDRSTRLEN];
1436
1437 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
1438 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
1439 /* MAC is learnt locally, program all inactive neigh
1440 * pointing to this mac */
1441 if (IS_ZEBRA_NEIGH_INACTIVE(n)) {
1442 if (IS_ZEBRA_DEBUG_VXLAN)
1443 zlog_debug(
1444 "neigh %s (MAC %s) on L2-VNI %u is now ACTIVE",
1445 ipaddr2str(&n->ip, buf2,
1446 sizeof(buf2)),
1447 prefix_mac2str(&n->emac, buf,
1448 sizeof(buf)),
1449 zvni->vni);
1450
1451 ZEBRA_NEIGH_SET_ACTIVE(n);
1452 zvni_neigh_send_add_to_client(
1453 zvni->vni, &n->ip, &n->emac, n->flags);
1454 } else {
1455 if (IS_ZEBRA_DEBUG_VXLAN)
1456 zlog_debug(
1457 "neigh %s (MAC %s) on VNI %u should NOT be ACTIVE",
1458 ipaddr2str(&n->ip, buf2,
1459 sizeof(buf2)),
1460 prefix_mac2str(&n->emac, buf,
1461 sizeof(buf)),
1462 zvni->vni);
1463 }
1464 } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
1465 /* TODO: assume the neigh has moved too ?? */
1466 }
1467 }
1468 }
1469
1470 /* Process all neigh associated to a mac upon local mac del event */
1471 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t *zvni,
1472 zebra_mac_t *zmac)
1473 {
1474 zebra_neigh_t *n = NULL;
1475 struct listnode *node = NULL;
1476 char buf[ETHER_ADDR_STRLEN];
1477 char buf2[INET6_ADDRSTRLEN];
1478
1479 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
1480 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
1481 if (IS_ZEBRA_NEIGH_ACTIVE(n)) {
1482 if (IS_ZEBRA_DEBUG_VXLAN)
1483 zlog_debug(
1484 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1485 ipaddr2str(&n->ip, buf2,
1486 sizeof(buf2)),
1487 prefix_mac2str(&n->emac, buf,
1488 sizeof(buf)),
1489 zvni->vni);
1490
1491 ZEBRA_NEIGH_SET_INACTIVE(n);
1492 zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
1493 &n->emac, 0);
1494 }
1495 } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
1496 if (IS_ZEBRA_DEBUG_VXLAN)
1497 zlog_err(
1498 "local MAC %s getting deleted on VNI %u has remote neigh %s",
1499 prefix_mac2str(&n->emac, buf,
1500 sizeof(buf)),
1501 zvni->vni,
1502 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
1503 }
1504 }
1505 }
1506
1507 /* process all neigh associated to a mac entry upon remote mac add */
1508 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t *zvni,
1509 zebra_mac_t *zmac)
1510 {
1511 zebra_neigh_t *n = NULL;
1512 struct listnode *node = NULL;
1513 char buf[ETHER_ADDR_STRLEN];
1514 char buf2[INET6_ADDRSTRLEN];
1515
1516 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
1517 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
1518 if (IS_ZEBRA_NEIGH_ACTIVE(n)) {
1519 if (IS_ZEBRA_DEBUG_VXLAN)
1520 zlog_debug(
1521 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1522 ipaddr2str(&n->ip, buf2,
1523 sizeof(buf2)),
1524 prefix_mac2str(&n->emac, buf,
1525 sizeof(buf)),
1526 zvni->vni);
1527
1528 ZEBRA_NEIGH_SET_INACTIVE(n);
1529 zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
1530 &n->emac, 0);
1531 }
1532 }
1533 }
1534 }
1535
1536 /* process all neigh associated to mac entry upon remote mac del */
1537 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t *zvni,
1538 zebra_mac_t *zmac)
1539 {
1540 zebra_neigh_t *n = NULL;
1541 struct listnode *node = NULL;
1542 char buf[ETHER_ADDR_STRLEN];
1543 char buf2[INET6_ADDRSTRLEN];
1544
1545 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
1546 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
1547 if (IS_ZEBRA_DEBUG_VXLAN)
1548 zlog_err(
1549 "remote MAC %s getting deleted on VNI %u has local neigh %s",
1550 prefix_mac2str(&n->emac, buf,
1551 sizeof(buf)),
1552 zvni->vni,
1553 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
1554 }
1555 }
1556 }
1557
1558 /*
1559 * Inform BGP about local neighbor addition.
1560 */
1561 static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
1562 struct ethaddr *macaddr,
1563 uint8_t neigh_flags)
1564 {
1565 uint8_t flags = 0;
1566
1567 if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_DEF_GW))
1568 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
1569 /* Set router flag (R-bit) based on local neigh entry add */
1570 if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_ROUTER_FLAG))
1571 SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
1572
1573 return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
1574 ZEBRA_MACIP_ADD);
1575 }
1576
1577 /*
1578 * Inform BGP about local neighbor deletion.
1579 */
1580 static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
1581 struct ethaddr *macaddr, uint8_t flags)
1582 {
1583 return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
1584 ZEBRA_MACIP_DEL);
1585 }
1586
1587 /*
1588 * Install remote neighbor into the kernel.
1589 */
1590 static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n)
1591 {
1592 struct zebra_if *zif;
1593 struct zebra_l2info_vxlan *vxl;
1594 struct interface *vlan_if;
1595 uint8_t flags;
1596 int ret = 0;
1597
1598 if (!(n->flags & ZEBRA_NEIGH_REMOTE))
1599 return 0;
1600
1601 zif = zvni->vxlan_if->info;
1602 if (!zif)
1603 return -1;
1604 vxl = &zif->l2info.vxl;
1605
1606 vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
1607 if (!vlan_if)
1608 return -1;
1609 #ifdef GNU_LINUX
1610 flags = NTF_EXT_LEARNED;
1611 if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
1612 flags |= NTF_ROUTER;
1613 ret = kernel_add_neigh(vlan_if, &n->ip, &n->emac, flags);
1614 #endif
1615 return ret;
1616 }
1617
1618 /*
1619 * Uninstall remote neighbor from the kernel.
1620 */
1621 static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n)
1622 {
1623 struct zebra_if *zif;
1624 struct zebra_l2info_vxlan *vxl;
1625 struct interface *vlan_if;
1626
1627 if (!(n->flags & ZEBRA_NEIGH_REMOTE))
1628 return 0;
1629
1630 if (!zvni->vxlan_if) {
1631 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
1632 zvni->vni, zvni);
1633 return -1;
1634 }
1635
1636 zif = zvni->vxlan_if->info;
1637 if (!zif)
1638 return -1;
1639 vxl = &zif->l2info.vxl;
1640 vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
1641 if (!vlan_if)
1642 return -1;
1643
1644 return kernel_del_neigh(vlan_if, &n->ip);
1645 }
1646
1647 /*
1648 * Install neighbor hash entry - called upon access VLAN change.
1649 */
1650 static void zvni_install_neigh_hash(struct hash_backet *backet, void *ctxt)
1651 {
1652 zebra_neigh_t *n;
1653 struct neigh_walk_ctx *wctx = ctxt;
1654
1655 n = (zebra_neigh_t *)backet->data;
1656 if (!n)
1657 return;
1658
1659 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE))
1660 zvni_neigh_install(wctx->zvni, n);
1661 }
1662
1663 /* Get the VRR interface for SVI if any */
1664 struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp)
1665 {
1666 struct zebra_vrf *zvrf = NULL;
1667 struct interface *tmp_if = NULL;
1668 struct zebra_if *zif = NULL;
1669
1670 zvrf = vrf_info_lookup(ifp->vrf_id);
1671 assert(zvrf);
1672
1673 FOR_ALL_INTERFACES (zvrf->vrf, tmp_if) {
1674 zif = tmp_if->info;
1675 if (!zif)
1676 continue;
1677
1678 if (!IS_ZEBRA_IF_MACVLAN(tmp_if))
1679 continue;
1680
1681 if (zif->link == ifp)
1682 return tmp_if;
1683 }
1684
1685 return NULL;
1686 }
1687
1688 static int zvni_del_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni)
1689 {
1690 struct listnode *cnode = NULL, *cnnode = NULL;
1691 struct connected *c = NULL;
1692 struct ethaddr macaddr;
1693
1694 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
1695
1696 for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
1697 struct ipaddr ip;
1698
1699 memset(&ip, 0, sizeof(struct ipaddr));
1700 if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
1701 continue;
1702
1703 if (c->address->family == AF_INET) {
1704 ip.ipa_type = IPADDR_V4;
1705 memcpy(&(ip.ipaddr_v4), &(c->address->u.prefix4),
1706 sizeof(struct in_addr));
1707 } else if (c->address->family == AF_INET6) {
1708 ip.ipa_type = IPADDR_V6;
1709 memcpy(&(ip.ipaddr_v6), &(c->address->u.prefix6),
1710 sizeof(struct in6_addr));
1711 } else {
1712 continue;
1713 }
1714
1715 zvni_gw_macip_del(ifp, zvni, &ip);
1716 }
1717
1718 return 0;
1719 }
1720
1721 static int zvni_add_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni)
1722 {
1723 struct listnode *cnode = NULL, *cnnode = NULL;
1724 struct connected *c = NULL;
1725 struct ethaddr macaddr;
1726
1727 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
1728
1729 for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
1730 struct ipaddr ip;
1731
1732 memset(&ip, 0, sizeof(struct ipaddr));
1733 if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
1734 continue;
1735
1736 if (c->address->family == AF_INET) {
1737 ip.ipa_type = IPADDR_V4;
1738 memcpy(&(ip.ipaddr_v4), &(c->address->u.prefix4),
1739 sizeof(struct in_addr));
1740 } else if (c->address->family == AF_INET6) {
1741 ip.ipa_type = IPADDR_V6;
1742 memcpy(&(ip.ipaddr_v6), &(c->address->u.prefix6),
1743 sizeof(struct in6_addr));
1744 } else {
1745 continue;
1746 }
1747
1748 zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
1749 }
1750 return 0;
1751 }
1752
1753
1754 static int zvni_advertise_subnet(zebra_vni_t *zvni, struct interface *ifp,
1755 int advertise)
1756 {
1757 struct listnode *cnode = NULL, *cnnode = NULL;
1758 struct connected *c = NULL;
1759 struct ethaddr macaddr;
1760
1761 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
1762
1763 for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
1764 struct prefix p;
1765
1766 memcpy(&p, c->address, sizeof(struct prefix));
1767
1768 /* skip link local address */
1769 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
1770 continue;
1771
1772 apply_mask(&p);
1773 if (advertise)
1774 ip_prefix_send_to_client(ifp->vrf_id, &p,
1775 ZEBRA_IP_PREFIX_ROUTE_ADD);
1776 else
1777 ip_prefix_send_to_client(ifp->vrf_id, &p,
1778 ZEBRA_IP_PREFIX_ROUTE_DEL);
1779 }
1780 return 0;
1781 }
1782
1783 /*
1784 * zvni_gw_macip_add_to_client
1785 */
1786 static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
1787 struct ethaddr *macaddr, struct ipaddr *ip)
1788 {
1789 char buf[ETHER_ADDR_STRLEN];
1790 char buf2[INET6_ADDRSTRLEN];
1791 zebra_neigh_t *n = NULL;
1792 zebra_mac_t *mac = NULL;
1793 struct zebra_if *zif = NULL;
1794 struct zebra_l2info_vxlan *vxl = NULL;
1795
1796 zif = zvni->vxlan_if->info;
1797 if (!zif)
1798 return -1;
1799
1800 vxl = &zif->l2info.vxl;
1801
1802 mac = zvni_mac_lookup(zvni, macaddr);
1803 if (!mac) {
1804 mac = zvni_mac_add(zvni, macaddr);
1805 if (!mac) {
1806 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
1807 prefix_mac2str(macaddr, buf, sizeof(buf)),
1808 ifp->name, ifp->ifindex, vxl->access_vlan);
1809 return -1;
1810 }
1811 }
1812
1813 /* Set "local" forwarding info. */
1814 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
1815 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
1816 SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
1817 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
1818 mac->fwd_info.local.ifindex = ifp->ifindex;
1819 mac->fwd_info.local.vid = vxl->access_vlan;
1820
1821 n = zvni_neigh_lookup(zvni, ip);
1822 if (!n) {
1823 n = zvni_neigh_add(zvni, ip, macaddr);
1824 if (!n) {
1825 zlog_err(
1826 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1827 ipaddr2str(ip, buf2, sizeof(buf2)),
1828 prefix_mac2str(macaddr, buf, sizeof(buf)),
1829 ifp->name, ifp->ifindex, zvni->vni);
1830 return -1;
1831 }
1832 }
1833
1834 /* Set "local" forwarding info. */
1835 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
1836 SET_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW);
1837 /* Set Router flag (R-bit) */
1838 if (ip->ipa_type == IPADDR_V6)
1839 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
1840 memcpy(&n->emac, macaddr, ETH_ALEN);
1841 n->ifindex = ifp->ifindex;
1842
1843 /* Only advertise in BGP if the knob is enabled */
1844 if (!advertise_gw_macip_enabled(zvni))
1845 return 0;
1846
1847 if (IS_ZEBRA_DEBUG_VXLAN)
1848 zlog_debug(
1849 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
1850 ifp->name, ifp->ifindex, zvni->vni,
1851 prefix_mac2str(macaddr, buf, sizeof(buf)),
1852 ipaddr2str(ip, buf2, sizeof(buf2)), n->flags);
1853
1854 zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags);
1855
1856 return 0;
1857 }
1858
1859 /*
1860 * zvni_gw_macip_del_from_client
1861 */
1862 static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
1863 struct ipaddr *ip)
1864 {
1865 char buf1[ETHER_ADDR_STRLEN];
1866 char buf2[INET6_ADDRSTRLEN];
1867 zebra_neigh_t *n = NULL;
1868 zebra_mac_t *mac = NULL;
1869
1870 /* If the neigh entry is not present nothing to do*/
1871 n = zvni_neigh_lookup(zvni, ip);
1872 if (!n)
1873 return 0;
1874
1875 /* mac entry should be present */
1876 mac = zvni_mac_lookup(zvni, &n->emac);
1877 if (!mac) {
1878 zlog_err("MAC %s doesnt exists for neigh %s on VNI %u",
1879 prefix_mac2str(&n->emac, buf1, sizeof(buf1)),
1880 ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
1881 return -1;
1882 }
1883
1884 /* If the entry is not local nothing to do*/
1885 if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL))
1886 return -1;
1887
1888 /* only need to delete the entry from bgp if we sent it before */
1889 if (IS_ZEBRA_DEBUG_VXLAN)
1890 zlog_debug(
1891 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
1892 ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni,
1893 prefix_mac2str(&(n->emac), buf1, sizeof(buf1)),
1894 ipaddr2str(ip, buf2, sizeof(buf2)));
1895
1896 /* Remove neighbor from BGP. */
1897 zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
1898 ZEBRA_MACIP_TYPE_GW);
1899
1900 /* Delete this neighbor entry. */
1901 zvni_neigh_del(zvni, n);
1902
1903 /* see if the mac needs to be deleted as well*/
1904 if (mac)
1905 zvni_deref_ip2mac(zvni, mac, 0);
1906
1907 return 0;
1908 }
1909
1910 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet *backet,
1911 void *ctxt)
1912 {
1913 zebra_vni_t *zvni = NULL;
1914 struct zebra_if *zif = NULL;
1915 struct zebra_l2info_vxlan zl2_info;
1916 struct interface *vlan_if = NULL;
1917 struct interface *vrr_if = NULL;
1918 struct interface *ifp;
1919
1920 /* Add primary SVI MAC*/
1921 zvni = (zebra_vni_t *)backet->data;
1922 if (!zvni)
1923 return;
1924
1925 ifp = zvni->vxlan_if;
1926 if (!ifp)
1927 return;
1928 zif = ifp->info;
1929
1930 /* If down or not mapped to a bridge, we're done. */
1931 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
1932 return;
1933
1934 zl2_info = zif->l2info.vxl;
1935
1936 vlan_if =
1937 zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
1938 if (!vlan_if)
1939 return;
1940
1941 /* Del primary MAC-IP */
1942 zvni_del_macip_for_intf(vlan_if, zvni);
1943
1944 /* Del VRR MAC-IP - if any*/
1945 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
1946 if (vrr_if)
1947 zvni_del_macip_for_intf(vrr_if, zvni);
1948
1949 return;
1950 }
1951
1952 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
1953 void *ctxt)
1954 {
1955 zebra_vni_t *zvni = NULL;
1956 struct zebra_if *zif = NULL;
1957 struct zebra_l2info_vxlan zl2_info;
1958 struct interface *vlan_if = NULL;
1959 struct interface *vrr_if = NULL;
1960 struct interface *ifp = NULL;
1961
1962 zvni = (zebra_vni_t *)backet->data;
1963 if (!zvni)
1964 return;
1965
1966 ifp = zvni->vxlan_if;
1967 if (!ifp)
1968 return;
1969 zif = ifp->info;
1970
1971 /* If down or not mapped to a bridge, we're done. */
1972 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
1973 return;
1974 zl2_info = zif->l2info.vxl;
1975
1976 vlan_if =
1977 zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
1978 if (!vlan_if)
1979 return;
1980
1981 /* Add primary SVI MAC-IP */
1982 zvni_add_macip_for_intf(vlan_if, zvni);
1983
1984 /* Add VRR MAC-IP - if any*/
1985 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
1986 if (vrr_if)
1987 zvni_add_macip_for_intf(vrr_if, zvni);
1988
1989 return;
1990 }
1991
1992 static int zvni_local_neigh_update(zebra_vni_t *zvni,
1993 struct interface *ifp,
1994 struct ipaddr *ip,
1995 struct ethaddr *macaddr,
1996 uint8_t router_flag)
1997 {
1998 char buf[ETHER_ADDR_STRLEN];
1999 char buf2[INET6_ADDRSTRLEN];
2000 zebra_neigh_t *n = NULL;
2001 zebra_mac_t *zmac = NULL, *old_zmac = NULL;
2002
2003 /* create a dummy MAC if the MAC is not already present */
2004 zmac = zvni_mac_lookup(zvni, macaddr);
2005 if (!zmac) {
2006 if (IS_ZEBRA_DEBUG_VXLAN)
2007 zlog_debug(
2008 "AUTO MAC %s created for neigh %s on VNI %u",
2009 prefix_mac2str(macaddr, buf, sizeof(buf)),
2010 ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
2011
2012 zmac = zvni_mac_add(zvni, macaddr);
2013 if (!zmac) {
2014 zlog_warn("Failed to add MAC %s VNI %u",
2015 prefix_mac2str(macaddr, buf, sizeof(buf)),
2016 zvni->vni);
2017 return -1;
2018 }
2019
2020 memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
2021 memset(&zmac->flags, 0, sizeof(uint32_t));
2022 SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO);
2023 }
2024
2025 /* If same entry already exists, it might be a change or it might be a
2026 * move from remote to local.
2027 */
2028 n = zvni_neigh_lookup(zvni, ip);
2029 if (n) {
2030 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
2031 if (memcmp(n->emac.octet, macaddr->octet,
2032 ETH_ALEN) == 0) {
2033 /* Update any params and return - client doesn't
2034 * care about a purely local change.
2035 */
2036 n->ifindex = ifp->ifindex;
2037 return 0;
2038 }
2039
2040 /* If the MAC has changed,
2041 * need to issue a delete first
2042 * as this means a different MACIP route.
2043 * Also, need to do some unlinking/relinking.
2044 */
2045 zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
2046 &n->emac, 0);
2047 old_zmac = zvni_mac_lookup(zvni, &n->emac);
2048 if (old_zmac) {
2049 listnode_delete(old_zmac->neigh_list, n);
2050 zvni_deref_ip2mac(zvni, old_zmac, 0);
2051 }
2052
2053 /* Update the forwarding info. */
2054 n->ifindex = ifp->ifindex;
2055 memcpy(&n->emac, macaddr, ETH_ALEN);
2056
2057 /* Link to new MAC */
2058 listnode_add_sort(zmac->neigh_list, n);
2059
2060 } else
2061 /* Neighbor has moved from remote to local. */
2062 {
2063 /* If MAC has changed, do the unlink/link */
2064 if (memcmp(n->emac.octet, macaddr->octet,
2065 ETH_ALEN) != 0) {
2066 old_zmac = zvni_mac_lookup(zvni, &n->emac);
2067 if (old_zmac) {
2068 listnode_delete(old_zmac->neigh_list,
2069 n);
2070 zvni_deref_ip2mac(zvni, old_zmac, 0);
2071 }
2072
2073 /* Link to new MAC */
2074 memcpy(&n->emac, macaddr, ETH_ALEN);
2075 listnode_add_sort(zmac->neigh_list, n);
2076 }
2077
2078 /* Mark appropriately */
2079 UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
2080 n->r_vtep_ip.s_addr = 0;
2081 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
2082 n->ifindex = ifp->ifindex;
2083 }
2084 } else {
2085 /* New neighbor - create */
2086 n = zvni_neigh_add(zvni, ip, macaddr);
2087 if (!n) {
2088 zlog_err(
2089 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2090 ipaddr2str(ip, buf2, sizeof(buf2)),
2091 prefix_mac2str(macaddr, buf, sizeof(buf)),
2092 ifp->name, ifp->ifindex, zvni->vni);
2093 return -1;
2094 }
2095 /* Set "local" forwarding info. */
2096 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
2097 n->ifindex = ifp->ifindex;
2098 }
2099
2100 /* Before we program this in BGP, we need to check if MAC is locally
2101 * learnt as well
2102 */
2103 if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
2104 if (IS_ZEBRA_DEBUG_VXLAN)
2105 zlog_debug(
2106 "Skipping neigh %s add to client as MAC %s is not local on VNI %u",
2107 ipaddr2str(ip, buf2, sizeof(buf2)),
2108 prefix_mac2str(macaddr, buf, sizeof(buf)),
2109 zvni->vni);
2110
2111 return 0;
2112 }
2113
2114 /*Set router flag (R-bit) */
2115 if (router_flag)
2116 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
2117
2118 /* Inform BGP. */
2119 if (IS_ZEBRA_DEBUG_VXLAN)
2120 zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u with flags 0x%x",
2121 ipaddr2str(ip, buf2, sizeof(buf2)),
2122 prefix_mac2str(macaddr, buf, sizeof(buf)),
2123 zvni->vni, n->flags);
2124 ZEBRA_NEIGH_SET_ACTIVE(n);
2125
2126 return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags);
2127 }
2128
2129 static int zvni_remote_neigh_update(zebra_vni_t *zvni,
2130 struct interface *ifp,
2131 struct ipaddr *ip,
2132 struct ethaddr *macaddr,
2133 uint16_t state)
2134 {
2135 char buf[ETHER_ADDR_STRLEN];
2136 char buf2[INET6_ADDRSTRLEN];
2137 zebra_neigh_t *n = NULL;
2138 zebra_mac_t *zmac = NULL;
2139
2140 /* If the neighbor is unknown, there is no further action. */
2141 n = zvni_neigh_lookup(zvni, ip);
2142 if (!n)
2143 return 0;
2144
2145 /* If a remote entry, see if it needs to be refreshed */
2146 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
2147 #ifdef GNU_LINUX
2148 if (state & NUD_STALE)
2149 zvni_neigh_install(zvni, n);
2150 #endif
2151 } else {
2152 /* We got a "remote" neighbor notification for an entry
2153 * we think is local. This can happen in a multihoming
2154 * scenario - but only if the MAC is already "remote".
2155 * Just mark our entry as "remote".
2156 */
2157 zmac = zvni_mac_lookup(zvni, macaddr);
2158 if (!zmac || !CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)) {
2159 zlog_err("Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
2160 ipaddr2str(&n->ip, buf2, sizeof(buf2)),
2161 prefix_mac2str(macaddr, buf, sizeof(buf)),
2162 zvni->vni);
2163 return -1;
2164 }
2165
2166 UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
2167 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
2168 n->r_vtep_ip = zmac->fwd_info.r_vtep_ip;
2169 }
2170
2171 return 0;
2172 }
2173
2174 /*
2175 * Make hash key for MAC.
2176 */
2177 static unsigned int mac_hash_keymake(void *p)
2178 {
2179 zebra_mac_t *pmac = p;
2180 const void *pnt = (void *)pmac->macaddr.octet;
2181
2182 return jhash(pnt, ETH_ALEN, 0xa5a5a55a);
2183 }
2184
2185 /*
2186 * Compare two MAC addresses.
2187 */
2188 static int mac_cmp(const void *p1, const void *p2)
2189 {
2190 const zebra_mac_t *pmac1 = p1;
2191 const zebra_mac_t *pmac2 = p2;
2192
2193 if (pmac1 == NULL && pmac2 == NULL)
2194 return 1;
2195
2196 if (pmac1 == NULL || pmac2 == NULL)
2197 return 0;
2198
2199 return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETH_ALEN)
2200 == 0);
2201 }
2202
2203 /*
2204 * Callback to allocate MAC hash entry.
2205 */
2206 static void *zvni_mac_alloc(void *p)
2207 {
2208 const zebra_mac_t *tmp_mac = p;
2209 zebra_mac_t *mac;
2210
2211 mac = XCALLOC(MTYPE_MAC, sizeof(zebra_mac_t));
2212 *mac = *tmp_mac;
2213
2214 return ((void *)mac);
2215 }
2216
2217 /*
2218 * Add MAC entry.
2219 */
2220 static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr)
2221 {
2222 zebra_mac_t tmp_mac;
2223 zebra_mac_t *mac = NULL;
2224
2225 memset(&tmp_mac, 0, sizeof(zebra_mac_t));
2226 memcpy(&tmp_mac.macaddr, macaddr, ETH_ALEN);
2227 mac = hash_get(zvni->mac_table, &tmp_mac, zvni_mac_alloc);
2228 assert(mac);
2229
2230 mac->neigh_list = list_new();
2231 mac->neigh_list->cmp = (int (*)(void *, void *))neigh_cmp;
2232
2233 return mac;
2234 }
2235
2236 /*
2237 * Delete MAC entry.
2238 */
2239 static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac)
2240 {
2241 zebra_mac_t *tmp_mac;
2242
2243 list_delete_and_null(&mac->neigh_list);
2244
2245 /* Free the VNI hash entry and allocated memory. */
2246 tmp_mac = hash_release(zvni->mac_table, mac);
2247 if (tmp_mac)
2248 XFREE(MTYPE_MAC, tmp_mac);
2249
2250 return 0;
2251 }
2252
2253 /*
2254 * Free MAC hash entry (callback)
2255 */
2256 static void zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg)
2257 {
2258 struct mac_walk_ctx *wctx = arg;
2259 zebra_mac_t *mac = backet->data;
2260
2261 if (((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL))
2262 || ((wctx->flags & DEL_REMOTE_MAC)
2263 && (mac->flags & ZEBRA_MAC_REMOTE))
2264 || ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP)
2265 && (mac->flags & ZEBRA_MAC_REMOTE)
2266 && IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
2267 &wctx->r_vtep_ip))) {
2268 if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
2269 zvni_mac_send_del_to_client(wctx->zvni->vni,
2270 &mac->macaddr, mac->flags);
2271 }
2272
2273 if (wctx->uninstall)
2274 zvni_mac_uninstall(wctx->zvni, mac, 0);
2275
2276 zvni_mac_del(wctx->zvni, mac);
2277 }
2278
2279 return;
2280 }
2281
2282 /*
2283 * Delete all MAC entries from specific VTEP for a particular VNI.
2284 */
2285 static void zvni_mac_del_from_vtep(zebra_vni_t *zvni, int uninstall,
2286 struct in_addr *r_vtep_ip)
2287 {
2288 struct mac_walk_ctx wctx;
2289
2290 if (!zvni->mac_table)
2291 return;
2292
2293 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
2294 wctx.zvni = zvni;
2295 wctx.uninstall = uninstall;
2296 wctx.flags = DEL_REMOTE_MAC_FROM_VTEP;
2297 wctx.r_vtep_ip = *r_vtep_ip;
2298
2299 hash_iterate(zvni->mac_table, zvni_mac_del_hash_entry, &wctx);
2300 }
2301
2302 /*
2303 * Delete all MAC entries for this VNI.
2304 */
2305 static void zvni_mac_del_all(zebra_vni_t *zvni, int uninstall, int upd_client,
2306 uint32_t flags)
2307 {
2308 struct mac_walk_ctx wctx;
2309
2310 if (!zvni->mac_table)
2311 return;
2312
2313 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
2314 wctx.zvni = zvni;
2315 wctx.uninstall = uninstall;
2316 wctx.upd_client = upd_client;
2317 wctx.flags = flags;
2318
2319 hash_iterate(zvni->mac_table, zvni_mac_del_hash_entry, &wctx);
2320 }
2321
2322 /*
2323 * Look up MAC hash entry.
2324 */
2325 static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *mac)
2326 {
2327 zebra_mac_t tmp;
2328 zebra_mac_t *pmac;
2329
2330 memset(&tmp, 0, sizeof(tmp));
2331 memcpy(&tmp.macaddr, mac, ETH_ALEN);
2332 pmac = hash_lookup(zvni->mac_table, &tmp);
2333
2334 return pmac;
2335 }
2336
2337 /*
2338 * Inform BGP about local MAC addition.
2339 */
2340 static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
2341 uint8_t mac_flags)
2342 {
2343 uint8_t flags = 0;
2344
2345 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY))
2346 SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
2347 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW))
2348 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
2349
2350 return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
2351 ZEBRA_MACIP_ADD);
2352 }
2353
2354 /*
2355 * Inform BGP about local MAC deletion.
2356 */
2357 static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr,
2358 uint8_t mac_flags)
2359 {
2360 uint8_t flags = 0;
2361
2362 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY))
2363 SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
2364 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW))
2365 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
2366
2367 return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
2368 ZEBRA_MACIP_DEL);
2369 }
2370
2371 /*
2372 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2373 * notifications, to see if they are of interest.
2374 */
2375 static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
2376 struct interface *br_if, vlanid_t vid)
2377 {
2378 struct zebra_ns *zns;
2379 struct route_node *rn;
2380 struct interface *tmp_if = NULL;
2381 struct zebra_if *zif;
2382 struct zebra_l2info_bridge *br;
2383 struct zebra_l2info_vxlan *vxl = NULL;
2384 uint8_t bridge_vlan_aware;
2385 zebra_vni_t *zvni;
2386 int found = 0;
2387
2388 /* Determine if bridge is VLAN-aware or not */
2389 zif = br_if->info;
2390 assert(zif);
2391 br = &zif->l2info.br;
2392 bridge_vlan_aware = br->vlan_aware;
2393
2394 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2395 /* TODO: Optimize with a hash. */
2396 zns = zebra_ns_lookup(NS_DEFAULT);
2397 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
2398 tmp_if = (struct interface *)rn->info;
2399 if (!tmp_if)
2400 continue;
2401 zif = tmp_if->info;
2402 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
2403 continue;
2404 if (!if_is_operative(tmp_if))
2405 continue;
2406 vxl = &zif->l2info.vxl;
2407
2408 if (zif->brslave_info.br_if != br_if)
2409 continue;
2410
2411 if (!bridge_vlan_aware || vxl->access_vlan == vid) {
2412 found = 1;
2413 break;
2414 }
2415 }
2416
2417 if (!found)
2418 return NULL;
2419
2420 zvni = zvni_lookup(vxl->vni);
2421 return zvni;
2422 }
2423
2424 /*
2425 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2426 * neighbor notifications, to see if they are of interest.
2427 */
2428 static zebra_vni_t *zvni_from_svi(struct interface *ifp,
2429 struct interface *br_if)
2430 {
2431 struct zebra_ns *zns;
2432 struct route_node *rn;
2433 struct interface *tmp_if = NULL;
2434 struct zebra_if *zif;
2435 struct zebra_l2info_bridge *br;
2436 struct zebra_l2info_vxlan *vxl = NULL;
2437 uint8_t bridge_vlan_aware;
2438 vlanid_t vid = 0;
2439 zebra_vni_t *zvni;
2440 int found = 0;
2441
2442 if (!br_if)
2443 return NULL;
2444
2445 /* Make sure the linked interface is a bridge. */
2446 if (!IS_ZEBRA_IF_BRIDGE(br_if))
2447 return NULL;
2448
2449 /* Determine if bridge is VLAN-aware or not */
2450 zif = br_if->info;
2451 assert(zif);
2452 br = &zif->l2info.br;
2453 bridge_vlan_aware = br->vlan_aware;
2454 if (bridge_vlan_aware) {
2455 struct zebra_l2info_vlan *vl;
2456
2457 if (!IS_ZEBRA_IF_VLAN(ifp))
2458 return NULL;
2459
2460 zif = ifp->info;
2461 assert(zif);
2462 vl = &zif->l2info.vl;
2463 vid = vl->vid;
2464 }
2465
2466 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2467 /* TODO: Optimize with a hash. */
2468 zns = zebra_ns_lookup(NS_DEFAULT);
2469 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
2470 tmp_if = (struct interface *)rn->info;
2471 if (!tmp_if)
2472 continue;
2473 zif = tmp_if->info;
2474 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
2475 continue;
2476 if (!if_is_operative(tmp_if))
2477 continue;
2478 vxl = &zif->l2info.vxl;
2479
2480 if (zif->brslave_info.br_if != br_if)
2481 continue;
2482
2483 if (!bridge_vlan_aware || vxl->access_vlan == vid) {
2484 found = 1;
2485 break;
2486 }
2487 }
2488
2489 if (!found)
2490 return NULL;
2491
2492 zvni = zvni_lookup(vxl->vni);
2493 return zvni;
2494 }
2495
2496 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
2497 * of two cases:
2498 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
2499 * linked to the bridge
2500 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
2501 * itself
2502 */
2503 static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
2504 {
2505 struct zebra_ns *zns;
2506 struct route_node *rn;
2507 struct interface *tmp_if = NULL;
2508 struct zebra_if *zif;
2509 struct zebra_l2info_bridge *br;
2510 struct zebra_l2info_vlan *vl;
2511 uint8_t bridge_vlan_aware;
2512 int found = 0;
2513
2514 /* Defensive check, caller expected to invoke only with valid bridge. */
2515 if (!br_if)
2516 return NULL;
2517
2518 /* Determine if bridge is VLAN-aware or not */
2519 zif = br_if->info;
2520 assert(zif);
2521 br = &zif->l2info.br;
2522 bridge_vlan_aware = br->vlan_aware;
2523
2524 /* Check oper status of the SVI. */
2525 if (!bridge_vlan_aware)
2526 return if_is_operative(br_if) ? br_if : NULL;
2527
2528 /* Identify corresponding VLAN interface. */
2529 /* TODO: Optimize with a hash. */
2530 zns = zebra_ns_lookup(NS_DEFAULT);
2531 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
2532 tmp_if = (struct interface *)rn->info;
2533 /* Check oper status of the SVI. */
2534 if (!tmp_if || !if_is_operative(tmp_if))
2535 continue;
2536 zif = tmp_if->info;
2537 if (!zif || zif->zif_type != ZEBRA_IF_VLAN
2538 || zif->link != br_if)
2539 continue;
2540 vl = (struct zebra_l2info_vlan *)&zif->l2info.vl;
2541
2542 if (vl->vid == vid) {
2543 found = 1;
2544 break;
2545 }
2546 }
2547
2548 return found ? tmp_if : NULL;
2549 }
2550
2551 /*
2552 * Install remote MAC into the kernel.
2553 */
2554 static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
2555 {
2556 struct zebra_if *zif;
2557 struct zebra_l2info_vxlan *vxl;
2558 uint8_t sticky;
2559
2560 if (!(mac->flags & ZEBRA_MAC_REMOTE))
2561 return 0;
2562
2563 zif = zvni->vxlan_if->info;
2564 if (!zif)
2565 return -1;
2566 vxl = &zif->l2info.vxl;
2567
2568 sticky = CHECK_FLAG(mac->flags,
2569 (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW)) ? 1 : 0;
2570
2571 return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
2572 mac->fwd_info.r_vtep_ip, sticky);
2573 }
2574
2575 /*
2576 * Uninstall remote MAC from the kernel. In the scenario where the MAC
2577 * moves to remote, we have to uninstall any existing local entry first.
2578 */
2579 static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac, int local)
2580 {
2581 struct zebra_if *zif;
2582 struct zebra_l2info_vxlan *vxl;
2583 struct in_addr vtep_ip = {.s_addr = 0};
2584 struct zebra_ns *zns;
2585 struct interface *ifp;
2586
2587 if (!local && !(mac->flags & ZEBRA_MAC_REMOTE))
2588 return 0;
2589
2590 if (!zvni->vxlan_if) {
2591 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2592 zvni->vni, zvni);
2593 return -1;
2594 }
2595
2596 zif = zvni->vxlan_if->info;
2597 if (!zif)
2598 return -1;
2599 vxl = &zif->l2info.vxl;
2600
2601 if (local) {
2602 zns = zebra_ns_lookup(NS_DEFAULT);
2603 ifp = if_lookup_by_index_per_ns(zns,
2604 mac->fwd_info.local.ifindex);
2605 if (!ifp) // unexpected
2606 return -1;
2607 } else {
2608 ifp = zvni->vxlan_if;
2609 vtep_ip = mac->fwd_info.r_vtep_ip;
2610 }
2611
2612 return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip,
2613 local);
2614 }
2615
2616 /*
2617 * Install MAC hash entry - called upon access VLAN change.
2618 */
2619 static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt)
2620 {
2621 zebra_mac_t *mac;
2622 struct mac_walk_ctx *wctx = ctxt;
2623
2624 mac = (zebra_mac_t *)backet->data;
2625 if (!mac)
2626 return;
2627
2628 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
2629 zvni_mac_install(wctx->zvni, mac);
2630 }
2631
2632 /*
2633 * Decrement neighbor refcount of MAC; uninstall and free it if
2634 * appropriate.
2635 */
2636 static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac,
2637 int uninstall)
2638 {
2639 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)
2640 || !list_isempty(mac->neigh_list))
2641 return;
2642
2643 if (uninstall)
2644 zvni_mac_uninstall(zvni, mac, 0);
2645
2646 zvni_mac_del(zvni, mac);
2647 }
2648
2649 /*
2650 * Read and populate local MACs and neighbors corresponding to this VNI.
2651 */
2652 static void zvni_read_mac_neigh(zebra_vni_t *zvni, struct interface *ifp)
2653 {
2654 struct zebra_ns *zns;
2655 struct zebra_if *zif;
2656 struct interface *vlan_if;
2657 struct zebra_l2info_vxlan *vxl;
2658 struct interface *vrr_if;
2659
2660 zif = ifp->info;
2661 vxl = &zif->l2info.vxl;
2662 zns = zebra_ns_lookup(NS_DEFAULT);
2663
2664 if (IS_ZEBRA_DEBUG_VXLAN)
2665 zlog_debug(
2666 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2667 ifp->name, ifp->ifindex, zvni->vni,
2668 zif->brslave_info.bridge_ifindex);
2669
2670 macfdb_read_for_bridge(zns, ifp, zif->brslave_info.br_if);
2671 vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
2672 if (vlan_if) {
2673
2674 /* Add SVI MAC-IP */
2675 zvni_add_macip_for_intf(vlan_if, zvni);
2676
2677 /* Add VRR MAC-IP - if any*/
2678 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
2679 if (vrr_if)
2680 zvni_add_macip_for_intf(vrr_if, zvni);
2681
2682 neigh_read_for_vlan(zns, vlan_if);
2683 }
2684 }
2685
2686 /*
2687 * Hash function for VNI.
2688 */
2689 static unsigned int vni_hash_keymake(void *p)
2690 {
2691 const zebra_vni_t *zvni = p;
2692
2693 return (jhash_1word(zvni->vni, 0));
2694 }
2695
2696 /*
2697 * Compare 2 VNI hash entries.
2698 */
2699 static int vni_hash_cmp(const void *p1, const void *p2)
2700 {
2701 const zebra_vni_t *zvni1 = p1;
2702 const zebra_vni_t *zvni2 = p2;
2703
2704 return (zvni1->vni == zvni2->vni);
2705 }
2706
2707 /*
2708 * Callback to allocate VNI hash entry.
2709 */
2710 static void *zvni_alloc(void *p)
2711 {
2712 const zebra_vni_t *tmp_vni = p;
2713 zebra_vni_t *zvni;
2714
2715 zvni = XCALLOC(MTYPE_ZVNI, sizeof(zebra_vni_t));
2716 zvni->vni = tmp_vni->vni;
2717 return ((void *)zvni);
2718 }
2719
2720 /*
2721 * Look up VNI hash entry.
2722 */
2723 static zebra_vni_t *zvni_lookup(vni_t vni)
2724 {
2725 struct zebra_vrf *zvrf;
2726 zebra_vni_t tmp_vni;
2727 zebra_vni_t *zvni = NULL;
2728
2729 zvrf = vrf_info_lookup(VRF_DEFAULT);
2730 assert(zvrf);
2731 memset(&tmp_vni, 0, sizeof(zebra_vni_t));
2732 tmp_vni.vni = vni;
2733 zvni = hash_lookup(zvrf->vni_table, &tmp_vni);
2734
2735 return zvni;
2736 }
2737
2738 /*
2739 * Add VNI hash entry.
2740 */
2741 static zebra_vni_t *zvni_add(vni_t vni)
2742 {
2743 struct zebra_vrf *zvrf;
2744 zebra_vni_t tmp_zvni;
2745 zebra_vni_t *zvni = NULL;
2746
2747 zvrf = vrf_info_lookup(VRF_DEFAULT);
2748 assert(zvrf);
2749 memset(&tmp_zvni, 0, sizeof(zebra_vni_t));
2750 tmp_zvni.vni = vni;
2751 zvni = hash_get(zvrf->vni_table, &tmp_zvni, zvni_alloc);
2752 assert(zvni);
2753
2754 /* Create hash table for MAC */
2755 zvni->mac_table =
2756 hash_create(mac_hash_keymake, mac_cmp, "Zebra VNI MAC Table");
2757
2758 /* Create hash table for neighbors */
2759 zvni->neigh_table = hash_create(neigh_hash_keymake, neigh_cmp,
2760 "Zebra VNI Neighbor Table");
2761
2762 return zvni;
2763 }
2764
2765 /*
2766 * Delete VNI hash entry.
2767 */
2768 static int zvni_del(zebra_vni_t *zvni)
2769 {
2770 struct zebra_vrf *zvrf;
2771 zebra_vni_t *tmp_zvni;
2772
2773 zvrf = vrf_info_lookup(VRF_DEFAULT);
2774 assert(zvrf);
2775
2776 zvni->vxlan_if = NULL;
2777
2778 /* Free the neighbor hash table. */
2779 hash_free(zvni->neigh_table);
2780 zvni->neigh_table = NULL;
2781
2782 /* Free the MAC hash table. */
2783 hash_free(zvni->mac_table);
2784 zvni->mac_table = NULL;
2785
2786 /* Free the VNI hash entry and allocated memory. */
2787 tmp_zvni = hash_release(zvrf->vni_table, zvni);
2788 if (tmp_zvni)
2789 XFREE(MTYPE_ZVNI, tmp_zvni);
2790
2791 return 0;
2792 }
2793
2794 /*
2795 * Inform BGP about local VNI addition.
2796 */
2797 static int zvni_send_add_to_client(zebra_vni_t *zvni)
2798 {
2799 struct zserv *client;
2800 struct stream *s;
2801
2802 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
2803 /* BGP may not be running. */
2804 if (!client)
2805 return 0;
2806
2807 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
2808
2809 zclient_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT);
2810 stream_putl(s, zvni->vni);
2811 stream_put_in_addr(s, &zvni->local_vtep_ip);
2812 stream_put(s, &zvni->vrf_id, sizeof(vrf_id_t)); /* tenant vrf */
2813
2814 /* Write packet size. */
2815 stream_putw_at(s, 0, stream_get_endp(s));
2816
2817 if (IS_ZEBRA_DEBUG_VXLAN)
2818 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni->vni,
2819 inet_ntoa(zvni->local_vtep_ip),
2820 vrf_id_to_name(zvni->vrf_id),
2821 zebra_route_string(client->proto));
2822
2823 client->vniadd_cnt++;
2824 return zserv_send_message(client, s);
2825 }
2826
2827 /*
2828 * Inform BGP about local VNI deletion.
2829 */
2830 static int zvni_send_del_to_client(vni_t vni)
2831 {
2832 struct zserv *client;
2833 struct stream *s;
2834
2835 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
2836 /* BGP may not be running. */
2837 if (!client)
2838 return 0;
2839
2840 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
2841 stream_reset(s);
2842
2843 zclient_create_header(s, ZEBRA_VNI_DEL, VRF_DEFAULT);
2844 stream_putl(s, vni);
2845
2846 /* Write packet size. */
2847 stream_putw_at(s, 0, stream_get_endp(s));
2848
2849 if (IS_ZEBRA_DEBUG_VXLAN)
2850 zlog_debug("Send VNI_DEL %u to %s", vni,
2851 zebra_route_string(client->proto));
2852
2853 client->vnidel_cnt++;
2854 return zserv_send_message(client, s);
2855 }
2856
2857 /*
2858 * Build the VNI hash table by going over the VxLAN interfaces. This
2859 * is called when EVPN (advertise-all-vni) is enabled.
2860 */
2861 static void zvni_build_hash_table()
2862 {
2863 struct zebra_ns *zns;
2864 struct route_node *rn;
2865 struct interface *ifp;
2866
2867 /* Walk VxLAN interfaces and create VNI hash. */
2868 zns = zebra_ns_lookup(NS_DEFAULT);
2869 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
2870 vni_t vni;
2871 zebra_vni_t *zvni = NULL;
2872 zebra_l3vni_t *zl3vni = NULL;
2873 struct zebra_if *zif;
2874 struct zebra_l2info_vxlan *vxl;
2875
2876 ifp = (struct interface *)rn->info;
2877 if (!ifp)
2878 continue;
2879 zif = ifp->info;
2880 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
2881 continue;
2882
2883 vxl = &zif->l2info.vxl;
2884 vni = vxl->vni;
2885
2886 /* L3-VNI and L2-VNI are handled seperately */
2887 zl3vni = zl3vni_lookup(vni);
2888 if (zl3vni) {
2889
2890 if (IS_ZEBRA_DEBUG_VXLAN)
2891 zlog_debug(
2892 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
2893 ifp->name, ifp->ifindex, vni);
2894
2895 /* associate with vxlan_if */
2896 zl3vni->local_vtep_ip = vxl->vtep_ip;
2897 zl3vni->vxlan_if = ifp;
2898
2899 /*
2900 * we need to associate with SVI.
2901 * we can associate with svi-if only after association
2902 * with vxlan-intf is complete
2903 */
2904 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
2905
2906 if (is_l3vni_oper_up(zl3vni))
2907 zebra_vxlan_process_l3vni_oper_up(zl3vni);
2908
2909 } else {
2910 struct interface *vlan_if = NULL;
2911
2912 if (IS_ZEBRA_DEBUG_VXLAN)
2913 zlog_debug(
2914 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
2915 ifp->name, ifp->ifindex, vni,
2916 inet_ntoa(vxl->vtep_ip));
2917
2918 /* VNI hash entry is not expected to exist. */
2919 zvni = zvni_lookup(vni);
2920 if (zvni) {
2921 zlog_err(
2922 "VNI hash already present for IF %s(%u) L2-VNI %u",
2923 ifp->name, ifp->ifindex, vni);
2924 continue;
2925 }
2926
2927 zvni = zvni_add(vni);
2928 if (!zvni) {
2929 zlog_err(
2930 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
2931 ifp->name, ifp->ifindex, vni);
2932 return;
2933 }
2934
2935 zvni->local_vtep_ip = vxl->vtep_ip;
2936 zvni->vxlan_if = ifp;
2937 vlan_if = zvni_map_to_svi(vxl->access_vlan,
2938 zif->brslave_info.br_if);
2939 if (vlan_if) {
2940 zvni->vrf_id = vlan_if->vrf_id;
2941 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
2942 if (zl3vni)
2943 listnode_add_sort(zl3vni->l2vnis, zvni);
2944 }
2945
2946
2947 /* Inform BGP if intf is up and mapped to bridge. */
2948 if (if_is_operative(ifp) && zif->brslave_info.br_if)
2949 zvni_send_add_to_client(zvni);
2950 }
2951 }
2952 }
2953
2954 /*
2955 * See if remote VTEP matches with prefix.
2956 */
2957 static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep)
2958 {
2959 return (IPV4_ADDR_SAME(vtep_ip, &zvtep->vtep_ip));
2960 }
2961
2962 /*
2963 * Locate remote VTEP in VNI hash table.
2964 */
2965 static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2966 {
2967 zebra_vtep_t *zvtep;
2968
2969 if (!zvni)
2970 return NULL;
2971
2972 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
2973 if (zvni_vtep_match(vtep_ip, zvtep))
2974 break;
2975 }
2976
2977 return zvtep;
2978 }
2979
2980 /*
2981 * Add remote VTEP to VNI hash table.
2982 */
2983 static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip)
2984 {
2985 zebra_vtep_t *zvtep;
2986
2987 zvtep = XCALLOC(MTYPE_ZVNI_VTEP, sizeof(zebra_vtep_t));
2988
2989 zvtep->vtep_ip = *vtep_ip;
2990
2991 if (zvni->vteps)
2992 zvni->vteps->prev = zvtep;
2993 zvtep->next = zvni->vteps;
2994 zvni->vteps = zvtep;
2995
2996 return zvtep;
2997 }
2998
2999 /*
3000 * Remove remote VTEP from VNI hash table.
3001 */
3002 static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep)
3003 {
3004 if (zvtep->next)
3005 zvtep->next->prev = zvtep->prev;
3006 if (zvtep->prev)
3007 zvtep->prev->next = zvtep->next;
3008 else
3009 zvni->vteps = zvtep->next;
3010
3011 zvtep->prev = zvtep->next = NULL;
3012 XFREE(MTYPE_ZVNI_VTEP, zvtep);
3013
3014 return 0;
3015 }
3016
3017 /*
3018 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
3019 * uninstall from kernel if asked to.
3020 */
3021 static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall)
3022 {
3023 zebra_vtep_t *zvtep, *zvtep_next;
3024
3025 if (!zvni)
3026 return -1;
3027
3028 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep_next) {
3029 zvtep_next = zvtep->next;
3030 if (uninstall)
3031 zvni_vtep_uninstall(zvni, &zvtep->vtep_ip);
3032 zvni_vtep_del(zvni, zvtep);
3033 }
3034
3035 return 0;
3036 }
3037
3038 /*
3039 * Install remote VTEP into the kernel.
3040 */
3041 static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip)
3042 {
3043 return kernel_add_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
3044 }
3045
3046 /*
3047 * Uninstall remote VTEP from the kernel.
3048 */
3049 static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip)
3050 {
3051 if (!zvni->vxlan_if) {
3052 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
3053 zvni->vni, zvni);
3054 return -1;
3055 }
3056
3057 return kernel_del_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
3058 }
3059
3060 /*
3061 * Cleanup VNI/VTEP and update kernel
3062 */
3063 static void zvni_cleanup_all(struct hash_backet *backet, void *arg)
3064 {
3065 zebra_vni_t *zvni = NULL;
3066 zebra_l3vni_t *zl3vni = NULL;
3067 struct zebra_vrf *zvrf = (struct zebra_vrf *)arg;
3068
3069 zvni = (zebra_vni_t *)backet->data;
3070 if (!zvni)
3071 return;
3072
3073 /* remove from l3-vni list */
3074 if (zvrf->l3vni)
3075 zl3vni = zl3vni_lookup(zvrf->l3vni);
3076 if (zl3vni)
3077 listnode_delete(zl3vni->l2vnis, zvni);
3078
3079 /* Free up all neighbors and MACs, if any. */
3080 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
3081 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
3082
3083 /* Free up all remote VTEPs, if any. */
3084 zvni_vtep_del_all(zvni, 1);
3085
3086 /* Delete the hash entry. */
3087 zvni_del(zvni);
3088 }
3089
3090 /* cleanup L3VNI */
3091 static void zl3vni_cleanup_all(struct hash_backet *backet, void *args)
3092 {
3093 zebra_l3vni_t *zl3vni = NULL;
3094
3095 zl3vni = (zebra_l3vni_t *)backet->data;
3096 if (!zl3vni)
3097 return;
3098
3099 zebra_vxlan_process_l3vni_oper_down(zl3vni);
3100 }
3101
3102 static void rb_find_or_add_host(struct host_rb_tree_entry *hrbe,
3103 struct prefix *host)
3104 {
3105 struct host_rb_entry lookup;
3106 struct host_rb_entry *hle;
3107
3108 memset(&lookup, 0, sizeof(lookup));
3109 memcpy(&lookup.p, host, sizeof(*host));
3110
3111 hle = RB_FIND(host_rb_tree_entry, hrbe, &lookup);
3112 if (hle)
3113 return;
3114
3115 hle = XCALLOC(MTYPE_HOST_PREFIX, sizeof(struct host_rb_entry));
3116 memcpy(hle, &lookup, sizeof(lookup));
3117
3118 RB_INSERT(host_rb_tree_entry, hrbe, hle);
3119 }
3120
3121 static void rb_delete_host(struct host_rb_tree_entry *hrbe, struct prefix *host)
3122 {
3123 struct host_rb_entry lookup;
3124 struct host_rb_entry *hle;
3125
3126 memset(&lookup, 0, sizeof(lookup));
3127 memcpy(&lookup.p, host, sizeof(*host));
3128
3129 hle = RB_FIND(host_rb_tree_entry, hrbe, &lookup);
3130 if (hle) {
3131 RB_REMOVE(host_rb_tree_entry, hrbe, hle);
3132 XFREE(MTYPE_HOST_PREFIX, hle);
3133 }
3134
3135 return;
3136 }
3137
3138 /*
3139 * Look up MAC hash entry.
3140 */
3141 static zebra_mac_t *zl3vni_rmac_lookup(zebra_l3vni_t *zl3vni,
3142 struct ethaddr *rmac)
3143 {
3144 zebra_mac_t tmp;
3145 zebra_mac_t *pmac;
3146
3147 memset(&tmp, 0, sizeof(tmp));
3148 memcpy(&tmp.macaddr, rmac, ETH_ALEN);
3149 pmac = hash_lookup(zl3vni->rmac_table, &tmp);
3150
3151 return pmac;
3152 }
3153
3154 /*
3155 * Callback to allocate RMAC hash entry.
3156 */
3157 static void *zl3vni_rmac_alloc(void *p)
3158 {
3159 const zebra_mac_t *tmp_rmac = p;
3160 zebra_mac_t *zrmac;
3161
3162 zrmac = XCALLOC(MTYPE_MAC, sizeof(zebra_mac_t));
3163 *zrmac = *tmp_rmac;
3164
3165 return ((void *)zrmac);
3166 }
3167
3168 /*
3169 * Add RMAC entry to l3-vni
3170 */
3171 static zebra_mac_t *zl3vni_rmac_add(zebra_l3vni_t *zl3vni, struct ethaddr *rmac)
3172 {
3173 zebra_mac_t tmp_rmac;
3174 zebra_mac_t *zrmac = NULL;
3175
3176 memset(&tmp_rmac, 0, sizeof(zebra_mac_t));
3177 memcpy(&tmp_rmac.macaddr, rmac, ETH_ALEN);
3178 zrmac = hash_get(zl3vni->rmac_table, &tmp_rmac, zl3vni_rmac_alloc);
3179 assert(zrmac);
3180
3181 RB_INIT(host_rb_tree_entry, &zrmac->host_rb);
3182
3183 SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE);
3184 SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC);
3185
3186 return zrmac;
3187 }
3188
3189 /*
3190 * Delete MAC entry.
3191 */
3192 static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
3193 {
3194 zebra_mac_t *tmp_rmac;
3195 struct host_rb_entry *hle;
3196
3197 while (!RB_EMPTY(host_rb_tree_entry, &zrmac->host_rb)) {
3198 hle = RB_ROOT(host_rb_tree_entry, &zrmac->host_rb);
3199
3200 RB_REMOVE(host_rb_tree_entry, &zrmac->host_rb, hle);
3201 XFREE(MTYPE_HOST_PREFIX, hle);
3202 }
3203
3204 tmp_rmac = hash_release(zl3vni->rmac_table, zrmac);
3205 if (tmp_rmac)
3206 XFREE(MTYPE_MAC, tmp_rmac);
3207
3208 return 0;
3209 }
3210
3211 /*
3212 * Install remote RMAC into the kernel.
3213 */
3214 static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
3215 {
3216 struct zebra_if *zif = NULL;
3217 struct zebra_l2info_vxlan *vxl = NULL;
3218
3219 if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
3220 || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
3221 return 0;
3222
3223 zif = zl3vni->vxlan_if->info;
3224 if (!zif)
3225 return -1;
3226
3227 vxl = &zif->l2info.vxl;
3228
3229 return kernel_add_mac(zl3vni->vxlan_if, vxl->access_vlan,
3230 &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
3231 }
3232
3233 /*
3234 * Uninstall remote RMAC from the kernel.
3235 */
3236 static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
3237 {
3238 char buf[ETHER_ADDR_STRLEN];
3239 struct zebra_if *zif = NULL;
3240 struct zebra_l2info_vxlan *vxl = NULL;
3241
3242 if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
3243 || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
3244 return 0;
3245
3246 if (!zl3vni->vxlan_if) {
3247 zlog_err(
3248 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
3249 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
3250 zl3vni->vni, zl3vni);
3251 return -1;
3252 }
3253
3254 zif = zl3vni->vxlan_if->info;
3255 if (!zif)
3256 return -1;
3257
3258 vxl = &zif->l2info.vxl;
3259
3260 return kernel_del_mac(zl3vni->vxlan_if, vxl->access_vlan,
3261 &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
3262 }
3263
3264 /* handle rmac add */
3265 static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni, struct ethaddr *rmac,
3266 struct ipaddr *vtep_ip,
3267 struct prefix *host_prefix)
3268 {
3269 char buf[ETHER_ADDR_STRLEN];
3270 char buf1[INET6_ADDRSTRLEN];
3271 zebra_mac_t *zrmac = NULL;
3272
3273 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
3274 if (!zrmac) {
3275
3276 zrmac = zl3vni_rmac_add(zl3vni, rmac);
3277 if (!zrmac) {
3278 zlog_warn(
3279 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
3280 prefix_mac2str(rmac, buf, sizeof(buf)),
3281 zl3vni->vni,
3282 ipaddr2str(vtep_ip, buf1, sizeof(buf1)));
3283 return -1;
3284 }
3285 memset(&zrmac->fwd_info, 0, sizeof(zrmac->fwd_info));
3286 zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
3287
3288 /* install rmac in kernel */
3289 zl3vni_rmac_install(zl3vni, zrmac);
3290 }
3291
3292 rb_find_or_add_host(&zrmac->host_rb, host_prefix);
3293
3294 return 0;
3295 }
3296
3297
3298 /* handle rmac delete */
3299 static void zl3vni_remote_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac,
3300 struct prefix *host_prefix)
3301 {
3302 rb_delete_host(&zrmac->host_rb, host_prefix);
3303
3304 if (RB_EMPTY(host_rb_tree_entry, &zrmac->host_rb)) {
3305 /* uninstall from kernel */
3306 zl3vni_rmac_uninstall(zl3vni, zrmac);
3307
3308 /* del the rmac entry */
3309 zl3vni_rmac_del(zl3vni, zrmac);
3310 }
3311 }
3312
3313 /*
3314 * Look up nh hash entry on a l3-vni.
3315 */
3316 static zebra_neigh_t *zl3vni_nh_lookup(zebra_l3vni_t *zl3vni, struct ipaddr *ip)
3317 {
3318 zebra_neigh_t tmp;
3319 zebra_neigh_t *n;
3320
3321 memset(&tmp, 0, sizeof(tmp));
3322 memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
3323 n = hash_lookup(zl3vni->nh_table, &tmp);
3324
3325 return n;
3326 }
3327
3328
3329 /*
3330 * Callback to allocate NH hash entry on L3-VNI.
3331 */
3332 static void *zl3vni_nh_alloc(void *p)
3333 {
3334 const zebra_neigh_t *tmp_n = p;
3335 zebra_neigh_t *n;
3336
3337 n = XCALLOC(MTYPE_NEIGH, sizeof(zebra_neigh_t));
3338 *n = *tmp_n;
3339
3340 return ((void *)n);
3341 }
3342
3343 /*
3344 * Add neighbor entry.
3345 */
3346 static zebra_neigh_t *zl3vni_nh_add(zebra_l3vni_t *zl3vni, struct ipaddr *ip,
3347 struct ethaddr *mac)
3348 {
3349 zebra_neigh_t tmp_n;
3350 zebra_neigh_t *n = NULL;
3351
3352 memset(&tmp_n, 0, sizeof(zebra_neigh_t));
3353 memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
3354 n = hash_get(zl3vni->nh_table, &tmp_n, zl3vni_nh_alloc);
3355 assert(n);
3356
3357 RB_INIT(host_rb_tree_entry, &n->host_rb);
3358
3359 memcpy(&n->emac, mac, ETH_ALEN);
3360 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
3361 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE_NH);
3362
3363 return n;
3364 }
3365
3366 /*
3367 * Delete neighbor entry.
3368 */
3369 static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
3370 {
3371 zebra_neigh_t *tmp_n;
3372 struct host_rb_entry *hle;
3373
3374 while (!RB_EMPTY(host_rb_tree_entry, &n->host_rb)) {
3375 hle = RB_ROOT(host_rb_tree_entry, &n->host_rb);
3376
3377 RB_REMOVE(host_rb_tree_entry, &n->host_rb, hle);
3378 XFREE(MTYPE_HOST_PREFIX, hle);
3379 }
3380
3381 tmp_n = hash_release(zl3vni->nh_table, n);
3382 if (tmp_n)
3383 XFREE(MTYPE_NEIGH, tmp_n);
3384
3385 return 0;
3386 }
3387
3388 /*
3389 * Install remote nh as neigh into the kernel.
3390 */
3391 static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
3392 {
3393 uint8_t flags;
3394 int ret = 0;
3395
3396 if (!is_l3vni_oper_up(zl3vni))
3397 return -1;
3398
3399 if (!(n->flags & ZEBRA_NEIGH_REMOTE)
3400 || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
3401 return 0;
3402 #ifdef GNU_LINUX
3403 flags = NTF_EXT_LEARNED;
3404 if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
3405 flags |= NTF_ROUTER;
3406 ret = kernel_add_neigh(zl3vni->svi_if, &n->ip, &n->emac, flags);
3407 #endif
3408 return ret;
3409 }
3410
3411 /*
3412 * Uninstall remote nh from the kernel.
3413 */
3414 static int zl3vni_nh_uninstall(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
3415 {
3416 if (!(n->flags & ZEBRA_NEIGH_REMOTE)
3417 || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
3418 return 0;
3419
3420 if (!zl3vni->svi_if || !if_is_operative(zl3vni->svi_if))
3421 return 0;
3422
3423 return kernel_del_neigh(zl3vni->svi_if, &n->ip);
3424 }
3425
3426 /* add remote vtep as a neigh entry */
3427 static int zl3vni_remote_nh_add(zebra_l3vni_t *zl3vni, struct ipaddr *vtep_ip,
3428 struct ethaddr *rmac,
3429 struct prefix *host_prefix)
3430 {
3431 char buf[ETHER_ADDR_STRLEN];
3432 char buf1[INET6_ADDRSTRLEN];
3433 zebra_neigh_t *nh = NULL;
3434
3435 nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
3436 if (!nh) {
3437 nh = zl3vni_nh_add(zl3vni, vtep_ip, rmac);
3438 if (!nh) {
3439
3440 zlog_warn(
3441 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
3442 ipaddr2str(vtep_ip, buf1, sizeof(buf1)),
3443 prefix_mac2str(rmac, buf, sizeof(buf)),
3444 zl3vni->vni);
3445 return -1;
3446 }
3447
3448 /* install the nh neigh in kernel */
3449 zl3vni_nh_install(zl3vni, nh);
3450 }
3451
3452 rb_find_or_add_host(&nh->host_rb, host_prefix);
3453
3454 return 0;
3455 }
3456
3457 /* handle nh neigh delete */
3458 static void zl3vni_remote_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *nh,
3459 struct prefix *host_prefix)
3460 {
3461 rb_delete_host(&nh->host_rb, host_prefix);
3462
3463 if (RB_EMPTY(host_rb_tree_entry, &nh->host_rb)) {
3464 /* uninstall from kernel */
3465 zl3vni_nh_uninstall(zl3vni, nh);
3466
3467 /* delete the nh entry */
3468 zl3vni_nh_del(zl3vni, nh);
3469 }
3470 }
3471
3472 /* handle neigh update from kernel - the only thing of interest is to
3473 * readd stale entries.
3474 */
3475 static int zl3vni_local_nh_add_update(zebra_l3vni_t *zl3vni, struct ipaddr *ip,
3476 uint16_t state)
3477 {
3478 #ifdef GNU_LINUX
3479 zebra_neigh_t *n = NULL;
3480
3481 n = zl3vni_nh_lookup(zl3vni, ip);
3482 if (!n)
3483 return 0;
3484
3485 /* all next hop neigh are remote and installed by frr.
3486 * If the kernel has aged this entry, re-install.
3487 */
3488 if (state & NUD_STALE)
3489 zl3vni_nh_install(zl3vni, n);
3490 #endif
3491 return 0;
3492 }
3493
3494 /* handle neigh delete from kernel */
3495 static int zl3vni_local_nh_del(zebra_l3vni_t *zl3vni, struct ipaddr *ip)
3496 {
3497 zebra_neigh_t *n = NULL;
3498
3499 n = zl3vni_nh_lookup(zl3vni, ip);
3500 if (!n)
3501 return 0;
3502
3503 /* all next hop neigh are remote and installed by frr.
3504 * If we get an age out notification for these neigh entries, we have to
3505 * install it back
3506 */
3507 zl3vni_nh_install(zl3vni, n);
3508
3509 return 0;
3510 }
3511
3512 /*
3513 * Hash function for L3 VNI.
3514 */
3515 static unsigned int l3vni_hash_keymake(void *p)
3516 {
3517 const zebra_l3vni_t *zl3vni = p;
3518
3519 return jhash_1word(zl3vni->vni, 0);
3520 }
3521
3522 /*
3523 * Compare 2 L3 VNI hash entries.
3524 */
3525 static int l3vni_hash_cmp(const void *p1, const void *p2)
3526 {
3527 const zebra_l3vni_t *zl3vni1 = p1;
3528 const zebra_l3vni_t *zl3vni2 = p2;
3529
3530 return (zl3vni1->vni == zl3vni2->vni);
3531 }
3532
3533 /*
3534 * Callback to allocate L3 VNI hash entry.
3535 */
3536 static void *zl3vni_alloc(void *p)
3537 {
3538 zebra_l3vni_t *zl3vni = NULL;
3539 const zebra_l3vni_t *tmp_l3vni = p;
3540
3541 zl3vni = XCALLOC(MTYPE_ZL3VNI, sizeof(zebra_l3vni_t));
3542 zl3vni->vni = tmp_l3vni->vni;
3543 return ((void *)zl3vni);
3544 }
3545
3546 /*
3547 * Look up L3 VNI hash entry.
3548 */
3549 static zebra_l3vni_t *zl3vni_lookup(vni_t vni)
3550 {
3551 struct zebra_ns *zns;
3552 zebra_l3vni_t tmp_l3vni;
3553 zebra_l3vni_t *zl3vni = NULL;
3554
3555 zns = zebra_ns_lookup(NS_DEFAULT);
3556 assert(zns);
3557 memset(&tmp_l3vni, 0, sizeof(zebra_l3vni_t));
3558 tmp_l3vni.vni = vni;
3559 zl3vni = hash_lookup(zns->l3vni_table, &tmp_l3vni);
3560
3561 return zl3vni;
3562 }
3563
3564 /*
3565 * Add L3 VNI hash entry.
3566 */
3567 static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id)
3568 {
3569 zebra_l3vni_t tmp_zl3vni;
3570 struct zebra_ns *zns = NULL;
3571 zebra_l3vni_t *zl3vni = NULL;
3572
3573 zns = zebra_ns_lookup(NS_DEFAULT);
3574 assert(zns);
3575
3576 memset(&tmp_zl3vni, 0, sizeof(zebra_l3vni_t));
3577 tmp_zl3vni.vni = vni;
3578
3579 zl3vni = hash_get(zns->l3vni_table, &tmp_zl3vni, zl3vni_alloc);
3580 assert(zl3vni);
3581
3582 zl3vni->vrf_id = vrf_id;
3583 zl3vni->svi_if = NULL;
3584 zl3vni->vxlan_if = NULL;
3585 zl3vni->l2vnis = list_new();
3586 zl3vni->l2vnis->cmp = (int (*)(void *, void *))vni_hash_cmp;
3587
3588 /* Create hash table for remote RMAC */
3589 zl3vni->rmac_table = hash_create(mac_hash_keymake, mac_cmp,
3590 "Zebra L3-VNI RMAC-Table");
3591
3592 /* Create hash table for neighbors */
3593 zl3vni->nh_table = hash_create(neigh_hash_keymake, neigh_cmp,
3594 "Zebra L3-VNI next-hop table");
3595
3596 return zl3vni;
3597 }
3598
3599 /*
3600 * Delete L3 VNI hash entry.
3601 */
3602 static int zl3vni_del(zebra_l3vni_t *zl3vni)
3603 {
3604 struct zebra_ns *zns;
3605 zebra_l3vni_t *tmp_zl3vni;
3606
3607 zns = zebra_ns_lookup(NS_DEFAULT);
3608 assert(zns);
3609
3610 /* free the list of l2vnis */
3611 list_delete_and_null(&zl3vni->l2vnis);
3612 zl3vni->l2vnis = NULL;
3613
3614 /* Free the rmac table */
3615 hash_free(zl3vni->rmac_table);
3616 zl3vni->rmac_table = NULL;
3617
3618 /* Free the nh table */
3619 hash_free(zl3vni->nh_table);
3620 zl3vni->nh_table = NULL;
3621
3622 /* Free the VNI hash entry and allocated memory. */
3623 tmp_zl3vni = hash_release(zns->l3vni_table, zl3vni);
3624 if (tmp_zl3vni)
3625 XFREE(MTYPE_ZL3VNI, tmp_zl3vni);
3626
3627 return 0;
3628 }
3629
3630 static struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni)
3631 {
3632 struct zebra_ns *zns = NULL;
3633 struct route_node *rn = NULL;
3634 struct interface *ifp = NULL;
3635
3636 /* loop through all vxlan-interface */
3637 zns = zebra_ns_lookup(NS_DEFAULT);
3638 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
3639
3640 struct zebra_if *zif = NULL;
3641 struct zebra_l2info_vxlan *vxl = NULL;
3642
3643 ifp = (struct interface *)rn->info;
3644 if (!ifp)
3645 continue;
3646
3647 zif = ifp->info;
3648 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
3649 continue;
3650
3651 vxl = &zif->l2info.vxl;
3652 if (vxl->vni == zl3vni->vni) {
3653 zl3vni->local_vtep_ip = vxl->vtep_ip;
3654 return ifp;
3655 }
3656 }
3657
3658 return NULL;
3659 }
3660
3661 static struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni)
3662 {
3663 struct zebra_if *zif = NULL; /* zebra_if for vxlan_if */
3664 struct zebra_l2info_vxlan *vxl = NULL; /* l2 info for vxlan_if */
3665
3666 if (!zl3vni)
3667 return NULL;
3668
3669 if (!zl3vni->vxlan_if)
3670 return NULL;
3671
3672 zif = zl3vni->vxlan_if->info;
3673 if (!zif)
3674 return NULL;
3675
3676 vxl = &zif->l2info.vxl;
3677
3678 return zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
3679 }
3680
3681 static zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t vrf_id)
3682 {
3683 struct zebra_vrf *zvrf = NULL;
3684
3685 zvrf = zebra_vrf_lookup_by_id(vrf_id);
3686 if (!zvrf)
3687 return NULL;
3688
3689 return zl3vni_lookup(zvrf->l3vni);
3690 }
3691
3692 /*
3693 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3694 * neighbor notifications, to see if they are of interest.
3695 */
3696 static zebra_l3vni_t *zl3vni_from_svi(struct interface *ifp,
3697 struct interface *br_if)
3698 {
3699 int found = 0;
3700 vlanid_t vid = 0;
3701 uint8_t bridge_vlan_aware = 0;
3702 zebra_l3vni_t *zl3vni = NULL;
3703 struct zebra_ns *zns = NULL;
3704 struct route_node *rn = NULL;
3705 struct zebra_if *zif = NULL;
3706 struct interface *tmp_if = NULL;
3707 struct zebra_l2info_bridge *br = NULL;
3708 struct zebra_l2info_vxlan *vxl = NULL;
3709
3710 if (!br_if)
3711 return NULL;
3712
3713 /* Make sure the linked interface is a bridge. */
3714 if (!IS_ZEBRA_IF_BRIDGE(br_if))
3715 return NULL;
3716
3717 /* Determine if bridge is VLAN-aware or not */
3718 zif = br_if->info;
3719 assert(zif);
3720 br = &zif->l2info.br;
3721 bridge_vlan_aware = br->vlan_aware;
3722 if (bridge_vlan_aware) {
3723 struct zebra_l2info_vlan *vl;
3724
3725 if (!IS_ZEBRA_IF_VLAN(ifp))
3726 return NULL;
3727
3728 zif = ifp->info;
3729 assert(zif);
3730 vl = &zif->l2info.vl;
3731 vid = vl->vid;
3732 }
3733
3734 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3735 /* TODO: Optimize with a hash. */
3736 zns = zebra_ns_lookup(NS_DEFAULT);
3737 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
3738 tmp_if = (struct interface *)rn->info;
3739 if (!tmp_if)
3740 continue;
3741 zif = tmp_if->info;
3742 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
3743 continue;
3744 if (!if_is_operative(tmp_if))
3745 continue;
3746 vxl = &zif->l2info.vxl;
3747
3748 if (zif->brslave_info.br_if != br_if)
3749 continue;
3750
3751 if (!bridge_vlan_aware || vxl->access_vlan == vid) {
3752 found = 1;
3753 break;
3754 }
3755 }
3756
3757 if (!found)
3758 return NULL;
3759
3760 zl3vni = zl3vni_lookup(vxl->vni);
3761 return zl3vni;
3762 }
3763
3764 /*
3765 * Inform BGP about l3-vni.
3766 */
3767 static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni)
3768 {
3769 struct stream *s = NULL;
3770 struct zserv *client = NULL;
3771 struct ethaddr rmac;
3772 char buf[ETHER_ADDR_STRLEN];
3773
3774 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
3775 /* BGP may not be running. */
3776 if (!client)
3777 return 0;
3778
3779 /* get the rmac */
3780 memset(&rmac, 0, sizeof(struct ethaddr));
3781 zl3vni_get_rmac(zl3vni, &rmac);
3782
3783 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
3784
3785 zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni));
3786 stream_putl(s, zl3vni->vni);
3787 stream_put(s, &rmac, sizeof(struct ethaddr));
3788 stream_put_in_addr(s, &zl3vni->local_vtep_ip);
3789 stream_put(s, &zl3vni->filter, sizeof(int));
3790
3791 /* Write packet size. */
3792 stream_putw_at(s, 0, stream_get_endp(s));
3793
3794 if (IS_ZEBRA_DEBUG_VXLAN)
3795 zlog_debug(
3796 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
3797 zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
3798 prefix_mac2str(&rmac, buf, sizeof(buf)),
3799 inet_ntoa(zl3vni->local_vtep_ip),
3800 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
3801 ? "prefix-routes-only"
3802 : "none",
3803 zebra_route_string(client->proto));
3804
3805 client->l3vniadd_cnt++;
3806 return zserv_send_message(client, s);
3807 }
3808
3809 /*
3810 * Inform BGP about local l3-VNI deletion.
3811 */
3812 static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni)
3813 {
3814 struct stream *s = NULL;
3815 struct zserv *client = NULL;
3816
3817 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
3818 /* BGP may not be running. */
3819 if (!client)
3820 return 0;
3821
3822 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
3823
3824 zclient_create_header(s, ZEBRA_L3VNI_DEL, zl3vni_vrf_id(zl3vni));
3825 stream_putl(s, zl3vni->vni);
3826
3827 /* Write packet size. */
3828 stream_putw_at(s, 0, stream_get_endp(s));
3829
3830 if (IS_ZEBRA_DEBUG_VXLAN)
3831 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni->vni,
3832 vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
3833 zebra_route_string(client->proto));
3834
3835 client->l3vnidel_cnt++;
3836 return zserv_send_message(client, s);
3837 }
3838
3839 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni)
3840 {
3841 if (!zl3vni)
3842 return;
3843
3844 /* send l3vni add to BGP */
3845 zl3vni_send_add_to_client(zl3vni);
3846 }
3847
3848 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni)
3849 {
3850 if (!zl3vni)
3851 return;
3852
3853 /* send l3-vni del to BGP*/
3854 zl3vni_send_del_to_client(zl3vni);
3855 }
3856
3857 static void zvni_add_to_l3vni_list(struct hash_backet *backet, void *ctxt)
3858 {
3859 zebra_vni_t *zvni = (zebra_vni_t *)backet->data;
3860 zebra_l3vni_t *zl3vni = (zebra_l3vni_t *)ctxt;
3861
3862 if (zvni->vrf_id == zl3vni_vrf_id(zl3vni))
3863 listnode_add_sort(zl3vni->l2vnis, zvni);
3864 }
3865
3866 /*
3867 * handle transition of vni from l2 to l3 and vice versa
3868 */
3869 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
3870 int add)
3871 {
3872 zebra_vni_t *zvni = NULL;
3873
3874 /* There is a possibility that VNI notification was already received
3875 * from kernel and we programmed it as L2-VNI
3876 * In such a case we need to delete this L2-VNI first, so
3877 * that it can be reprogrammed as L3-VNI in the system. It is also
3878 * possible that the vrf-vni mapping is removed from FRR while the vxlan
3879 * interface is still present in kernel. In this case to keep it
3880 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
3881 */
3882 if (add) {
3883 /* Locate hash entry */
3884 zvni = zvni_lookup(vni);
3885 if (!zvni)
3886 return 0;
3887
3888 if (IS_ZEBRA_DEBUG_VXLAN)
3889 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni);
3890
3891 /* Delete VNI from BGP. */
3892 zvni_send_del_to_client(zvni->vni);
3893
3894 /* Free up all neighbors and MAC, if any. */
3895 zvni_neigh_del_all(zvni, 0, 0, DEL_ALL_NEIGH);
3896 zvni_mac_del_all(zvni, 0, 0, DEL_ALL_MAC);
3897
3898 /* Free up all remote VTEPs, if any. */
3899 zvni_vtep_del_all(zvni, 0);
3900
3901 /* Delete the hash entry. */
3902 if (zvni_del(zvni)) {
3903 zlog_err("Failed to del VNI hash %p, VNI %u", zvni,
3904 zvni->vni);
3905 return -1;
3906 }
3907 } else {
3908 /* TODO_MITESH: This needs to be thought through. We don't have
3909 * enough information at this point to reprogram the vni as
3910 * l2-vni. One way is to store the required info in l3-vni and
3911 * used it solely for this purpose
3912 */
3913 }
3914
3915 return 0;
3916 }
3917
3918 /* delete and uninstall rmac hash entry */
3919 static void zl3vni_del_rmac_hash_entry(struct hash_backet *backet, void *ctx)
3920 {
3921 zebra_mac_t *zrmac = NULL;
3922 zebra_l3vni_t *zl3vni = NULL;
3923
3924 zrmac = (zebra_mac_t *)backet->data;
3925 zl3vni = (zebra_l3vni_t *)ctx;
3926 zl3vni_rmac_uninstall(zl3vni, zrmac);
3927 zl3vni_rmac_del(zl3vni, zrmac);
3928 }
3929
3930 /* delete and uninstall nh hash entry */
3931 static void zl3vni_del_nh_hash_entry(struct hash_backet *backet, void *ctx)
3932 {
3933 zebra_neigh_t *n = NULL;
3934 zebra_l3vni_t *zl3vni = NULL;
3935
3936 n = (zebra_neigh_t *)backet->data;
3937 zl3vni = (zebra_l3vni_t *)ctx;
3938 zl3vni_nh_uninstall(zl3vni, n);
3939 zl3vni_nh_del(zl3vni, n);
3940 }
3941
3942 static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
3943 uint16_t cmd)
3944 {
3945 struct zserv *client = NULL;
3946 struct stream *s = NULL;
3947 char buf[PREFIX_STRLEN];
3948
3949 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
3950 /* BGP may not be running. */
3951 if (!client)
3952 return 0;
3953
3954 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
3955
3956 zclient_create_header(s, cmd, vrf_id);
3957 stream_put(s, p, sizeof(struct prefix));
3958
3959 /* Write packet size. */
3960 stream_putw_at(s, 0, stream_get_endp(s));
3961
3962 if (IS_ZEBRA_DEBUG_VXLAN)
3963 zlog_debug("Send ip prefix %s %s on vrf %s",
3964 prefix2str(p, buf, sizeof(buf)),
3965 (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) ? "ADD" : "DEL",
3966 vrf_id_to_name(vrf_id));
3967
3968 if (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD)
3969 client->prefixadd_cnt++;
3970 else
3971 client->prefixdel_cnt++;
3972
3973 return zserv_send_message(client, s);
3974 }
3975
3976 /* re-add remote rmac if needed */
3977 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t *zl3vni,
3978 struct ethaddr *rmac)
3979 {
3980 char buf[ETHER_ADDR_STRLEN];
3981 zebra_mac_t *zrmac = NULL;
3982
3983 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
3984 if (!zrmac)
3985 return 0;
3986
3987 if (IS_ZEBRA_DEBUG_VXLAN)
3988 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
3989 prefix_mac2str(rmac, buf, sizeof(buf)), zl3vni->vni);
3990
3991 zl3vni_rmac_install(zl3vni, zrmac);
3992 return 0;
3993 }
3994
3995 /* Public functions */
3996
3997 int is_l3vni_for_prefix_routes_only(vni_t vni)
3998 {
3999 zebra_l3vni_t *zl3vni = NULL;
4000
4001 zl3vni = zl3vni_lookup(vni);
4002 if (!zl3vni)
4003 return 0;
4004
4005 return CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY) ? 1 : 0;
4006 }
4007
4008 /* handle evpn route in vrf table */
4009 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id, struct ethaddr *rmac,
4010 struct ipaddr *vtep_ip,
4011 struct prefix *host_prefix)
4012 {
4013 zebra_l3vni_t *zl3vni = NULL;
4014 struct ipaddr ipv4_vtep;
4015
4016 zl3vni = zl3vni_from_vrf(vrf_id);
4017 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
4018 return;
4019
4020 /*
4021 * add the next hop neighbor -
4022 * neigh to be installed is the ipv6 nexthop neigh
4023 */
4024 zl3vni_remote_nh_add(zl3vni, vtep_ip, rmac, host_prefix);
4025
4026 /*
4027 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
4028 * address. Rmac is programmed against the ipv4 vtep because we only
4029 * support ipv4 tunnels in the h/w right now
4030 */
4031 memset(&ipv4_vtep, 0, sizeof(struct ipaddr));
4032 ipv4_vtep.ipa_type = IPADDR_V4;
4033 if (vtep_ip->ipa_type == IPADDR_V6)
4034 ipv4_mapped_ipv6_to_ipv4(&vtep_ip->ipaddr_v6,
4035 &(ipv4_vtep.ipaddr_v4));
4036 else
4037 memcpy(&(ipv4_vtep.ipaddr_v4), &vtep_ip->ipaddr_v4,
4038 sizeof(struct in_addr));
4039
4040 /*
4041 * add the rmac - remote rmac to be installed is against the ipv4
4042 * nexthop address
4043 */
4044 zl3vni_remote_rmac_add(zl3vni, rmac, &ipv4_vtep, host_prefix);
4045 }
4046
4047 /* handle evpn vrf route delete */
4048 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
4049 struct ipaddr *vtep_ip,
4050 struct prefix *host_prefix)
4051 {
4052 zebra_l3vni_t *zl3vni = NULL;
4053 zebra_neigh_t *nh = NULL;
4054 zebra_mac_t *zrmac = NULL;
4055
4056 zl3vni = zl3vni_from_vrf(vrf_id);
4057 if (!zl3vni)
4058 return;
4059
4060 /* find the next hop entry and rmac entry */
4061 nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
4062 if (!nh)
4063 return;
4064 zrmac = zl3vni_rmac_lookup(zl3vni, &nh->emac);
4065
4066 /* delete the next hop entry */
4067 zl3vni_remote_nh_del(zl3vni, nh, host_prefix);
4068
4069 /* delete the rmac entry */
4070 if (zrmac)
4071 zl3vni_remote_rmac_del(zl3vni, zrmac, host_prefix);
4072
4073 }
4074
4075 void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
4076 struct ethaddr *rmac,
4077 uint8_t use_json)
4078 {
4079 zebra_l3vni_t *zl3vni = NULL;
4080 zebra_mac_t *zrmac = NULL;
4081 json_object *json = NULL;
4082
4083 if (!is_evpn_enabled()) {
4084 if (use_json)
4085 vty_out(vty, "{}\n");
4086 return;
4087 }
4088
4089 if (use_json)
4090 json = json_object_new_object();
4091
4092 zl3vni = zl3vni_lookup(l3vni);
4093 if (!zl3vni) {
4094 if (use_json)
4095 vty_out(vty, "{}\n");
4096 else
4097 vty_out(vty, "%% L3-VNI %u doesnt exist\n", l3vni);
4098 return;
4099 }
4100
4101 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
4102 if (!zrmac) {
4103 if (use_json)
4104 vty_out(vty, "{}\n");
4105 else
4106 vty_out(vty,
4107 "%% Requested RMAC doesnt exist in L3-VNI %u",
4108 l3vni);
4109 return;
4110 }
4111
4112 zl3vni_print_rmac(zrmac, vty, json);
4113
4114 if (use_json) {
4115 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4116 json, JSON_C_TO_STRING_PRETTY));
4117 json_object_free(json);
4118 }
4119 }
4120
4121 void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni,
4122 uint8_t use_json)
4123 {
4124 zebra_l3vni_t *zl3vni;
4125 uint32_t num_rmacs;
4126 struct rmac_walk_ctx wctx;
4127 json_object *json = NULL;
4128
4129 if (!is_evpn_enabled())
4130 return;
4131
4132 zl3vni = zl3vni_lookup(l3vni);
4133 if (!zl3vni) {
4134 if (use_json)
4135 vty_out(vty, "{}\n");
4136 else
4137 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
4138 return;
4139 }
4140 num_rmacs = hashcount(zl3vni->rmac_table);
4141 if (!num_rmacs)
4142 return;
4143
4144 if (use_json)
4145 json = json_object_new_object();
4146
4147 memset(&wctx, 0, sizeof(struct rmac_walk_ctx));
4148 wctx.vty = vty;
4149 wctx.json = json;
4150 if (!use_json) {
4151 vty_out(vty, "Number of Remote RMACs known for this VNI: %u\n",
4152 num_rmacs);
4153 vty_out(vty, "%-17s %-21s\n", "MAC", "Remote VTEP");
4154 } else
4155 json_object_int_add(json, "numRmacs", num_rmacs);
4156
4157 hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
4158
4159 if (use_json) {
4160 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4161 json, JSON_C_TO_STRING_PRETTY));
4162 json_object_free(json);
4163 }
4164 }
4165
4166 void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, uint8_t use_json)
4167 {
4168 struct zebra_ns *zns = NULL;
4169 json_object *json = NULL;
4170 void *args[2];
4171
4172 if (!is_evpn_enabled()) {
4173 if (use_json)
4174 vty_out(vty, "{}\n");
4175 return;
4176 }
4177
4178 zns = zebra_ns_lookup(NS_DEFAULT);
4179 if (!zns) {
4180 if (use_json)
4181 vty_out(vty, "{}\n");
4182 return;
4183 }
4184
4185 if (use_json)
4186 json = json_object_new_object();
4187
4188 args[0] = vty;
4189 args[1] = json;
4190 hash_iterate(zns->l3vni_table,
4191 (void (*)(struct hash_backet *,
4192 void *))zl3vni_print_rmac_hash_all_vni,
4193 args);
4194
4195 if (use_json) {
4196 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4197 json, JSON_C_TO_STRING_PRETTY));
4198 json_object_free(json);
4199 }
4200 }
4201
4202 void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
4203 struct ipaddr *ip, uint8_t use_json)
4204 {
4205 zebra_l3vni_t *zl3vni = NULL;
4206 zebra_neigh_t *n = NULL;
4207 json_object *json = NULL;
4208
4209 if (!is_evpn_enabled()) {
4210 if (use_json)
4211 vty_out(vty, "{}\n");
4212 return;
4213 }
4214
4215 if (use_json)
4216 json = json_object_new_object();
4217
4218 zl3vni = zl3vni_lookup(l3vni);
4219 if (!zl3vni) {
4220 if (use_json)
4221 vty_out(vty, "{}\n");
4222 else
4223 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
4224 return;
4225 }
4226
4227 n = zl3vni_nh_lookup(zl3vni, ip);
4228 if (!n) {
4229 if (use_json)
4230 vty_out(vty, "{}\n");
4231 else
4232 vty_out(vty,
4233 "%% Requested next-hop not present for L3-VNI %u",
4234 l3vni);
4235 return;
4236 }
4237
4238 zl3vni_print_nh(n, vty, json);
4239
4240 if (use_json) {
4241 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4242 json, JSON_C_TO_STRING_PRETTY));
4243 json_object_free(json);
4244 }
4245 }
4246
4247 void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, uint8_t use_json)
4248 {
4249 uint32_t num_nh;
4250 struct nh_walk_ctx wctx;
4251 json_object *json = NULL;
4252 zebra_l3vni_t *zl3vni = NULL;
4253
4254 if (!is_evpn_enabled())
4255 return;
4256
4257 zl3vni = zl3vni_lookup(l3vni);
4258 if (!zl3vni) {
4259 if (use_json)
4260 vty_out(vty, "{}\n");
4261 else
4262 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
4263 return;
4264 }
4265
4266 num_nh = hashcount(zl3vni->nh_table);
4267 if (!num_nh)
4268 return;
4269
4270 if (use_json)
4271 json = json_object_new_object();
4272
4273 wctx.vty = vty;
4274 wctx.json = json;
4275 if (!use_json) {
4276 vty_out(vty, "Number of NH Neighbors known for this VNI: %u\n",
4277 num_nh);
4278 vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
4279 } else
4280 json_object_int_add(json, "numNextHops", num_nh);
4281
4282 hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
4283
4284 if (use_json) {
4285 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4286 json, JSON_C_TO_STRING_PRETTY));
4287 json_object_free(json);
4288 }
4289 }
4290
4291 void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, uint8_t use_json)
4292 {
4293 struct zebra_ns *zns = NULL;
4294 json_object *json = NULL;
4295 void *args[2];
4296
4297 if (!is_evpn_enabled()) {
4298 if (use_json)
4299 vty_out(vty, "{}\n");
4300 return;
4301 }
4302
4303 zns = zebra_ns_lookup(NS_DEFAULT);
4304 if (!zns)
4305 return;
4306
4307 if (use_json)
4308 json = json_object_new_object();
4309
4310 args[0] = vty;
4311 args[1] = json;
4312 hash_iterate(zns->l3vni_table,
4313 (void (*)(struct hash_backet *,
4314 void *))zl3vni_print_nh_hash_all_vni,
4315 args);
4316
4317 if (use_json) {
4318 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4319 json, JSON_C_TO_STRING_PRETTY));
4320 json_object_free(json);
4321 }
4322 return;
4323 }
4324
4325 /*
4326 * Display L3 VNI information (VTY command handler).
4327 */
4328 void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, uint8_t use_json)
4329 {
4330 void *args[2];
4331 json_object *json = NULL;
4332 zebra_l3vni_t *zl3vni = NULL;
4333
4334 if (!is_evpn_enabled()) {
4335 if (use_json)
4336 vty_out(vty, "{}\n");
4337 return;
4338 }
4339
4340 zl3vni = zl3vni_lookup(vni);
4341 if (!zl3vni) {
4342 if (use_json)
4343 vty_out(vty, "{}\n");
4344 else
4345 vty_out(vty, "%% VNI %u does not exist\n", vni);
4346 return;
4347 }
4348
4349 if (use_json)
4350 json = json_object_new_object();
4351
4352 args[0] = vty;
4353 args[1] = json;
4354 zl3vni_print(zl3vni, (void *)args);
4355
4356 if (use_json) {
4357 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4358 json, JSON_C_TO_STRING_PRETTY));
4359 json_object_free(json);
4360 }
4361 }
4362
4363 void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf,
4364 json_object *json_vrfs)
4365 {
4366 char buf[ETHER_ADDR_STRLEN];
4367 zebra_l3vni_t *zl3vni = NULL;
4368
4369 zl3vni = zl3vni_lookup(zvrf->l3vni);
4370 if (!zl3vni)
4371 return;
4372
4373 if (!json_vrfs) {
4374 vty_out(vty, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
4375 zvrf_name(zvrf), zl3vni->vni,
4376 zl3vni_vxlan_if_name(zl3vni),
4377 zl3vni_svi_if_name(zl3vni), zl3vni_state2str(zl3vni),
4378 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
4379 } else {
4380 json_object *json_vrf = NULL;
4381 json_vrf = json_object_new_object();
4382 json_object_string_add(json_vrf, "vrf", zvrf_name(zvrf));
4383 json_object_int_add(json_vrf, "vni", zl3vni->vni);
4384 json_object_string_add(json_vrf, "vxlanIntf",
4385 zl3vni_vxlan_if_name(zl3vni));
4386 json_object_string_add(json_vrf, "sviIntf",
4387 zl3vni_svi_if_name(zl3vni));
4388 json_object_string_add(json_vrf, "state",
4389 zl3vni_state2str(zl3vni));
4390 json_object_string_add(
4391 json_vrf, "routerMac",
4392 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
4393 json_object_array_add(json_vrfs, json_vrf);
4394 }
4395 }
4396
4397 /*
4398 * Display Neighbors for a VNI (VTY command handler).
4399 */
4400 void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
4401 vni_t vni, uint8_t use_json)
4402 {
4403 zebra_vni_t *zvni;
4404 uint32_t num_neigh;
4405 struct neigh_walk_ctx wctx;
4406 json_object *json = NULL;
4407
4408 if (!is_evpn_enabled())
4409 return;
4410 zvni = zvni_lookup(vni);
4411 if (!zvni) {
4412 if (use_json)
4413 vty_out(vty, "{}\n");
4414 else
4415 vty_out(vty, "%% VNI %u does not exist\n", vni);
4416 return;
4417 }
4418 num_neigh = hashcount(zvni->neigh_table);
4419 if (!num_neigh)
4420 return;
4421
4422 if (use_json)
4423 json = json_object_new_object();
4424
4425 /* Since we have IPv6 addresses to deal with which can vary widely in
4426 * size, we try to be a bit more elegant in display by first computing
4427 * the maximum width.
4428 */
4429 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
4430 wctx.zvni = zvni;
4431 wctx.vty = vty;
4432 wctx.addr_width = 15;
4433 wctx.json = json;
4434 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
4435
4436 if (!use_json) {
4437 vty_out(vty,
4438 "Number of ARPs (local and remote) known for this VNI: %u\n",
4439 num_neigh);
4440 vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP",
4441 "Type", "MAC", "Remote VTEP");
4442 } else
4443 json_object_int_add(json, "numArpNd", num_neigh);
4444
4445 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
4446 if (use_json) {
4447 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4448 json, JSON_C_TO_STRING_PRETTY));
4449 json_object_free(json);
4450 }
4451 }
4452
4453 /*
4454 * Display neighbors across all VNIs (VTY command handler).
4455 */
4456 void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
4457 uint8_t use_json)
4458 {
4459 json_object *json = NULL;
4460 void *args[2];
4461
4462 if (!is_evpn_enabled())
4463 return;
4464
4465 if (use_json)
4466 json = json_object_new_object();
4467
4468 args[0] = vty;
4469 args[1] = json;
4470 hash_iterate(zvrf->vni_table,
4471 (void (*)(struct hash_backet *,
4472 void *))zvni_print_neigh_hash_all_vni,
4473 args);
4474 if (use_json) {
4475 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4476 json, JSON_C_TO_STRING_PRETTY));
4477 json_object_free(json);
4478 }
4479 }
4480
4481 /*
4482 * Display specific neighbor for a VNI, if present (VTY command handler).
4483 */
4484 void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
4485 struct zebra_vrf *zvrf, vni_t vni,
4486 struct ipaddr *ip, uint8_t use_json)
4487 {
4488 zebra_vni_t *zvni;
4489 zebra_neigh_t *n;
4490 json_object *json = NULL;
4491
4492 if (!is_evpn_enabled())
4493 return;
4494 zvni = zvni_lookup(vni);
4495 if (!zvni) {
4496 if (use_json)
4497 vty_out(vty, "{}\n");
4498 else
4499 vty_out(vty, "%% VNI %u does not exist\n", vni);
4500 return;
4501 }
4502 n = zvni_neigh_lookup(zvni, ip);
4503 if (!n) {
4504 if (!use_json)
4505 vty_out(vty,
4506 "%% Requested neighbor does not exist in VNI %u\n",
4507 vni);
4508 return;
4509 }
4510 if (use_json)
4511 json = json_object_new_object();
4512
4513 zvni_print_neigh(n, vty, json);
4514
4515 if (use_json) {
4516 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4517 json, JSON_C_TO_STRING_PRETTY));
4518 json_object_free(json);
4519 }
4520 }
4521
4522 /*
4523 * Display neighbors for a VNI from specific VTEP (VTY command handler).
4524 * By definition, these are remote neighbors.
4525 */
4526 void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
4527 vni_t vni, struct in_addr vtep_ip,
4528 uint8_t use_json)
4529 {
4530 zebra_vni_t *zvni;
4531 uint32_t num_neigh;
4532 struct neigh_walk_ctx wctx;
4533 json_object *json = NULL;
4534
4535 if (!is_evpn_enabled())
4536 return;
4537 zvni = zvni_lookup(vni);
4538 if (!zvni) {
4539 if (use_json)
4540 vty_out(vty, "{}\n");
4541 else
4542 vty_out(vty, "%% VNI %u does not exist\n", vni);
4543 return;
4544 }
4545 num_neigh = hashcount(zvni->neigh_table);
4546 if (!num_neigh)
4547 return;
4548
4549 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
4550 wctx.zvni = zvni;
4551 wctx.vty = vty;
4552 wctx.addr_width = 15;
4553 wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP;
4554 wctx.r_vtep_ip = vtep_ip;
4555 wctx.json = json;
4556 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
4557 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
4558
4559 if (use_json) {
4560 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4561 json, JSON_C_TO_STRING_PRETTY));
4562 json_object_free(json);
4563 }
4564 }
4565
4566 /*
4567 * Display MACs for a VNI (VTY command handler).
4568 */
4569 void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
4570 vni_t vni, uint8_t use_json)
4571 {
4572 zebra_vni_t *zvni;
4573 uint32_t num_macs;
4574 struct mac_walk_ctx wctx;
4575 json_object *json = NULL;
4576 json_object *json_mac = NULL;
4577
4578 if (!is_evpn_enabled())
4579 return;
4580 zvni = zvni_lookup(vni);
4581 if (!zvni) {
4582 if (use_json)
4583 vty_out(vty, "{}\n");
4584 else
4585 vty_out(vty, "%% VNI %u does not exist\n", vni);
4586 return;
4587 }
4588 num_macs = num_valid_macs(zvni);
4589 if (!num_macs)
4590 return;
4591
4592 if (use_json) {
4593 json = json_object_new_object();
4594 json_mac = json_object_new_object();
4595 }
4596
4597 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4598 wctx.zvni = zvni;
4599 wctx.vty = vty;
4600 wctx.json = json_mac;
4601
4602 if (!use_json) {
4603 vty_out(vty,
4604 "Number of MACs (local and remote) known for this VNI: %u\n",
4605 num_macs);
4606 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
4607 "Intf/Remote VTEP", "VLAN");
4608 } else
4609 json_object_int_add(json, "numMacs", num_macs);
4610
4611 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
4612
4613 if (use_json) {
4614 json_object_object_add(json, "macs", json_mac);
4615 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4616 json, JSON_C_TO_STRING_PRETTY));
4617 json_object_free(json);
4618 }
4619 }
4620
4621 /*
4622 * Display MACs for all VNIs (VTY command handler).
4623 */
4624 void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
4625 uint8_t use_json)
4626 {
4627 struct mac_walk_ctx wctx;
4628 json_object *json = NULL;
4629
4630 if (!is_evpn_enabled()) {
4631 if (use_json)
4632 vty_out(vty, "{}\n");
4633 return;
4634 }
4635 if (use_json)
4636 json = json_object_new_object();
4637
4638 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4639 wctx.vty = vty;
4640 wctx.json = json;
4641 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
4642
4643 if (use_json) {
4644 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4645 json, JSON_C_TO_STRING_PRETTY));
4646 json_object_free(json);
4647 }
4648 }
4649
4650 /*
4651 * Display MACs for all VNIs (VTY command handler).
4652 */
4653 void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
4654 struct zebra_vrf *zvrf,
4655 struct in_addr vtep_ip,
4656 uint8_t use_json)
4657 {
4658 struct mac_walk_ctx wctx;
4659 json_object *json = NULL;
4660
4661 if (!is_evpn_enabled())
4662 return;
4663
4664 if (use_json)
4665 json = json_object_new_object();
4666
4667 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4668 wctx.vty = vty;
4669 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
4670 wctx.r_vtep_ip = vtep_ip;
4671 wctx.json = json;
4672 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
4673
4674 if (use_json) {
4675 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4676 json, JSON_C_TO_STRING_PRETTY));
4677 json_object_free(json);
4678 }
4679 }
4680
4681 /*
4682 * Display specific MAC for a VNI, if present (VTY command handler).
4683 */
4684 void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
4685 vni_t vni, struct ethaddr *macaddr)
4686 {
4687 zebra_vni_t *zvni;
4688 zebra_mac_t *mac;
4689
4690 if (!is_evpn_enabled())
4691 return;
4692 zvni = zvni_lookup(vni);
4693 if (!zvni) {
4694 vty_out(vty, "%% VNI %u does not exist\n", vni);
4695 return;
4696 }
4697 mac = zvni_mac_lookup(zvni, macaddr);
4698 if (!mac) {
4699 vty_out(vty, "%% Requested MAC does not exist in VNI %u\n",
4700 vni);
4701 return;
4702 }
4703
4704 zvni_print_mac(mac, vty);
4705 }
4706
4707 /*
4708 * Display MACs for a VNI from specific VTEP (VTY command handler).
4709 */
4710 void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
4711 vni_t vni, struct in_addr vtep_ip,
4712 uint8_t use_json)
4713 {
4714 zebra_vni_t *zvni;
4715 uint32_t num_macs;
4716 struct mac_walk_ctx wctx;
4717 json_object *json = NULL;
4718 json_object *json_mac = NULL;
4719
4720 if (!is_evpn_enabled())
4721 return;
4722 zvni = zvni_lookup(vni);
4723 if (!zvni) {
4724 if (use_json)
4725 vty_out(vty, "{}\n");
4726 else
4727 vty_out(vty, "%% VNI %u does not exist\n", vni);
4728 return;
4729 }
4730 num_macs = num_valid_macs(zvni);
4731 if (!num_macs)
4732 return;
4733
4734 if (use_json) {
4735 json = json_object_new_object();
4736 json_mac = json_object_new_object();
4737 }
4738
4739 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
4740 wctx.zvni = zvni;
4741 wctx.vty = vty;
4742 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
4743 wctx.r_vtep_ip = vtep_ip;
4744 wctx.json = json_mac;
4745 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
4746
4747 if (use_json) {
4748 json_object_int_add(json, "numMacs", wctx.count);
4749 if (wctx.count)
4750 json_object_object_add(json, "macs", json_mac);
4751 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4752 json, JSON_C_TO_STRING_PRETTY));
4753 json_object_free(json);
4754 }
4755 }
4756
4757
4758 /*
4759 * Display VNI information (VTY command handler).
4760 */
4761 void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
4762 uint8_t use_json)
4763 {
4764 json_object *json = NULL;
4765 void *args[2];
4766 zebra_l3vni_t *zl3vni = NULL;
4767 zebra_vni_t *zvni = NULL;
4768
4769 if (!is_evpn_enabled())
4770 return;
4771
4772 if (use_json)
4773 json = json_object_new_object();
4774 args[0] = vty;
4775 args[1] = json;
4776
4777 zl3vni = zl3vni_lookup(vni);
4778 if (zl3vni) {
4779 zl3vni_print(zl3vni, (void *)args);
4780 } else {
4781 zvni = zvni_lookup(vni);
4782 if (!zvni) {
4783 if (use_json)
4784 vty_out(vty, "{}\n");
4785 else
4786 vty_out(vty, "%% VNI %u does not exist\n", vni);
4787 return;
4788 }
4789
4790 zvni_print(zvni, (void *)args);
4791 }
4792
4793 if (use_json) {
4794 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4795 json, JSON_C_TO_STRING_PRETTY));
4796 json_object_free(json);
4797 }
4798 }
4799
4800 /* Display all global details for EVPN */
4801 void zebra_vxlan_print_evpn(struct vty *vty, uint8_t uj)
4802 {
4803 int num_l2vnis = 0;
4804 int num_l3vnis = 0;
4805 int num_vnis = 0;
4806 json_object *json = NULL;
4807 struct zebra_ns *zns = NULL;
4808 struct zebra_vrf *zvrf = NULL;
4809
4810 if (!is_evpn_enabled())
4811 return;
4812
4813 zns = zebra_ns_lookup(NS_DEFAULT);
4814 if (!zns)
4815 return;
4816
4817 zvrf = vrf_info_lookup(VRF_DEFAULT);
4818 if (!zvrf)
4819 return;
4820
4821 num_l3vnis = hashcount(zns->l3vni_table);
4822 num_l2vnis = hashcount(zvrf->vni_table);
4823 num_vnis = num_l2vnis + num_l3vnis;
4824
4825 if (uj) {
4826 json = json_object_new_object();
4827 json_object_string_add(json, "advertiseGatewayMacip",
4828 zvrf->advertise_gw_macip ? "Yes" : "No");
4829 json_object_int_add(json, "numVnis", num_vnis);
4830 json_object_int_add(json, "numL2Vnis", num_l2vnis);
4831 json_object_int_add(json, "numL3Vnis", num_l3vnis);
4832 } else {
4833 vty_out(vty, "L2 VNIs: %u\n", num_l2vnis);
4834 vty_out(vty, "L3 VNIs: %u\n", num_l3vnis);
4835 vty_out(vty, "Advertise gateway mac-ip: %s\n",
4836 zvrf->advertise_gw_macip ? "Yes" : "No");
4837 }
4838
4839 if (uj) {
4840 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4841 json, JSON_C_TO_STRING_PRETTY));
4842 json_object_free(json);
4843 }
4844 }
4845
4846 /*
4847 * Display VNI hash table (VTY command handler).
4848 */
4849 void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
4850 uint8_t use_json)
4851 {
4852 json_object *json = NULL;
4853 struct zebra_ns *zns = NULL;
4854 void *args[2];
4855
4856 if (!is_evpn_enabled())
4857 return;
4858
4859 zns = zebra_ns_lookup(NS_DEFAULT);
4860 if (!zns)
4861 return;
4862
4863
4864 if (use_json)
4865 json = json_object_new_object();
4866 else
4867 vty_out(vty, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
4868 "Type", "VxLAN IF", "# MACs", "# ARPs",
4869 "# Remote VTEPs", "Tenant VRF");
4870
4871 args[0] = vty;
4872 args[1] = json;
4873
4874 /* Display all L2-VNIs */
4875 hash_iterate(zvrf->vni_table,
4876 (void (*)(struct hash_backet *, void *))zvni_print_hash,
4877 args);
4878
4879 /* Display all L3-VNIs */
4880 hash_iterate(zns->l3vni_table,
4881 (void (*)(struct hash_backet *, void *))zl3vni_print_hash,
4882 args);
4883
4884 if (use_json) {
4885 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4886 json, JSON_C_TO_STRING_PRETTY));
4887 json_object_free(json);
4888 }
4889 }
4890
4891 /*
4892 * Handle neighbor delete notification from the kernel (on a VLAN device
4893 * / L3 interface). This may result in either the neighbor getting deleted
4894 * from our database or being re-added to the kernel (if it is a valid
4895 * remote neighbor).
4896 */
4897 int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
4898 struct interface *link_if,
4899 struct ipaddr *ip)
4900 {
4901 char buf[INET6_ADDRSTRLEN];
4902 char buf2[ETHER_ADDR_STRLEN];
4903 zebra_neigh_t *n = NULL;
4904 zebra_vni_t *zvni = NULL;
4905 zebra_mac_t *zmac = NULL;
4906 zebra_l3vni_t *zl3vni = NULL;
4907
4908 /* check if this is a remote neigh entry corresponding to remote
4909 * next-hop
4910 */
4911 zl3vni = zl3vni_from_svi(ifp, link_if);
4912 if (zl3vni)
4913 return zl3vni_local_nh_del(zl3vni, ip);
4914
4915 /* We are only interested in neighbors on an SVI that resides on top
4916 * of a VxLAN bridge.
4917 */
4918 zvni = zvni_from_svi(ifp, link_if);
4919 if (!zvni)
4920 return 0;
4921
4922 if (!zvni->vxlan_if) {
4923 zlog_err(
4924 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
4925 zvni->vni, zvni);
4926 return -1;
4927 }
4928
4929 if (IS_ZEBRA_DEBUG_VXLAN)
4930 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
4931 ipaddr2str(ip, buf, sizeof(buf)), ifp->name,
4932 ifp->ifindex, zvni->vni);
4933
4934 /* If entry doesn't exist, nothing to do. */
4935 n = zvni_neigh_lookup(zvni, ip);
4936 if (!n)
4937 return 0;
4938
4939 zmac = zvni_mac_lookup(zvni, &n->emac);
4940 if (!zmac) {
4941 if (IS_ZEBRA_DEBUG_VXLAN)
4942 zlog_err(
4943 "Trying to del a neigh %s without a mac %s on VNI %u",
4944 ipaddr2str(ip, buf, sizeof(buf)),
4945 prefix_mac2str(&n->emac, buf2, sizeof(buf2)),
4946 zvni->vni);
4947
4948 return 0;
4949 }
4950
4951 /* If it is a remote entry, the kernel has aged this out or someone has
4952 * deleted it, it needs to be re-installed as Quagga is the owner.
4953 */
4954 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
4955 zvni_neigh_install(zvni, n);
4956 return 0;
4957 }
4958
4959 /* Remove neighbor from BGP. */
4960 if (IS_ZEBRA_NEIGH_ACTIVE(n))
4961 zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0);
4962
4963 /* Delete this neighbor entry. */
4964 zvni_neigh_del(zvni, n);
4965
4966 /* see if the AUTO mac needs to be deleted */
4967 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
4968 && !listcount(zmac->neigh_list))
4969 zvni_mac_del(zvni, zmac);
4970
4971 return 0;
4972 }
4973
4974 /*
4975 * Handle neighbor add or update notification from the kernel (on a VLAN
4976 * device / L3 interface). This is typically for a local neighbor but can
4977 * also be for a remote neighbor (e.g., ageout notification). It could
4978 * also be a "move" scenario.
4979 */
4980 int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
4981 struct interface *link_if,
4982 struct ipaddr *ip,
4983 struct ethaddr *macaddr,
4984 uint16_t state,
4985 uint8_t ext_learned,
4986 uint8_t router_flag)
4987 {
4988 char buf[ETHER_ADDR_STRLEN];
4989 char buf2[INET6_ADDRSTRLEN];
4990 zebra_vni_t *zvni = NULL;
4991 zebra_l3vni_t *zl3vni = NULL;
4992
4993 /* check if this is a remote neigh entry corresponding to remote
4994 * next-hop
4995 */
4996 zl3vni = zl3vni_from_svi(ifp, link_if);
4997 if (zl3vni)
4998 return zl3vni_local_nh_add_update(zl3vni, ip, state);
4999
5000 /* We are only interested in neighbors on an SVI that resides on top
5001 * of a VxLAN bridge.
5002 */
5003 zvni = zvni_from_svi(ifp, link_if);
5004 if (!zvni)
5005 return 0;
5006
5007 if (IS_ZEBRA_DEBUG_VXLAN)
5008 zlog_debug(
5009 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u",
5010 ipaddr2str(ip, buf2, sizeof(buf2)),
5011 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5012 ifp->ifindex, state, ext_learned ? "ext-learned " : "",
5013 zvni->vni);
5014
5015 /* Is this about a local neighbor or a remote one? */
5016 if (!ext_learned)
5017 return zvni_local_neigh_update(zvni, ifp, ip, macaddr,
5018 router_flag);
5019
5020 return zvni_remote_neigh_update(zvni, ifp, ip, macaddr, state);
5021 }
5022
5023
5024 /*
5025 * Handle message from client to delete a remote MACIP for a VNI.
5026 */
5027 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS)
5028 {
5029 struct stream *s;
5030 vni_t vni;
5031 struct ethaddr macaddr;
5032 struct ipaddr ip;
5033 struct in_addr vtep_ip;
5034 zebra_vni_t *zvni;
5035 zebra_mac_t *mac;
5036 zebra_neigh_t *n;
5037 unsigned short l = 0, ipa_len;
5038 char buf[ETHER_ADDR_STRLEN];
5039 char buf1[INET6_ADDRSTRLEN];
5040 struct interface *ifp = NULL;
5041 struct zebra_if *zif = NULL;
5042
5043 memset(&macaddr, 0, sizeof(struct ethaddr));
5044 memset(&ip, 0, sizeof(struct ipaddr));
5045 memset(&vtep_ip, 0, sizeof(struct in_addr));
5046
5047 s = msg;
5048
5049 while (l < hdr->length) {
5050 /* Obtain each remote MACIP and process. */
5051 /* Message contains VNI, followed by MAC followed by IP (if any)
5052 * followed by remote VTEP IP.
5053 */
5054 mac = NULL;
5055 n = NULL;
5056 memset(&ip, 0, sizeof(ip));
5057 STREAM_GETL(s, vni);
5058 STREAM_GET(&macaddr.octet, s, ETH_ALEN);
5059 STREAM_GETL(s, ipa_len);
5060 if (ipa_len) {
5061 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
5062 : IPADDR_V6;
5063 STREAM_GET(&ip.ip.addr, s, ipa_len);
5064 }
5065 l += 4 + ETH_ALEN + 4 + ipa_len;
5066 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
5067 l += IPV4_MAX_BYTELEN;
5068
5069 if (IS_ZEBRA_DEBUG_VXLAN)
5070 zlog_debug(
5071 "Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
5072 prefix_mac2str(&macaddr, buf, sizeof(buf)),
5073 ipaddr2str(&ip, buf1, sizeof(buf1)), vni,
5074 inet_ntoa(vtep_ip),
5075 zebra_route_string(client->proto));
5076
5077 /* Locate VNI hash entry - expected to exist. */
5078 zvni = zvni_lookup(vni);
5079 if (!zvni) {
5080 if (IS_ZEBRA_DEBUG_VXLAN)
5081 zlog_debug(
5082 "Failed to locate VNI hash upon remote MACIP DEL, "
5083 "VNI %u",
5084 vni);
5085 continue;
5086 }
5087 ifp = zvni->vxlan_if;
5088 if (!ifp) {
5089 zlog_err(
5090 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
5091 vni, zvni);
5092 continue;
5093 }
5094 zif = ifp->info;
5095
5096 /* If down or not mapped to a bridge, we're done. */
5097 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
5098 continue;
5099
5100 /* The remote VTEP specified is normally expected to exist, but
5101 * it is
5102 * possible that the peer may delete the VTEP before deleting
5103 * any MACs
5104 * referring to the VTEP, in which case the handler (see
5105 * remote_vtep_del)
5106 * would have already deleted the MACs.
5107 */
5108 if (!zvni_vtep_find(zvni, &vtep_ip))
5109 continue;
5110
5111 mac = zvni_mac_lookup(zvni, &macaddr);
5112 if (ipa_len)
5113 n = zvni_neigh_lookup(zvni, &ip);
5114
5115 if (n && !mac) {
5116 zlog_err("Failed to locate MAC %s for neigh %s VNI %u",
5117 prefix_mac2str(&macaddr, buf, sizeof(buf)),
5118 ipaddr2str(&ip, buf1, sizeof(buf1)), vni);
5119 continue;
5120 }
5121
5122 /* If the remote mac or neighbor doesn't exist there is nothing
5123 * more
5124 * to do. Otherwise, uninstall the entry and then remove it.
5125 */
5126 if (!mac && !n)
5127 continue;
5128
5129 /* Ignore the delete if this mac is a gateway mac-ip */
5130 if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
5131 && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) {
5132 zlog_err(
5133 "%u: Ignore Del for MAC %s neigh %s on VNI %u as it is configured as a default gateway",
5134 zvrf_id(zvrf),
5135 prefix_mac2str(&macaddr, buf, sizeof(buf)),
5136 ipaddr2str(&ip, buf1, sizeof(buf1)), vni);
5137 continue;
5138 }
5139
5140 /* Uninstall remote neighbor or MAC. */
5141 if (n) {
5142 /* When the MAC changes for an IP, it is possible the
5143 * client may
5144 * update the new MAC before trying to delete the "old"
5145 * neighbor
5146 * (as these are two different MACIP routes). Do the
5147 * delete only
5148 * if the MAC matches.
5149 */
5150 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
5151 && (memcmp(n->emac.octet, macaddr.octet, ETH_ALEN)
5152 == 0)) {
5153 zvni_neigh_uninstall(zvni, n);
5154 zvni_neigh_del(zvni, n);
5155 zvni_deref_ip2mac(zvni, mac, 1);
5156 }
5157 } else {
5158 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
5159 zvni_process_neigh_on_remote_mac_del(zvni, mac);
5160
5161 if (list_isempty(mac->neigh_list)) {
5162 zvni_mac_uninstall(zvni, mac, 0);
5163 zvni_mac_del(zvni, mac);
5164 } else
5165 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5166 }
5167 }
5168 }
5169
5170 stream_failure:
5171 return;
5172 }
5173
5174 /*
5175 * Handle message from client to add a remote MACIP for a VNI. This
5176 * could be just the add of a MAC address or the add of a neighbor
5177 * (IP+MAC).
5178 */
5179 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
5180 {
5181 struct stream *s;
5182 vni_t vni;
5183 struct ethaddr macaddr;
5184 struct ipaddr ip;
5185 struct in_addr vtep_ip;
5186 zebra_vni_t *zvni;
5187 zebra_vtep_t *zvtep;
5188 zebra_mac_t *mac, *old_mac;
5189 zebra_neigh_t *n;
5190 unsigned short l = 0, ipa_len;
5191 int update_mac = 0, update_neigh = 0;
5192 char buf[ETHER_ADDR_STRLEN];
5193 char buf1[INET6_ADDRSTRLEN];
5194 uint8_t sticky = 0;
5195 u_char remote_gw = 0;
5196 uint8_t flags = 0;
5197 struct interface *ifp = NULL;
5198 struct zebra_if *zif = NULL;
5199
5200 memset(&macaddr, 0, sizeof(struct ethaddr));
5201 memset(&ip, 0, sizeof(struct ipaddr));
5202 memset(&vtep_ip, 0, sizeof(struct in_addr));
5203
5204 if (!EVPN_ENABLED(zvrf)) {
5205 zlog_warn(
5206 "%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
5207 __PRETTY_FUNCTION__);
5208 return;
5209 }
5210
5211 s = msg;
5212
5213 while (l < hdr->length) {
5214 /* Obtain each remote MACIP and process. */
5215 /* Message contains VNI, followed by MAC followed by IP (if any)
5216 * followed by remote VTEP IP.
5217 */
5218 update_mac = update_neigh = 0;
5219 mac = NULL;
5220 n = NULL;
5221 memset(&ip, 0, sizeof(ip));
5222 STREAM_GETL(s, vni);
5223 STREAM_GET(&macaddr.octet, s, ETH_ALEN);
5224 STREAM_GETL(s, ipa_len);
5225 if (ipa_len) {
5226 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
5227 : IPADDR_V6;
5228 STREAM_GET(&ip.ip.addr, s, ipa_len);
5229 }
5230 l += 4 + ETH_ALEN + 4 + ipa_len;
5231 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
5232 l += IPV4_MAX_BYTELEN;
5233
5234 /* Get flags - sticky mac and/or gateway mac */
5235 STREAM_GETC(s, flags);
5236 sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
5237 remote_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
5238 l++;
5239
5240 if (IS_ZEBRA_DEBUG_VXLAN)
5241 zlog_debug(
5242 "Recv MACIP Add MAC %s IP %s VNI %u Remote VTEP %s with flags 0x%x from %s",
5243 prefix_mac2str(&macaddr, buf, sizeof(buf)),
5244 ipaddr2str(&ip, buf1, sizeof(buf1)), vni,
5245 inet_ntoa(vtep_ip), flags,
5246 zebra_route_string(client->proto));
5247
5248 /* Locate VNI hash entry - expected to exist. */
5249 zvni = zvni_lookup(vni);
5250 if (!zvni) {
5251 zlog_err(
5252 "Failed to locate VNI hash upon remote MACIP ADD, VNI %u",
5253 vni);
5254 continue;
5255 }
5256 ifp = zvni->vxlan_if;
5257 if (!ifp) {
5258 zlog_err(
5259 "VNI %u hash %p doesn't have intf upon remote MACIP add",
5260 vni, zvni);
5261 continue;
5262 }
5263 zif = ifp->info;
5264
5265 /* If down or not mapped to a bridge, we're done. */
5266 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
5267 continue;
5268
5269 /* The remote VTEP specified should normally exist, but it is
5270 * possible
5271 * that when peering comes up, peer may advertise MACIP routes
5272 * before
5273 * advertising type-3 routes.
5274 */
5275 zvtep = zvni_vtep_find(zvni, &vtep_ip);
5276 if (!zvtep) {
5277 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
5278 zlog_err(
5279 "Failed to add remote VTEP, VNI %u zvni %p",
5280 vni, zvni);
5281 continue;
5282 }
5283
5284 zvni_vtep_install(zvni, &vtep_ip);
5285 }
5286
5287 mac = zvni_mac_lookup(zvni, &macaddr);
5288
5289 /* Ignore the update if the mac is already present
5290 as a gateway mac */
5291 if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)
5292 && CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) {
5293 if (IS_ZEBRA_DEBUG_VXLAN)
5294 zlog_debug(
5295 "%u:Ignore MAC %s IP %s on VNI %u as MAC is already configured as gateway mac",
5296 zvrf_id(zvrf),
5297 prefix_mac2str(&macaddr, buf,
5298 sizeof(buf)),
5299 ipaddr2str(&ip, buf1, sizeof(buf1)),
5300 vni);
5301 continue;
5302 }
5303
5304 /* check if the remote MAC is unknown or has a change.
5305 * If so, that needs to be updated first. Note that client could
5306 * install MAC and MACIP separately or just install the latter.
5307 */
5308 if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
5309 || (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0)
5310 != sticky
5311 || (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? 1 : 0)
5312 != remote_gw
5313 || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip))
5314 update_mac = 1;
5315
5316 if (update_mac) {
5317 if (!mac) {
5318 mac = zvni_mac_add(zvni, &macaddr);
5319 if (!mac) {
5320 zlog_warn(
5321 "Failed to add MAC %s VNI %u Remote VTEP %s",
5322 prefix_mac2str(&macaddr, buf,
5323 sizeof(buf)),
5324 vni, inet_ntoa(vtep_ip));
5325 return;
5326 }
5327
5328 /* Is this MAC created for a MACIP? */
5329 if (ipa_len)
5330 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5331 }
5332
5333 /* Set "auto" and "remote" forwarding info. */
5334 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
5335 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
5336 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
5337 mac->fwd_info.r_vtep_ip = vtep_ip;
5338
5339 if (sticky)
5340 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5341 else
5342 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5343
5344 if (remote_gw)
5345 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
5346 else
5347 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
5348
5349 zvni_process_neigh_on_remote_mac_add(zvni, mac);
5350
5351 /* Install the entry. */
5352 zvni_mac_install(zvni, mac);
5353 }
5354
5355 /* If there is no IP, continue - after clearing AUTO flag of
5356 * MAC. */
5357 if (!ipa_len) {
5358 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5359 continue;
5360 }
5361
5362 /* Check if the remote neighbor itself is unknown or has a
5363 * change.
5364 * If so, create or update and then install the entry.
5365 */
5366 n = zvni_neigh_lookup(zvni, &ip);
5367 if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
5368 || (memcmp(&n->emac, &macaddr, sizeof(macaddr)) != 0)
5369 || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip))
5370 update_neigh = 1;
5371
5372 if (update_neigh) {
5373 if (!n) {
5374 n = zvni_neigh_add(zvni, &ip, &macaddr);
5375 if (!n) {
5376 zlog_warn(
5377 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5378 ipaddr2str(&ip, buf1,
5379 sizeof(buf1)),
5380 prefix_mac2str(&macaddr, buf,
5381 sizeof(buf)),
5382 vni, inet_ntoa(vtep_ip));
5383 return;
5384 }
5385
5386 } else if (memcmp(&n->emac, &macaddr, sizeof(macaddr))
5387 != 0) {
5388 /* MAC change, update neigh list for old and new
5389 * mac */
5390 old_mac = zvni_mac_lookup(zvni, &n->emac);
5391 if (old_mac) {
5392 listnode_delete(old_mac->neigh_list, n);
5393 zvni_deref_ip2mac(zvni, old_mac, 1);
5394 }
5395 listnode_add_sort(mac->neigh_list, n);
5396 memcpy(&n->emac, &macaddr, ETH_ALEN);
5397 }
5398
5399 /* Set "remote" forwarding info. */
5400 UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
5401 /* TODO: Handle MAC change. */
5402 n->r_vtep_ip = vtep_ip;
5403 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
5404
5405 /* Set router flag (R-bit) to this Neighbor entry */
5406 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG))
5407 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
5408
5409 /* Install the entry. */
5410 zvni_neigh_install(zvni, n);
5411 }
5412 }
5413
5414 stream_failure:
5415 return;
5416 }
5417
5418 /*
5419 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5420 * us, this must involve a multihoming scenario. Treat this as implicit delete
5421 * of any prior local MAC.
5422 */
5423 int zebra_vxlan_check_del_local_mac(struct interface *ifp,
5424 struct interface *br_if,
5425 struct ethaddr *macaddr, vlanid_t vid)
5426 {
5427 struct zebra_if *zif;
5428 struct zebra_l2info_vxlan *vxl;
5429 vni_t vni;
5430 zebra_vni_t *zvni;
5431 zebra_mac_t *mac;
5432 char buf[ETHER_ADDR_STRLEN];
5433
5434 zif = ifp->info;
5435 assert(zif);
5436 vxl = &zif->l2info.vxl;
5437 vni = vxl->vni;
5438
5439 /* Check if EVPN is enabled. */
5440 if (!is_evpn_enabled())
5441 return 0;
5442
5443 /* Locate hash entry; it is expected to exist. */
5444 zvni = zvni_lookup(vni);
5445 if (!zvni)
5446 return 0;
5447
5448 /* If entry doesn't exist, nothing to do. */
5449 mac = zvni_mac_lookup(zvni, macaddr);
5450 if (!mac)
5451 return 0;
5452
5453 /* Is it a local entry? */
5454 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
5455 return 0;
5456
5457 if (IS_ZEBRA_DEBUG_VXLAN)
5458 zlog_debug(
5459 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5460 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5461 ifp->ifindex, vni);
5462
5463 /* Remove MAC from BGP. */
5464 zvni_mac_send_del_to_client(zvni->vni, macaddr, mac->flags);
5465
5466 /*
5467 * If there are no neigh associated with the mac delete the mac
5468 * else mark it as AUTO for forward reference
5469 */
5470 if (!listcount(mac->neigh_list)) {
5471 zvni_mac_del(zvni, mac);
5472 } else {
5473 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
5474 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5475 }
5476
5477 return 0;
5478 }
5479
5480 /*
5481 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5482 * This can happen because the remote MAC entries are also added as "dynamic",
5483 * so the kernel can ageout the entry.
5484 */
5485 int zebra_vxlan_check_readd_remote_mac(struct interface *ifp,
5486 struct interface *br_if,
5487 struct ethaddr *macaddr, vlanid_t vid)
5488 {
5489 struct zebra_if *zif = NULL;
5490 struct zebra_l2info_vxlan *vxl = NULL;
5491 vni_t vni;
5492 zebra_vni_t *zvni = NULL;
5493 zebra_l3vni_t *zl3vni = NULL;
5494 zebra_mac_t *mac = NULL;
5495 char buf[ETHER_ADDR_STRLEN];
5496
5497 zif = ifp->info;
5498 assert(zif);
5499 vxl = &zif->l2info.vxl;
5500 vni = vxl->vni;
5501
5502 /* Check if EVPN is enabled. */
5503 if (!is_evpn_enabled())
5504 return 0;
5505
5506 /* check if this is a remote RMAC and readd simillar to remote macs */
5507 zl3vni = zl3vni_lookup(vni);
5508 if (zl3vni)
5509 return zebra_vxlan_readd_remote_rmac(zl3vni, macaddr);
5510
5511 /* Locate hash entry; it is expected to exist. */
5512 zvni = zvni_lookup(vni);
5513 if (!zvni)
5514 return 0;
5515
5516 /* If entry doesn't exist, nothing to do. */
5517 mac = zvni_mac_lookup(zvni, macaddr);
5518 if (!mac)
5519 return 0;
5520
5521 /* Is it a remote entry? */
5522 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
5523 return 0;
5524
5525 if (IS_ZEBRA_DEBUG_VXLAN)
5526 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
5527 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5528 ifp->ifindex, vni);
5529
5530 zvni_mac_install(zvni, mac);
5531 return 0;
5532 }
5533
5534 /*
5535 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
5536 */
5537 int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
5538 struct ethaddr *macaddr, vlanid_t vid)
5539 {
5540 zebra_vni_t *zvni;
5541 zebra_mac_t *mac;
5542 char buf[ETHER_ADDR_STRLEN];
5543
5544 /* We are interested in MACs only on ports or (port, VLAN) that
5545 * map to a VNI.
5546 */
5547 zvni = zvni_map_vlan(ifp, br_if, vid);
5548 if (!zvni)
5549 return 0;
5550 if (!zvni->vxlan_if) {
5551 zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL",
5552 zvni->vni, zvni);
5553 return -1;
5554 }
5555
5556 if (IS_ZEBRA_DEBUG_VXLAN)
5557 zlog_debug("Del MAC %s intf %s(%u) VID %u -> VNI %u",
5558 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5559 ifp->ifindex, vid, zvni->vni);
5560
5561 /* If entry doesn't exist, nothing to do. */
5562 mac = zvni_mac_lookup(zvni, macaddr);
5563 if (!mac)
5564 return 0;
5565
5566 /* Is it a local entry? */
5567 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
5568 return 0;
5569
5570 /* Remove MAC from BGP. */
5571 zvni_mac_send_del_to_client(zvni->vni, macaddr, mac->flags);
5572
5573 /* Update all the neigh entries associated with this mac */
5574 zvni_process_neigh_on_local_mac_del(zvni, mac);
5575
5576 /*
5577 * If there are no neigh associated with the mac delete the mac
5578 * else mark it as AUTO for forward reference
5579 */
5580 if (!listcount(mac->neigh_list)) {
5581 zvni_mac_del(zvni, mac);
5582 } else {
5583 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
5584 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5585 }
5586
5587 return 0;
5588 }
5589
5590 /*
5591 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
5592 */
5593 int zebra_vxlan_local_mac_add_update(struct interface *ifp,
5594 struct interface *br_if,
5595 struct ethaddr *macaddr, vlanid_t vid,
5596 uint8_t sticky)
5597 {
5598 zebra_vni_t *zvni;
5599 zebra_mac_t *mac;
5600 char buf[ETHER_ADDR_STRLEN];
5601 int add = 1;
5602 uint8_t mac_sticky;
5603
5604 /* We are interested in MACs only on ports or (port, VLAN) that
5605 * map to a VNI.
5606 */
5607 zvni = zvni_map_vlan(ifp, br_if, vid);
5608 if (!zvni) {
5609 if (IS_ZEBRA_DEBUG_VXLAN)
5610 zlog_debug(
5611 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5612 sticky ? "sticky " : "",
5613 prefix_mac2str(macaddr, buf, sizeof(buf)),
5614 ifp->name, ifp->ifindex, vid);
5615 return 0;
5616 }
5617
5618 if (!zvni->vxlan_if) {
5619 zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD",
5620 zvni->vni, zvni);
5621 return -1;
5622 }
5623
5624 if (IS_ZEBRA_DEBUG_VXLAN)
5625 zlog_debug("Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
5626 sticky ? "sticky " : "",
5627 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
5628 ifp->ifindex, vid, zvni->vni);
5629
5630 /* If same entry already exists, nothing to do. */
5631 mac = zvni_mac_lookup(zvni, macaddr);
5632 if (mac) {
5633 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
5634 mac_sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
5635 ? 1
5636 : 0;
5637
5638
5639 /*
5640 * return if nothing has changed.
5641 * inform bgp if sticky flag has changed
5642 * update locally and do not inform bgp if local
5643 * parameters like interface has changed
5644 */
5645 if (mac_sticky == sticky
5646 && mac->fwd_info.local.ifindex == ifp->ifindex
5647 && mac->fwd_info.local.vid == vid) {
5648 if (IS_ZEBRA_DEBUG_VXLAN)
5649 zlog_debug(
5650 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
5651 "entry exists and has not changed ",
5652 sticky ? "sticky " : "",
5653 prefix_mac2str(macaddr, buf,
5654 sizeof(buf)),
5655 ifp->name, ifp->ifindex, vid,
5656 zvni->vni);
5657 return 0;
5658 } else if (mac_sticky != sticky) {
5659 add = 1;
5660 } else {
5661 add = 0; /* This is an update of local
5662 interface. */
5663 }
5664 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
5665 /*
5666 * If we have already learned the MAC as a remote sticky
5667 * MAC,
5668 * this is a operator error and we must log a warning
5669 */
5670 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) {
5671 zlog_warn(
5672 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
5673 prefix_mac2str(macaddr, buf,
5674 sizeof(buf)),
5675 inet_ntoa(mac->fwd_info.r_vtep_ip),
5676 zvni->vni);
5677 return 0;
5678 }
5679 }
5680 }
5681
5682 if (!mac) {
5683 mac = zvni_mac_add(zvni, macaddr);
5684 if (!mac) {
5685 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
5686 prefix_mac2str(macaddr, buf, sizeof(buf)),
5687 ifp->name, ifp->ifindex, vid);
5688 return -1;
5689 }
5690 }
5691
5692 /* Set "local" forwarding info. */
5693 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
5694 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5695 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
5696 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
5697 mac->fwd_info.local.ifindex = ifp->ifindex;
5698 mac->fwd_info.local.vid = vid;
5699
5700 if (sticky)
5701 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5702 else
5703 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5704
5705 /* Inform BGP if required. */
5706 if (add) {
5707 zvni_process_neigh_on_local_mac_add(zvni, mac);
5708 return zvni_mac_send_add_to_client(zvni->vni, macaddr,
5709 mac->flags);
5710 }
5711
5712 return 0;
5713 }
5714
5715 /*
5716 * Handle message from client to delete a remote VTEP for a VNI.
5717 */
5718 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS)
5719 {
5720 struct stream *s;
5721 unsigned short l = 0;
5722 vni_t vni;
5723 struct in_addr vtep_ip;
5724 zebra_vni_t *zvni;
5725 zebra_vtep_t *zvtep;
5726 struct interface *ifp;
5727 struct zebra_if *zif;
5728
5729 if (!is_evpn_enabled()) {
5730 zlog_warn(
5731 "%s: EVPN is not enabled yet we have received a vtep del command",
5732 __PRETTY_FUNCTION__);
5733 return;
5734 }
5735
5736 if (zvrf_id(zvrf) != VRF_DEFAULT) {
5737 zlog_err("Recv MACIP DEL for non-default VRF %u",
5738 zvrf_id(zvrf));
5739 return;
5740 }
5741
5742 s = msg;
5743
5744 while (l < hdr->length) {
5745 /* Obtain each remote VTEP and process. */
5746 STREAM_GETL(s, vni);
5747 l += 4;
5748 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
5749 l += IPV4_MAX_BYTELEN;
5750
5751 if (IS_ZEBRA_DEBUG_VXLAN)
5752 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
5753 inet_ntoa(vtep_ip), vni,
5754 zebra_route_string(client->proto));
5755
5756 /* Locate VNI hash entry - expected to exist. */
5757 zvni = zvni_lookup(vni);
5758 if (!zvni) {
5759 if (IS_ZEBRA_DEBUG_VXLAN)
5760 zlog_debug(
5761 "Failed to locate VNI hash upon remote VTEP DEL, "
5762 "VNI %u",
5763 vni);
5764 continue;
5765 }
5766
5767 ifp = zvni->vxlan_if;
5768 if (!ifp) {
5769 zlog_err(
5770 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
5771 zvni->vni, zvni);
5772 continue;
5773 }
5774 zif = ifp->info;
5775
5776 /* If down or not mapped to a bridge, we're done. */
5777 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
5778 continue;
5779
5780 /* If the remote VTEP does not exist, there's nothing more to
5781 * do.
5782 * Otherwise, uninstall any remote MACs pointing to this VTEP
5783 * and
5784 * then, the VTEP entry itself and remove it.
5785 */
5786 zvtep = zvni_vtep_find(zvni, &vtep_ip);
5787 if (!zvtep)
5788 continue;
5789
5790 zvni_neigh_del_from_vtep(zvni, 1, &vtep_ip);
5791 zvni_mac_del_from_vtep(zvni, 1, &vtep_ip);
5792 zvni_vtep_uninstall(zvni, &vtep_ip);
5793 zvni_vtep_del(zvni, zvtep);
5794 }
5795
5796 stream_failure:
5797 return;
5798 }
5799
5800 /*
5801 * Handle message from client to add a remote VTEP for a VNI.
5802 */
5803 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)
5804 {
5805 struct stream *s;
5806 unsigned short l = 0;
5807 vni_t vni;
5808 struct in_addr vtep_ip;
5809 zebra_vni_t *zvni;
5810 struct interface *ifp;
5811 struct zebra_if *zif;
5812
5813 if (!is_evpn_enabled()) {
5814 zlog_warn(
5815 "%s: EVPN not enabled yet we received a vtep_add zapi call",
5816 __PRETTY_FUNCTION__);
5817 return;
5818 }
5819
5820 if (zvrf_id(zvrf) != VRF_DEFAULT) {
5821 zlog_err("Recv MACIP ADD for non-default VRF %u",
5822 zvrf_id(zvrf));
5823 return;
5824 }
5825
5826 s = msg;
5827
5828 while (l < hdr->length) {
5829 /* Obtain each remote VTEP and process. */
5830 STREAM_GETL(s, vni);
5831 l += 4;
5832 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
5833 l += IPV4_MAX_BYTELEN;
5834
5835 if (IS_ZEBRA_DEBUG_VXLAN)
5836 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
5837 inet_ntoa(vtep_ip), vni,
5838 zebra_route_string(client->proto));
5839
5840 /* Locate VNI hash entry - expected to exist. */
5841 zvni = zvni_lookup(vni);
5842 if (!zvni) {
5843 zlog_err(
5844 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
5845 vni);
5846 continue;
5847 }
5848
5849 ifp = zvni->vxlan_if;
5850 if (!ifp) {
5851 zlog_err(
5852 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
5853 zvni->vni, zvni);
5854 continue;
5855 }
5856
5857 zif = ifp->info;
5858
5859 /* If down or not mapped to a bridge, we're done. */
5860 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
5861 continue;
5862
5863 /* If the remote VTEP already exists,
5864 there's nothing more to do. */
5865 if (zvni_vtep_find(zvni, &vtep_ip))
5866 continue;
5867
5868 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
5869 zlog_err("Failed to add remote VTEP, VNI %u zvni %p",
5870 vni, zvni);
5871 continue;
5872 }
5873
5874 zvni_vtep_install(zvni, &vtep_ip);
5875 }
5876
5877 stream_failure:
5878 return;
5879 }
5880
5881 /*
5882 * Add/Del gateway macip to evpn
5883 * g/w can be:
5884 * 1. SVI interface on a vlan aware bridge
5885 * 2. SVI interface on a vlan unaware bridge
5886 * 3. vrr interface (MACVLAN) associated to a SVI
5887 * We advertise macip routes for an interface if it is associated to VxLan vlan
5888 */
5889 int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
5890 int add)
5891 {
5892 struct ipaddr ip;
5893 struct ethaddr macaddr;
5894 zebra_vni_t *zvni = NULL;
5895
5896 memset(&ip, 0, sizeof(struct ipaddr));
5897 memset(&macaddr, 0, sizeof(struct ethaddr));
5898
5899 /* Check if EVPN is enabled. */
5900 if (!is_evpn_enabled())
5901 return 0;
5902
5903 if (IS_ZEBRA_IF_MACVLAN(ifp)) {
5904 struct interface *svi_if =
5905 NULL; /* SVI corresponding to the MACVLAN */
5906 struct zebra_if *ifp_zif =
5907 NULL; /* Zebra daemon specific info for MACVLAN */
5908 struct zebra_if *svi_if_zif =
5909 NULL; /* Zebra daemon specific info for SVI*/
5910
5911 ifp_zif = ifp->info;
5912 if (!ifp_zif)
5913 return -1;
5914
5915 /*
5916 * for a MACVLAN interface the link represents the svi_if
5917 */
5918 svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
5919 ifp_zif->link_ifindex);
5920 if (!svi_if) {
5921 zlog_err("MACVLAN %s(%u) without link information",
5922 ifp->name, ifp->ifindex);
5923 return -1;
5924 }
5925
5926 if (IS_ZEBRA_IF_VLAN(svi_if)) {
5927 /*
5928 * If it is a vlan aware bridge then the link gives the
5929 * bridge information
5930 */
5931 struct interface *svi_if_link = NULL;
5932
5933 svi_if_zif = svi_if->info;
5934 if (svi_if_zif) {
5935 svi_if_link = if_lookup_by_index_per_ns(
5936 zebra_ns_lookup(NS_DEFAULT),
5937 svi_if_zif->link_ifindex);
5938 zvni = zvni_from_svi(svi_if, svi_if_link);
5939 }
5940 } else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
5941 /*
5942 * If it is a vlan unaware bridge then svi is the bridge
5943 * itself
5944 */
5945 zvni = zvni_from_svi(svi_if, svi_if);
5946 }
5947 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
5948 struct zebra_if *svi_if_zif =
5949 NULL; /* Zebra daemon specific info for SVI */
5950 struct interface *svi_if_link =
5951 NULL; /* link info for the SVI = bridge info */
5952
5953 svi_if_zif = ifp->info;
5954 if (svi_if_zif) {
5955 svi_if_link = if_lookup_by_index_per_ns(
5956 zebra_ns_lookup(NS_DEFAULT),
5957 svi_if_zif->link_ifindex);
5958 if (svi_if_link)
5959 zvni = zvni_from_svi(ifp, svi_if_link);
5960 }
5961 } else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
5962 zvni = zvni_from_svi(ifp, ifp);
5963 }
5964
5965 if (!zvni)
5966 return 0;
5967
5968 if (!zvni->vxlan_if) {
5969 zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
5970 zvni->vni, zvni);
5971 return -1;
5972 }
5973
5974
5975 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
5976
5977 if (p->family == AF_INET) {
5978 ip.ipa_type = IPADDR_V4;
5979 memcpy(&(ip.ipaddr_v4), &(p->u.prefix4),
5980 sizeof(struct in_addr));
5981 } else if (p->family == AF_INET6) {
5982 ip.ipa_type = IPADDR_V6;
5983 memcpy(&(ip.ipaddr_v6), &(p->u.prefix6),
5984 sizeof(struct in6_addr));
5985 }
5986
5987
5988 if (add)
5989 zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
5990 else
5991 zvni_gw_macip_del(ifp, zvni, &ip);
5992
5993 return 0;
5994 }
5995
5996 /*
5997 * Handle SVI interface going down.
5998 * SVI can be associated to either L3-VNI or L2-VNI.
5999 * For L2-VNI: At this point, this is a NOP since
6000 * the kernel deletes the neighbor entries on this SVI (if any).
6001 * We only need to update the vrf corresponding to zvni.
6002 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
6003 * from bgp
6004 */
6005 int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)
6006 {
6007 zebra_l3vni_t *zl3vni = NULL;
6008
6009 zl3vni = zl3vni_from_svi(ifp, link_if);
6010 if (zl3vni) {
6011
6012 /* process l3-vni down */
6013 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6014
6015 /* remove association with svi-if */
6016 zl3vni->svi_if = NULL;
6017 } else {
6018 zebra_vni_t *zvni = NULL;
6019
6020 /* since we dont have svi corresponding to zvni, we associate it
6021 * to default vrf. Note: the corresponding neigh entries on the
6022 * SVI would have already been deleted */
6023 zvni = zvni_from_svi(ifp, link_if);
6024 if (zvni) {
6025 zvni->vrf_id = VRF_DEFAULT;
6026
6027 /* update the tenant vrf in BGP */
6028 zvni_send_add_to_client(zvni);
6029 }
6030 }
6031 return 0;
6032 }
6033
6034 /*
6035 * Handle SVI interface coming up.
6036 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
6037 * vxlan intf).
6038 * For L2-VNI: we need to install any remote neighbors entried (used for
6039 * apr-suppression)
6040 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
6041 */
6042 int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
6043 {
6044 zebra_vni_t *zvni = NULL;
6045 zebra_l3vni_t *zl3vni = NULL;
6046
6047 zl3vni = zl3vni_from_svi(ifp, link_if);
6048 if (zl3vni) {
6049
6050 /* associate with svi */
6051 zl3vni->svi_if = ifp;
6052
6053 /* process oper-up */
6054 if (is_l3vni_oper_up(zl3vni))
6055 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6056 } else {
6057
6058 /* process SVI up for l2-vni */
6059 struct neigh_walk_ctx n_wctx;
6060
6061 zvni = zvni_from_svi(ifp, link_if);
6062 if (!zvni)
6063 return 0;
6064
6065 if (!zvni->vxlan_if) {
6066 zlog_err("VNI %u hash %p doesn't have intf upon SVI up",
6067 zvni->vni, zvni);
6068 return -1;
6069 }
6070
6071 if (IS_ZEBRA_DEBUG_VXLAN)
6072 zlog_debug(
6073 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
6074 ifp->name, ifp->ifindex, zvni->vni,
6075 vrf_id_to_name(ifp->vrf_id));
6076
6077 /* update the vrf information for l2-vni and inform bgp */
6078 zvni->vrf_id = ifp->vrf_id;
6079 zvni_send_add_to_client(zvni);
6080
6081 /* Install any remote neighbors for this VNI. */
6082 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
6083 n_wctx.zvni = zvni;
6084 hash_iterate(zvni->neigh_table, zvni_install_neigh_hash,
6085 &n_wctx);
6086 }
6087
6088 return 0;
6089 }
6090
6091 /*
6092 * Handle VxLAN interface down
6093 */
6094 int zebra_vxlan_if_down(struct interface *ifp)
6095 {
6096 vni_t vni;
6097 struct zebra_if *zif = NULL;
6098 struct zebra_l2info_vxlan *vxl = NULL;
6099 zebra_l3vni_t *zl3vni = NULL;
6100 zebra_vni_t *zvni;
6101
6102 /* Check if EVPN is enabled. */
6103 if (!is_evpn_enabled())
6104 return 0;
6105
6106 zif = ifp->info;
6107 assert(zif);
6108 vxl = &zif->l2info.vxl;
6109 vni = vxl->vni;
6110
6111 zl3vni = zl3vni_lookup(vni);
6112 if (zl3vni) {
6113 /* process-if-down for l3-vni */
6114 if (IS_ZEBRA_DEBUG_VXLAN)
6115 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp->name,
6116 ifp->ifindex, vni);
6117
6118 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6119 } else {
6120 /* process if-down for l2-vni */
6121 if (IS_ZEBRA_DEBUG_VXLAN)
6122 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp->name,
6123 ifp->ifindex, vni);
6124
6125 /* Locate hash entry; it is expected to exist. */
6126 zvni = zvni_lookup(vni);
6127 if (!zvni) {
6128 zlog_err(
6129 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
6130 ifp->name, ifp->ifindex, vni);
6131 return -1;
6132 }
6133
6134 assert(zvni->vxlan_if == ifp);
6135
6136 /* Delete this VNI from BGP. */
6137 zvni_send_del_to_client(zvni->vni);
6138
6139 /* Free up all neighbors and MACs, if any. */
6140 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
6141 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
6142
6143 /* Free up all remote VTEPs, if any. */
6144 zvni_vtep_del_all(zvni, 1);
6145 }
6146 return 0;
6147 }
6148
6149 /*
6150 * Handle VxLAN interface up - update BGP if required.
6151 */
6152 int zebra_vxlan_if_up(struct interface *ifp)
6153 {
6154 vni_t vni;
6155 struct zebra_if *zif = NULL;
6156 struct zebra_l2info_vxlan *vxl = NULL;
6157 zebra_vni_t *zvni = NULL;
6158 zebra_l3vni_t *zl3vni = NULL;
6159
6160 /* Check if EVPN is enabled. */
6161 if (!is_evpn_enabled())
6162 return 0;
6163
6164 zif = ifp->info;
6165 assert(zif);
6166 vxl = &zif->l2info.vxl;
6167 vni = vxl->vni;
6168
6169 zl3vni = zl3vni_lookup(vni);
6170 if (zl3vni) {
6171
6172 if (IS_ZEBRA_DEBUG_VXLAN)
6173 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp->name,
6174 ifp->ifindex, vni);
6175
6176 /* we need to associate with SVI, if any, we can associate with
6177 * svi-if only after association with vxlan-intf is complete
6178 */
6179 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
6180
6181 if (is_l3vni_oper_up(zl3vni))
6182 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6183 } else {
6184 /* Handle L2-VNI add */
6185 struct interface *vlan_if = NULL;
6186
6187 if (IS_ZEBRA_DEBUG_VXLAN)
6188 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp->name,
6189 ifp->ifindex, vni);
6190
6191 /* Locate hash entry; it is expected to exist. */
6192 zvni = zvni_lookup(vni);
6193 if (!zvni) {
6194 zlog_err(
6195 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
6196 ifp->name, ifp->ifindex, vni);
6197 return -1;
6198 }
6199
6200 assert(zvni->vxlan_if == ifp);
6201 vlan_if = zvni_map_to_svi(vxl->access_vlan,
6202 zif->brslave_info.br_if);
6203 if (vlan_if) {
6204 zvni->vrf_id = vlan_if->vrf_id;
6205 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
6206 if (zl3vni)
6207 listnode_add_sort(zl3vni->l2vnis, zvni);
6208 }
6209
6210 /* If part of a bridge, inform BGP about this VNI. */
6211 /* Also, read and populate local MACs and neighbors. */
6212 if (zif->brslave_info.br_if) {
6213 zvni_send_add_to_client(zvni);
6214 zvni_read_mac_neigh(zvni, ifp);
6215 }
6216 }
6217
6218 return 0;
6219 }
6220
6221 /*
6222 * Handle VxLAN interface delete. Locate and remove entry in hash table
6223 * and update BGP, if required.
6224 */
6225 int zebra_vxlan_if_del(struct interface *ifp)
6226 {
6227 vni_t vni;
6228 struct zebra_if *zif = NULL;
6229 struct zebra_l2info_vxlan *vxl = NULL;
6230 zebra_vni_t *zvni = NULL;
6231 zebra_l3vni_t *zl3vni = NULL;
6232
6233 /* Check if EVPN is enabled. */
6234 if (!is_evpn_enabled())
6235 return 0;
6236
6237 zif = ifp->info;
6238 assert(zif);
6239 vxl = &zif->l2info.vxl;
6240 vni = vxl->vni;
6241
6242 zl3vni = zl3vni_lookup(vni);
6243 if (zl3vni) {
6244
6245 if (IS_ZEBRA_DEBUG_VXLAN)
6246 zlog_debug("Del L3-VNI %u intf %s(%u)", vni, ifp->name,
6247 ifp->ifindex);
6248
6249 /* process oper-down for l3-vni */
6250 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6251
6252 /* remove the association with vxlan_if */
6253 memset(&zl3vni->local_vtep_ip, 0, sizeof(struct in_addr));
6254 zl3vni->vxlan_if = NULL;
6255 } else {
6256
6257 /* process if-del for l2-vni*/
6258 if (IS_ZEBRA_DEBUG_VXLAN)
6259 zlog_debug("Del L2-VNI %u intf %s(%u)", vni, ifp->name,
6260 ifp->ifindex);
6261
6262 /* Locate hash entry; it is expected to exist. */
6263 zvni = zvni_lookup(vni);
6264 if (!zvni) {
6265 zlog_err(
6266 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6267 ifp->name, ifp->ifindex, vni);
6268 return 0;
6269 }
6270
6271 /* remove from l3-vni list */
6272 zl3vni = zl3vni_from_vrf(zvni->vrf_id);
6273 if (zl3vni)
6274 listnode_delete(zl3vni->l2vnis, zvni);
6275
6276 /* Delete VNI from BGP. */
6277 zvni_send_del_to_client(zvni->vni);
6278
6279 /* Free up all neighbors and MAC, if any. */
6280 zvni_neigh_del_all(zvni, 0, 0, DEL_ALL_NEIGH);
6281 zvni_mac_del_all(zvni, 0, 0, DEL_ALL_MAC);
6282
6283 /* Free up all remote VTEPs, if any. */
6284 zvni_vtep_del_all(zvni, 0);
6285
6286 /* Delete the hash entry. */
6287 if (zvni_del(zvni)) {
6288 zlog_err("Failed to del VNI hash %p, IF %s(%u) VNI %u",
6289 zvni, ifp->name, ifp->ifindex, zvni->vni);
6290 return -1;
6291 }
6292 }
6293 return 0;
6294 }
6295
6296 /*
6297 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6298 */
6299 int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
6300 {
6301 vni_t vni;
6302 struct zebra_if *zif = NULL;
6303 struct zebra_l2info_vxlan *vxl = NULL;
6304 zebra_vni_t *zvni = NULL;
6305 zebra_l3vni_t *zl3vni = NULL;
6306
6307 /* Check if EVPN is enabled. */
6308 if (!is_evpn_enabled())
6309 return 0;
6310
6311 zif = ifp->info;
6312 assert(zif);
6313 vxl = &zif->l2info.vxl;
6314 vni = vxl->vni;
6315
6316 zl3vni = zl3vni_lookup(vni);
6317 if (zl3vni) {
6318
6319 if (IS_ZEBRA_DEBUG_VXLAN)
6320 zlog_debug(
6321 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6322 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
6323 inet_ntoa(vxl->vtep_ip),
6324 zif->brslave_info.bridge_ifindex, chgflags);
6325
6326 /* Removed from bridge? Cleanup and return */
6327 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
6328 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
6329 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6330 return 0;
6331 }
6332
6333 /* access-vlan change - process oper down, associate with new
6334 * svi_if and then process oper up again
6335 */
6336 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
6337 if (if_is_operative(ifp)) {
6338 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6339 zl3vni->svi_if = NULL;
6340 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
6341 zl3vni->local_vtep_ip = vxl->vtep_ip;
6342 if (is_l3vni_oper_up(zl3vni))
6343 zebra_vxlan_process_l3vni_oper_up(
6344 zl3vni);
6345 }
6346 }
6347
6348 /*
6349 * local-ip change - process oper down, associate with new
6350 * local-ip and then process oper up again
6351 */
6352 if (chgflags & ZEBRA_VXLIF_LOCAL_IP_CHANGE) {
6353 if (if_is_operative(ifp)) {
6354 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6355 zl3vni->local_vtep_ip = vxl->vtep_ip;
6356 if (is_l3vni_oper_up(zl3vni))
6357 zebra_vxlan_process_l3vni_oper_up(
6358 zl3vni);
6359 }
6360 }
6361
6362 /* Update local tunnel IP. */
6363 zl3vni->local_vtep_ip = vxl->vtep_ip;
6364
6365 /* if we have a valid new master, process l3-vni oper up */
6366 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) {
6367 if (if_is_operative(ifp) && is_l3vni_oper_up(zl3vni))
6368 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6369 }
6370 } else {
6371
6372 /* Update VNI hash. */
6373 zvni = zvni_lookup(vni);
6374 if (!zvni) {
6375 zlog_err(
6376 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6377 ifp->name, ifp->ifindex, vni);
6378 return -1;
6379 }
6380
6381 if (IS_ZEBRA_DEBUG_VXLAN)
6382 zlog_debug(
6383 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6384 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
6385 inet_ntoa(vxl->vtep_ip),
6386 zif->brslave_info.bridge_ifindex, chgflags);
6387
6388 /* Removed from bridge? Cleanup and return */
6389 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
6390 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
6391 /* Delete from client, remove all remote VTEPs */
6392 /* Also, free up all MACs and neighbors. */
6393 zvni_send_del_to_client(zvni->vni);
6394 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
6395 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
6396 zvni_vtep_del_all(zvni, 1);
6397 return 0;
6398 }
6399
6400 /* Handle other changes. */
6401 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
6402 /* Remove all existing local neigh and MACs for this VNI
6403 * (including from BGP)
6404 */
6405 zvni_neigh_del_all(zvni, 0, 1, DEL_LOCAL_MAC);
6406 zvni_mac_del_all(zvni, 0, 1, DEL_LOCAL_MAC);
6407 }
6408
6409 zvni->local_vtep_ip = vxl->vtep_ip;
6410 zvni->vxlan_if = ifp;
6411
6412 /* Take further actions needed.
6413 * Note that if we are here, there is a change of interest.
6414 */
6415 /* If down or not mapped to a bridge, we're done. */
6416 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
6417 return 0;
6418
6419 /* Inform BGP, if there is a change of interest. */
6420 if (chgflags
6421 & (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE))
6422 zvni_send_add_to_client(zvni);
6423
6424 /* If there is a valid new master or a VLAN mapping change,
6425 * read and populate local MACs and neighbors.
6426 * Also, reinstall any remote MACs and neighbors
6427 * for this VNI (based on new VLAN).
6428 */
6429 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
6430 zvni_read_mac_neigh(zvni, ifp);
6431 else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
6432 struct mac_walk_ctx m_wctx;
6433 struct neigh_walk_ctx n_wctx;
6434
6435 zvni_read_mac_neigh(zvni, ifp);
6436
6437 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
6438 m_wctx.zvni = zvni;
6439 hash_iterate(zvni->mac_table, zvni_install_mac_hash,
6440 &m_wctx);
6441
6442 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
6443 n_wctx.zvni = zvni;
6444 hash_iterate(zvni->neigh_table, zvni_install_neigh_hash,
6445 &n_wctx);
6446 }
6447 }
6448
6449 return 0;
6450 }
6451
6452 /*
6453 * Handle VxLAN interface add.
6454 */
6455 int zebra_vxlan_if_add(struct interface *ifp)
6456 {
6457 vni_t vni;
6458 struct zebra_if *zif = NULL;
6459 struct zebra_l2info_vxlan *vxl = NULL;
6460 zebra_vni_t *zvni = NULL;
6461 zebra_l3vni_t *zl3vni = NULL;
6462
6463 /* Check if EVPN is enabled. */
6464 if (!is_evpn_enabled())
6465 return 0;
6466
6467 zif = ifp->info;
6468 assert(zif);
6469 vxl = &zif->l2info.vxl;
6470 vni = vxl->vni;
6471
6472 zl3vni = zl3vni_lookup(vni);
6473 if (zl3vni) {
6474
6475 /* process if-add for l3-vni*/
6476 if (IS_ZEBRA_DEBUG_VXLAN)
6477 zlog_debug(
6478 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6479 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
6480 inet_ntoa(vxl->vtep_ip),
6481 zif->brslave_info.bridge_ifindex);
6482
6483 /* associate with vxlan_if */
6484 zl3vni->local_vtep_ip = vxl->vtep_ip;
6485 zl3vni->vxlan_if = ifp;
6486
6487 /* Associate with SVI, if any. We can associate with svi-if only
6488 * after association with vxlan_if is complete */
6489 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
6490
6491 if (is_l3vni_oper_up(zl3vni))
6492 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6493 } else {
6494
6495 /* process if-add for l2-vni */
6496 struct interface *vlan_if = NULL;
6497
6498 /* Create or update VNI hash. */
6499 zvni = zvni_lookup(vni);
6500 if (!zvni) {
6501 zvni = zvni_add(vni);
6502 if (!zvni) {
6503 zlog_err(
6504 "Failed to add VNI hash, IF %s(%u) VNI %u",
6505 ifp->name, ifp->ifindex, vni);
6506 return -1;
6507 }
6508 }
6509
6510 zvni->local_vtep_ip = vxl->vtep_ip;
6511 zvni->vxlan_if = ifp;
6512 vlan_if = zvni_map_to_svi(vxl->access_vlan,
6513 zif->brslave_info.br_if);
6514 if (vlan_if) {
6515 zvni->vrf_id = vlan_if->vrf_id;
6516 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
6517 if (zl3vni)
6518 listnode_add_sort(zl3vni->l2vnis, zvni);
6519 }
6520
6521 if (IS_ZEBRA_DEBUG_VXLAN)
6522 zlog_debug(
6523 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6524 vni,
6525 vlan_if ? vrf_id_to_name(vlan_if->vrf_id)
6526 : "Default",
6527 ifp->name, ifp->ifindex, vxl->access_vlan,
6528 inet_ntoa(vxl->vtep_ip),
6529 zif->brslave_info.bridge_ifindex);
6530
6531 /* If down or not mapped to a bridge, we're done. */
6532 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
6533 return 0;
6534
6535 /* Inform BGP */
6536 zvni_send_add_to_client(zvni);
6537
6538 /* Read and populate local MACs and neighbors */
6539 zvni_read_mac_neigh(zvni, ifp);
6540 }
6541
6542 return 0;
6543 }
6544
6545 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
6546 char *err, int err_str_sz, int filter,
6547 int add)
6548 {
6549 zebra_l3vni_t *zl3vni = NULL;
6550 struct zebra_vrf *zvrf_default = NULL;
6551
6552 zvrf_default = zebra_vrf_lookup_by_id(VRF_DEFAULT);
6553 if (!zvrf_default)
6554 return -1;
6555
6556 if (IS_ZEBRA_DEBUG_VXLAN)
6557 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf), vni,
6558 add ? "ADD" : "DEL");
6559
6560 if (add) {
6561
6562 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
6563
6564 /* check if the vni is already present under zvrf */
6565 if (zvrf->l3vni) {
6566 snprintf(err, err_str_sz,
6567 "VNI is already configured under the vrf");
6568 return -1;
6569 }
6570
6571 /* check if this VNI is already present in the system */
6572 zl3vni = zl3vni_lookup(vni);
6573 if (zl3vni) {
6574 snprintf(err, err_str_sz,
6575 "VNI is already configured as L3-VNI");
6576 return -1;
6577 }
6578
6579 /* add the L3-VNI to the global table */
6580 zl3vni = zl3vni_add(vni, zvrf_id(zvrf));
6581 if (!zl3vni) {
6582 snprintf(err, err_str_sz, "Could not add L3-VNI");
6583 return -1;
6584 }
6585
6586 /* associate the vrf with vni */
6587 zvrf->l3vni = vni;
6588
6589 /* set the filter in l3vni to denote if we are using l3vni only
6590 * for prefix routes
6591 */
6592 if (filter)
6593 SET_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY);
6594
6595 /* associate with vxlan-intf;
6596 * we need to associate with the vxlan-intf first
6597 */
6598 zl3vni->vxlan_if = zl3vni_map_to_vxlan_if(zl3vni);
6599
6600 /* associate with corresponding SVI interface, we can associate
6601 * with svi-if only after vxlan interface association is
6602 * complete
6603 */
6604 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
6605
6606 /* formulate l2vni list */
6607 hash_iterate(zvrf_default->vni_table, zvni_add_to_l3vni_list,
6608 zl3vni);
6609
6610 if (is_l3vni_oper_up(zl3vni))
6611 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6612
6613 } else {
6614 zl3vni = zl3vni_lookup(vni);
6615 if (!zl3vni) {
6616 snprintf(err, err_str_sz, "VNI doesn't exist");
6617 return -1;
6618 }
6619
6620 if (filter && !CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)) {
6621 snprintf(err, ERR_STR_SZ,
6622 "prefix-routes-only is not set for the vni");
6623 return -1;
6624 }
6625
6626 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6627
6628 /* delete and uninstall all rmacs */
6629 hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry,
6630 zl3vni);
6631
6632 /* delete and uninstall all next-hops */
6633 hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry,
6634 zl3vni);
6635
6636 zvrf->l3vni = 0;
6637 zl3vni_del(zl3vni);
6638
6639 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
6640 }
6641 return 0;
6642 }
6643
6644 int zebra_vxlan_vrf_enable(struct zebra_vrf *zvrf)
6645 {
6646 zebra_l3vni_t *zl3vni = NULL;
6647
6648 if (zvrf->l3vni)
6649 zl3vni = zl3vni_lookup(zvrf->l3vni);
6650 if (!zl3vni)
6651 return 0;
6652
6653 zl3vni->vrf_id = zvrf_id(zvrf);
6654 if (is_l3vni_oper_up(zl3vni))
6655 zebra_vxlan_process_l3vni_oper_up(zl3vni);
6656 return 0;
6657 }
6658
6659 int zebra_vxlan_vrf_disable(struct zebra_vrf *zvrf)
6660 {
6661 zebra_l3vni_t *zl3vni = NULL;
6662
6663 if (zvrf->l3vni)
6664 zl3vni = zl3vni_lookup(zvrf->l3vni);
6665 if (!zl3vni)
6666 return 0;
6667
6668 zl3vni->vrf_id = VRF_UNKNOWN;
6669 zebra_vxlan_process_l3vni_oper_down(zl3vni);
6670 return 0;
6671 }
6672
6673 int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
6674 {
6675 zebra_l3vni_t *zl3vni = NULL;
6676 vni_t vni;
6677
6678 if (zvrf->l3vni)
6679 zl3vni = zl3vni_lookup(zvrf->l3vni);
6680 if (!zl3vni)
6681 return 0;
6682
6683 vni = zl3vni->vni;
6684 zl3vni_del(zl3vni);
6685 zebra_vxlan_handle_vni_transition(zvrf, vni, 0);
6686
6687 return 0;
6688 }
6689
6690 /*
6691 * Handle message from client to enable/disable advertisement of g/w macip
6692 * routes
6693 */
6694 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)
6695 {
6696 struct stream *s;
6697 int advertise;
6698 vni_t vni = 0;
6699 zebra_vni_t *zvni = NULL;
6700 struct interface *ifp = NULL;
6701 struct zebra_if *zif = NULL;
6702 struct zebra_l2info_vxlan zl2_info;
6703 struct interface *vlan_if = NULL;
6704
6705 if (zvrf_id(zvrf) != VRF_DEFAULT) {
6706 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6707 zvrf_id(zvrf));
6708 return;
6709 }
6710
6711 s = msg;
6712 STREAM_GETC(s, advertise);
6713 vni = stream_get3(s);
6714
6715 zvni = zvni_lookup(vni);
6716 if (!zvni)
6717 return;
6718
6719 if (zvni->advertise_subnet == advertise)
6720 return;
6721
6722 if (IS_ZEBRA_DEBUG_VXLAN)
6723 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
6724 advertise ? "enabled" : "disabled", vni,
6725 zvni->advertise_subnet ? "enabled" : "disabled");
6726
6727
6728 zvni->advertise_subnet = advertise;
6729
6730 ifp = zvni->vxlan_if;
6731 if (!ifp)
6732 return;
6733
6734 zif = ifp->info;
6735
6736 /* If down or not mapped to a bridge, we're done. */
6737 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
6738 return;
6739
6740 zl2_info = zif->l2info.vxl;
6741
6742 vlan_if =
6743 zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
6744 if (!vlan_if)
6745 return;
6746
6747 if (zvni->advertise_subnet)
6748 zvni_advertise_subnet(zvni, vlan_if, 1);
6749 else
6750 zvni_advertise_subnet(zvni, vlan_if, 0);
6751
6752 stream_failure:
6753 return;
6754 }
6755
6756 /*
6757 * Handle message from client to enable/disable advertisement of g/w macip
6758 * routes
6759 */
6760 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)
6761 {
6762 struct stream *s;
6763 int advertise;
6764 vni_t vni = 0;
6765 zebra_vni_t *zvni = NULL;
6766 struct interface *ifp = NULL;
6767
6768 if (zvrf_id(zvrf) != VRF_DEFAULT) {
6769 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6770 zvrf_id(zvrf));
6771 return;
6772 }
6773
6774 s = msg;
6775 STREAM_GETC(s, advertise);
6776 STREAM_GETL(s, vni);
6777
6778 if (!vni) {
6779 if (IS_ZEBRA_DEBUG_VXLAN)
6780 zlog_debug("EVPN gateway macip Adv %s, currently %s",
6781 advertise ? "enabled" : "disabled",
6782 advertise_gw_macip_enabled(NULL)
6783 ? "enabled"
6784 : "disabled");
6785
6786 if (zvrf->advertise_gw_macip == advertise)
6787 return;
6788
6789 zvrf->advertise_gw_macip = advertise;
6790
6791 if (advertise_gw_macip_enabled(zvni))
6792 hash_iterate(zvrf->vni_table,
6793 zvni_gw_macip_add_for_vni_hash, NULL);
6794 else
6795 hash_iterate(zvrf->vni_table,
6796 zvni_gw_macip_del_for_vni_hash, NULL);
6797
6798 } else {
6799 struct zebra_if *zif = NULL;
6800 struct zebra_l2info_vxlan zl2_info;
6801 struct interface *vlan_if = NULL;
6802 struct interface *vrr_if = NULL;
6803
6804 zvni = zvni_lookup(vni);
6805 if (!zvni)
6806 return;
6807
6808 if (IS_ZEBRA_DEBUG_VXLAN)
6809 zlog_debug(
6810 "EVPN gateway macip Adv %s on VNI %d , currently %s",
6811 advertise ? "enabled" : "disabled", vni,
6812 advertise_gw_macip_enabled(zvni) ? "enabled"
6813 : "disabled");
6814
6815 if (zvni->advertise_gw_macip == advertise)
6816 return;
6817
6818 zvni->advertise_gw_macip = advertise;
6819
6820 ifp = zvni->vxlan_if;
6821 if (!ifp)
6822 return;
6823
6824 zif = ifp->info;
6825
6826 /* If down or not mapped to a bridge, we're done. */
6827 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
6828 return;
6829
6830 zl2_info = zif->l2info.vxl;
6831
6832 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
6833 zif->brslave_info.br_if);
6834 if (!vlan_if)
6835 return;
6836
6837 if (advertise_gw_macip_enabled(zvni)) {
6838 /* Add primary SVI MAC-IP */
6839 zvni_add_macip_for_intf(vlan_if, zvni);
6840
6841 /* Add VRR MAC-IP - if any*/
6842 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
6843 if (vrr_if)
6844 zvni_add_macip_for_intf(vrr_if, zvni);
6845 } else {
6846 /* Del primary MAC-IP */
6847 zvni_del_macip_for_intf(vlan_if, zvni);
6848
6849 /* Del VRR MAC-IP - if any*/
6850 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
6851 if (vrr_if)
6852 zvni_del_macip_for_intf(vrr_if, zvni);
6853 }
6854 }
6855
6856 stream_failure:
6857 return;
6858 }
6859
6860
6861 /*
6862 * Handle message from client to learn (or stop learning) about VNIs and MACs.
6863 * When enabled, the VNI hash table will be built and MAC FDB table read;
6864 * when disabled, the entries should be deleted and remote VTEPs and MACs
6865 * uninstalled from the kernel.
6866 */
6867 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
6868 {
6869 struct stream *s = NULL;
6870 int advertise = 0;
6871 struct zebra_ns *zns = NULL;
6872
6873 if (zvrf_id(zvrf) != VRF_DEFAULT) {
6874 zlog_err("EVPN VNI Adv for non-default VRF %u", zvrf_id(zvrf));
6875 return;
6876 }
6877
6878 s = msg;
6879 STREAM_GETC(s, advertise);
6880
6881 if (IS_ZEBRA_DEBUG_VXLAN)
6882 zlog_debug("EVPN VNI Adv %s, currently %s",
6883 advertise ? "enabled" : "disabled",
6884 is_evpn_enabled() ? "enabled" : "disabled");
6885
6886 if (zvrf->advertise_all_vni == advertise)
6887 return;
6888
6889 zvrf->advertise_all_vni = advertise;
6890 if (is_evpn_enabled()) {
6891 /* Build VNI hash table and inform BGP. */
6892 zvni_build_hash_table();
6893
6894 /* Add all SVI (L3 GW) MACs to BGP*/
6895 hash_iterate(zvrf->vni_table, zvni_gw_macip_add_for_vni_hash,
6896 NULL);
6897
6898 /* Read the MAC FDB */
6899 macfdb_read(zvrf->zns);
6900
6901 /* Read neighbors */
6902 neigh_read(zvrf->zns);
6903 } else {
6904 /* Cleanup VTEPs for all VNIs - uninstall from
6905 * kernel and free entries.
6906 */
6907 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
6908
6909 /* cleanup all l3vnis */
6910 zns = zebra_ns_lookup(NS_DEFAULT);
6911 if (!zns)
6912 return;
6913
6914 hash_iterate(zns->l3vni_table, zl3vni_cleanup_all, NULL);
6915 }
6916
6917 stream_failure:
6918 return;
6919 }
6920
6921 /*
6922 * Allocate VNI hash table for this VRF and do other initialization.
6923 * NOTE: Currently supported only for default VRF.
6924 */
6925 void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
6926 {
6927 if (!zvrf)
6928 return;
6929 zvrf->vni_table = hash_create(vni_hash_keymake, vni_hash_cmp,
6930 "Zebra VRF VNI Table");
6931 }
6932
6933 /* Cleanup VNI info, but don't free the table. */
6934 void zebra_vxlan_cleanup_tables(struct zebra_vrf *zvrf)
6935 {
6936 if (!zvrf)
6937 return;
6938 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
6939 }
6940
6941 /* Close all VNI handling */
6942 void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
6943 {
6944 if (!zvrf)
6945 return;
6946 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
6947 hash_free(zvrf->vni_table);
6948 }
6949
6950 /* init the l3vni table */
6951 void zebra_vxlan_ns_init(struct zebra_ns *zns)
6952 {
6953 zns->l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp,
6954 "Zebra VRF L3 VNI table");
6955 }
6956
6957 /* free l3vni table */
6958 void zebra_vxlan_ns_disable(struct zebra_ns *zns)
6959 {
6960 hash_free(zns->l3vni_table);
6961 }
6962
6963 /* get the l3vni svi ifindex */
6964 ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id)
6965 {
6966 zebra_l3vni_t *zl3vni = NULL;
6967
6968 zl3vni = zl3vni_from_vrf(vrf_id);
6969 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
6970 return 0;
6971
6972 return zl3vni->svi_if->ifindex;
6973 }