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