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