2 * Zebra EVPN for VxLAN code
3 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
5 * This file is part of FRR.
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
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.
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
37 #include "zebra/rib.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"
51 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI
, "VNI hash");
52 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI_VTEP
, "VNI remote VTEP");
53 DEFINE_MTYPE_STATIC(ZEBRA
, MAC
, "VNI MAC");
54 DEFINE_MTYPE_STATIC(ZEBRA
, NEIGH
, "VNI Neighbor");
59 /* static function declarations */
60 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
61 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
);
62 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
64 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
);
65 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
);
66 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
);
67 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
68 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[]);
70 static int zvni_macip_send_msg_to_client(struct zebra_vrf
*zvrf
, vni_t vni
,
71 struct ethaddr
*macaddr
,
72 struct ipaddr
*ip
, u_char flags
,
74 static unsigned int neigh_hash_keymake(void *p
);
75 static int neigh_cmp(const void *p1
, const void *p2
);
76 static void *zvni_neigh_alloc(void *p
);
77 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
79 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
80 static int zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
);
81 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
82 struct in_addr
*r_vtep_ip
);
83 static void zvni_neigh_del_all(struct zebra_vrf
*zvrf
, zebra_vni_t
*zvni
,
84 int uninstall
, int upd_client
, u_int32_t flags
);
85 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
);
86 static int zvni_neigh_send_add_to_client(struct zebra_vrf
*zvrf
, vni_t vni
,
88 struct ethaddr
*macaddr
, u_char flags
);
89 static int zvni_neigh_send_del_to_client(struct zebra_vrf
*zvrf
, vni_t vni
,
91 struct ethaddr
*macaddr
, u_char flags
);
92 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
93 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
94 static zebra_vni_t
*zvni_map_svi(struct interface
*ifp
,
95 struct interface
*br_if
);
96 static struct interface
*zvni_map_to_svi(struct zebra_vrf
*zvrf
, vlanid_t vid
,
97 struct interface
*br_if
);
99 static unsigned int mac_hash_keymake(void *p
);
100 static int mac_cmp(const void *p1
, const void *p2
);
101 static void *zvni_mac_alloc(void *p
);
102 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
103 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
104 static int zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
);
105 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
106 struct in_addr
*r_vtep_ip
);
107 static void zvni_mac_del_all(struct zebra_vrf
*zvrf
, zebra_vni_t
*zvni
,
108 int uninstall
, int upd_client
, u_int32_t flags
);
109 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
110 static int zvni_mac_send_add_to_client(struct zebra_vrf
*zvrf
, vni_t vni
,
111 struct ethaddr
*macaddr
, u_char flags
);
112 static int zvni_mac_send_del_to_client(struct zebra_vrf
*zvrf
, vni_t vni
,
113 struct ethaddr
*macaddr
, u_char flags
);
114 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
115 struct interface
*br_if
, vlanid_t vid
);
116 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
117 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
);
118 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
);
120 static unsigned int vni_hash_keymake(void *p
);
121 static int vni_hash_cmp(const void *p1
, const void *p2
);
122 static void *zvni_alloc(void *p
);
123 static zebra_vni_t
*zvni_lookup(struct zebra_vrf
*zvrf
, vni_t vni
);
124 static zebra_vni_t
*zvni_add(struct zebra_vrf
*zvrf
, vni_t vni
);
125 static int zvni_del(struct zebra_vrf
*zvrf
, zebra_vni_t
*zvni
);
126 static int zvni_send_add_to_client(struct zebra_vrf
*zvrf
, zebra_vni_t
*zvni
);
127 static int zvni_send_del_to_client(struct zebra_vrf
*zvrf
, vni_t vni
);
128 static void zvni_build_hash_table(struct zebra_vrf
*zvrf
);
129 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
130 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
131 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
132 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
133 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
134 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
135 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
136 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
137 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
138 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
139 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
140 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
142 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
143 static int advertise_gw_macip_enabled(struct zebra_vrf
*zvrf
,
145 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
148 /* Private functions */
150 static int advertise_gw_macip_enabled(struct zebra_vrf
*zvrf
, zebra_vni_t
*zvni
)
152 if (zvrf
&& zvrf
->advertise_gw_macip
)
155 if (zvni
&& zvni
->advertise_gw_macip
)
162 * Helper function to determine maximum width of neighbor IP address for
163 * display - just because we're dealing with IPv6 addresses that can
166 static void zvni_find_neigh_addr_width(struct hash_backet
*backet
, void *ctxt
)
169 char buf
[INET6_ADDRSTRLEN
];
170 struct neigh_walk_ctx
*wctx
= ctxt
;
173 n
= (zebra_neigh_t
*)backet
->data
;
177 ipaddr2str(&n
->ip
, buf
, sizeof(buf
)), width
= strlen(buf
);
178 if (width
> wctx
->addr_width
)
179 wctx
->addr_width
= width
;
183 * Print a specific neighbor entry.
185 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
188 char buf1
[ETHER_ADDR_STRLEN
];
189 char buf2
[INET6_ADDRSTRLEN
];
191 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
192 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
193 vty
= (struct vty
*)ctxt
;
195 vty_out(vty
, "IP: %s\n",
196 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
197 vty_out(vty
, " MAC: %s",
198 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
200 json_object_string_add(json
, "ip", buf2
);
201 json_object_string_add(json
, "mac", buf1
);
203 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
205 vty_out(vty
, " Remote VTEP: %s",
206 inet_ntoa(n
->r_vtep_ip
));
208 json_object_string_add(json
, "remoteVtep",
209 inet_ntoa(n
->r_vtep_ip
));
211 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
214 vty_out(vty
, " State: %s",
215 IS_ZEBRA_NEIGH_ACTIVE(n
) ? "Active"
224 * Print neighbor hash entry - called for display of all neighbors.
226 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
229 json_object
*json_vni
= NULL
, *json_row
= NULL
;
231 char buf1
[ETHER_ADDR_STRLEN
];
232 char buf2
[INET6_ADDRSTRLEN
];
233 struct neigh_walk_ctx
*wctx
= ctxt
;
236 json_vni
= wctx
->json
;
237 n
= (zebra_neigh_t
*)backet
->data
;
242 json_row
= json_object_new_object();
244 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
245 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
246 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)
247 && !(wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)) {
248 if (json_vni
== NULL
) {
249 vty_out(vty
, "%*s %-6s %-17s\n", -wctx
->addr_width
,
250 buf2
, "local", buf1
);
252 json_object_string_add(json_row
, "type", "local");
253 json_object_string_add(json_row
, "mac", buf1
);
257 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) {
258 if (IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
)) {
259 if (json_vni
== NULL
) {
260 if (wctx
->count
== 0)
262 "%*s %-6s %-17s %-21s\n",
265 "MAC", "Remote VTEP");
266 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
267 -wctx
->addr_width
, buf2
,
269 inet_ntoa(n
->r_vtep_ip
));
271 json_object_string_add(json_row
, "type",
273 json_object_string_add(json_row
, "mac",
275 json_object_string_add(
276 json_row
, "remoteVtep",
277 inet_ntoa(n
->r_vtep_ip
));
282 if (json_vni
== NULL
) {
283 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
284 -wctx
->addr_width
, buf2
, "remote", buf1
,
285 inet_ntoa(n
->r_vtep_ip
));
287 json_object_string_add(json_row
, "type",
289 json_object_string_add(json_row
, "mac", buf1
);
290 json_object_string_add(json_row
, "remoteVtep",
291 inet_ntoa(n
->r_vtep_ip
));
298 json_object_object_add(json_vni
, buf2
, json_row
);
302 * Print neighbors for all VNI.
304 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
308 json_object
*json
= NULL
, *json_vni
= NULL
;
311 struct neigh_walk_ctx wctx
;
312 char vni_str
[VNI_STR_LEN
];
314 vty
= (struct vty
*)args
[0];
315 json
= (json_object
*)args
[1];
317 zvni
= (zebra_vni_t
*)backet
->data
;
320 vty_out(vty
, "{}\n");
323 num_neigh
= hashcount(zvni
->neigh_table
);
326 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
327 zvni
->vni
, num_neigh
);
329 json_vni
= json_object_new_object();
330 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
331 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
335 json_object_object_add(json
, vni_str
, json_vni
);
339 /* Since we have IPv6 addresses to deal with which can vary widely in
340 * size, we try to be a bit more elegant in display by first computing
343 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
346 wctx
.addr_width
= 15;
347 wctx
.json
= json_vni
;
348 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
351 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
352 "Type", "MAC", "Remote VTEP");
353 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
356 json_object_object_add(json
, vni_str
, json_vni
);
360 * Print a specific MAC entry.
362 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
)
365 zebra_neigh_t
*n
= NULL
;
366 struct listnode
*node
= NULL
;
368 char buf2
[INET6_ADDRSTRLEN
];
370 vty
= (struct vty
*)ctxt
;
371 vty_out(vty
, "MAC: %s",
372 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
)));
373 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
374 struct zebra_ns
*zns
;
375 struct interface
*ifp
;
378 ifindex
= mac
->fwd_info
.local
.ifindex
;
379 zns
= zebra_ns_lookup(NS_DEFAULT
);
380 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
381 if (!ifp
) // unexpected
383 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
384 if (mac
->fwd_info
.local
.vid
)
385 vty_out(vty
, " VLAN: %u", mac
->fwd_info
.local
.vid
);
386 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
387 vty_out(vty
, " Remote VTEP: %s",
388 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
389 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
390 vty_out(vty
, " Auto Mac ");
394 /* print all the associated neigh */
395 vty_out(vty
, " Neighbors:\n");
396 if (!listcount(mac
->neigh_list
))
397 vty_out(vty
, " No Neighbors\n");
399 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
400 vty_out(vty
, " %s %s\n",
401 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
402 CHECK_FLAG(n
->flags
, ZEBRA_MAC_LOCAL
)
403 ? (IS_ZEBRA_NEIGH_ACTIVE(n
)
414 * Print MAC hash entry - called for display of all MACs.
416 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
419 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
422 struct mac_walk_ctx
*wctx
= ctxt
;
425 json_mac_hdr
= wctx
->json
;
426 mac
= (zebra_mac_t
*)backet
->data
;
430 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
433 json_mac
= json_object_new_object();
435 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
436 && !(wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)) {
437 struct zebra_ns
*zns
;
439 struct interface
*ifp
;
442 zns
= zebra_ns_lookup(NS_DEFAULT
);
443 ifindex
= mac
->fwd_info
.local
.ifindex
;
444 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
445 if (!ifp
) // unexpected
447 vid
= mac
->fwd_info
.local
.vid
;
448 if (json_mac_hdr
== NULL
)
449 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
452 json_object_string_add(json_mac
, "type", "local");
453 json_object_string_add(json_mac
, "intf", ifp
->name
);
456 if (json_mac_hdr
== NULL
)
457 vty_out(vty
, " %-5u", vid
);
459 json_object_int_add(json_mac
, "vlan", vid
);
461 if (json_mac_hdr
== NULL
)
464 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
466 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
467 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) {
468 if (IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
470 if (wctx
->count
== 0) {
471 if (json_mac_hdr
== NULL
) {
472 vty_out(vty
, "\nVNI %u\n\n",
475 "%-17s %-6s %-21s %-5s\n",
481 if (json_mac_hdr
== NULL
)
482 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
484 inet_ntoa(mac
->fwd_info
487 json_object_string_add(json_mac
, "type",
489 json_object_string_add(
490 json_mac
, "remoteVtep",
491 inet_ntoa(mac
->fwd_info
493 json_object_object_add(json_mac_hdr
,
499 if (json_mac_hdr
== NULL
)
500 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
502 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
504 json_object_string_add(json_mac
, "type",
506 json_object_string_add(
507 json_mac
, "remoteVtep",
508 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
509 json_object_object_add(json_mac_hdr
, buf1
,
518 * Print MACs for all VNI.
520 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
523 json_object
*json
= NULL
, *json_vni
= NULL
;
524 json_object
*json_mac
= NULL
;
527 struct mac_walk_ctx
*wctx
= ctxt
;
528 char vni_str
[VNI_STR_LEN
];
530 vty
= (struct vty
*)wctx
->vty
;
531 json
= (struct json_object
*)wctx
->json
;
533 zvni
= (zebra_vni_t
*)backet
->data
;
536 vty_out(vty
, "{}\n");
541 /*We are iterating over a new VNI, set the count to 0*/
544 num_macs
= hashcount(zvni
->mac_table
);
549 json_vni
= json_object_new_object();
550 json_mac
= json_object_new_object();
551 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
554 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
556 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
557 zvni
->vni
, num_macs
);
558 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
559 "Intf/Remote VTEP", "VLAN");
561 json_object_int_add(json_vni
, "numMacs", num_macs
);
563 /* assign per-vni to wctx->json object to fill macs
564 * under the vni. Re-assign primary json object to fill
565 * next vni information.
567 wctx
->json
= json_mac
;
568 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
572 json_object_object_add(json_vni
, "macs", json_mac
);
573 json_object_object_add(json
, vni_str
, json_vni
);
578 * Print a specific VNI entry.
580 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
586 json_object
*json
= NULL
;
587 json_object
*json_vtep_list
= NULL
;
588 json_object
*json_ip_str
= NULL
;
594 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
596 json_object_int_add(json
, "vni", zvni
->vni
);
598 if (!zvni
->vxlan_if
) { // unexpected
600 vty_out(vty
, " VxLAN interface: unknown\n");
603 num_macs
= hashcount(zvni
->mac_table
);
604 num_neigh
= hashcount(zvni
->neigh_table
);
606 vty_out(vty
, " VxLAN interface: %s ifIndex: %u VTEP IP: %s\n",
607 zvni
->vxlan_if
->name
, zvni
->vxlan_if
->ifindex
,
608 inet_ntoa(zvni
->local_vtep_ip
));
610 json_object_string_add(json
, "vxlanInterface",
611 zvni
->vxlan_if
->name
);
612 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
613 json_object_string_add(json
, "vtepIp",
614 inet_ntoa(zvni
->local_vtep_ip
));
615 json_object_string_add(json
, "advertiseGatewayMacip",
616 zvni
->advertise_gw_macip
? "Yes" : "No");
617 json_object_int_add(json
, "numMacs", num_macs
);
618 json_object_int_add(json
, "numArpNd", num_neigh
);
622 vty_out(vty
, " No remote VTEPs known for this VNI\n");
625 vty_out(vty
, " Remote VTEPs for this VNI:\n");
627 json_vtep_list
= json_object_new_array();
628 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
630 vty_out(vty
, " %s\n",
631 inet_ntoa(zvtep
->vtep_ip
));
633 json_ip_str
= json_object_new_string(
634 inet_ntoa(zvtep
->vtep_ip
));
635 json_object_array_add(json_vtep_list
,
640 json_object_object_add(json
, "numRemoteVteps",
645 " Number of MACs (local and remote) known for this VNI: %u\n",
648 " Number of ARPs (IPv4 and IPv6, local and remote) "
649 "known for this VNI: %u\n",
651 vty_out(vty
, " Advertise-gw-macip: %s\n",
652 zvni
->advertise_gw_macip
? "Yes" : "No");
657 * Print a VNI hash entry - called for display of all VNIs.
659 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
664 u_int32_t num_vteps
= 0;
665 u_int32_t num_macs
= 0;
666 u_int32_t num_neigh
= 0;
667 json_object
*json
= NULL
;
668 json_object
*json_vni
= NULL
;
669 json_object
*json_ip_str
= NULL
;
670 json_object
*json_vtep_list
= NULL
;
675 zvni
= (zebra_vni_t
*)backet
->data
;
685 num_macs
= hashcount(zvni
->mac_table
);
686 num_neigh
= hashcount(zvni
->neigh_table
);
688 vty_out(vty
, "%-10u %-21s %-15s %-8u %-8u %-15u\n", zvni
->vni
,
689 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
690 inet_ntoa(zvni
->local_vtep_ip
), num_macs
, num_neigh
,
693 char vni_str
[VNI_STR_LEN
];
694 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
695 json_vni
= json_object_new_object();
696 json_object_string_add(json_vni
, "vxlanIf",
697 zvni
->vxlan_if
? zvni
->vxlan_if
->name
699 json_object_string_add(json_vni
, "vtepIp",
700 inet_ntoa(zvni
->local_vtep_ip
));
701 json_object_int_add(json_vni
, "numMacs", num_macs
);
702 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
703 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
705 json_vtep_list
= json_object_new_array();
706 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
707 json_ip_str
= json_object_new_string(
708 inet_ntoa(zvtep
->vtep_ip
));
709 json_object_array_add(json_vtep_list
,
712 json_object_object_add(json_vni
, "remoteVteps",
715 json_object_object_add(json
, vni_str
, json_vni
);
720 * Inform BGP about local MACIP.
722 static int zvni_macip_send_msg_to_client(struct zebra_vrf
*zvrf
, vni_t vni
,
723 struct ethaddr
*macaddr
,
724 struct ipaddr
*ip
, u_char flags
,
727 struct zserv
*client
;
730 char buf
[ETHER_ADDR_STRLEN
];
731 char buf2
[INET6_ADDRSTRLEN
];
733 client
= zebra_find_client(ZEBRA_ROUTE_BGP
);
734 /* BGP may not be running. */
741 zserv_create_header(s
, cmd
, zvrf_id(zvrf
));
743 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
746 if (IS_IPADDR_V4(ip
))
747 ipa_len
= IPV4_MAX_BYTELEN
;
748 else if (IS_IPADDR_V6(ip
))
749 ipa_len
= IPV6_MAX_BYTELEN
;
751 stream_putl(s
, ipa_len
); /* IP address length */
753 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
755 stream_putl(s
, 0); /* Just MAC. */
757 stream_putc(s
, flags
); /* sticky mac/gateway mac */
759 /* Write packet size. */
760 stream_putw_at(s
, 0, stream_get_endp(s
));
762 if (IS_ZEBRA_DEBUG_VXLAN
)
764 "%u:Send MACIP %s flags 0x%x MAC %s IP %s VNI %u to %s",
765 zvrf_id(zvrf
), (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del",
766 flags
, prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
767 ipaddr2str(ip
, buf2
, sizeof(buf2
)), vni
,
768 zebra_route_string(client
->proto
));
770 if (cmd
== ZEBRA_MACIP_ADD
)
771 client
->macipadd_cnt
++;
773 client
->macipdel_cnt
++;
775 return zebra_server_send_message(client
);
779 * Make hash key for neighbors.
781 static unsigned int neigh_hash_keymake(void *p
)
783 zebra_neigh_t
*n
= p
;
784 struct ipaddr
*ip
= &n
->ip
;
786 if (IS_IPADDR_V4(ip
))
787 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
789 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
790 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
794 * Compare two neighbor hash structures.
796 static int neigh_cmp(const void *p1
, const void *p2
)
798 const zebra_neigh_t
*n1
= p1
;
799 const zebra_neigh_t
*n2
= p2
;
801 if (n1
== NULL
&& n2
== NULL
)
804 if (n1
== NULL
|| n2
== NULL
)
807 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
811 * Callback to allocate neighbor hash entry.
813 static void *zvni_neigh_alloc(void *p
)
815 const zebra_neigh_t
*tmp_n
= p
;
818 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
825 * Add neighbor entry.
827 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
831 zebra_neigh_t
*n
= NULL
;
832 zebra_mac_t
*zmac
= NULL
;
834 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
835 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
836 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
839 memcpy(&n
->emac
, mac
, ETH_ALEN
);
840 n
->state
= ZEBRA_NEIGH_INACTIVE
;
842 /* Associate the neigh to mac */
843 zmac
= zvni_mac_lookup(zvni
, mac
);
845 listnode_add_sort(zmac
->neigh_list
, n
);
851 * Delete neighbor entry.
853 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
855 zebra_neigh_t
*tmp_n
;
856 zebra_mac_t
*zmac
= NULL
;
858 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
860 listnode_delete(zmac
->neigh_list
, n
);
862 /* Free the VNI hash entry and allocated memory. */
863 tmp_n
= hash_release(zvni
->neigh_table
, n
);
865 XFREE(MTYPE_NEIGH
, tmp_n
);
871 * Free neighbor hash entry (callback)
873 static int zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
875 struct neigh_walk_ctx
*wctx
= arg
;
876 zebra_neigh_t
*n
= backet
->data
;
878 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
879 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
880 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
881 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
882 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
883 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
884 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
885 zvni_neigh_send_del_to_client(wctx
->zvrf
,
886 wctx
->zvni
->vni
, &n
->ip
,
890 zvni_neigh_uninstall(wctx
->zvni
, n
);
892 return zvni_neigh_del(wctx
->zvni
, n
);
899 * Delete all neighbor entries from specific VTEP for a particular VNI.
901 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
902 struct in_addr
*r_vtep_ip
)
904 struct neigh_walk_ctx wctx
;
906 if (!zvni
->neigh_table
)
909 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
911 wctx
.uninstall
= uninstall
;
912 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
913 wctx
.r_vtep_ip
= *r_vtep_ip
;
915 hash_iterate(zvni
->neigh_table
,
916 (void (*)(struct hash_backet
*,
917 void *))zvni_neigh_del_hash_entry
,
922 * Delete all neighbor entries for this VNI.
924 static void zvni_neigh_del_all(struct zebra_vrf
*zvrf
, zebra_vni_t
*zvni
,
925 int uninstall
, int upd_client
, u_int32_t flags
)
927 struct neigh_walk_ctx wctx
;
929 if (!zvni
->neigh_table
)
932 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
935 wctx
.uninstall
= uninstall
;
936 wctx
.upd_client
= upd_client
;
939 hash_iterate(zvni
->neigh_table
,
940 (void (*)(struct hash_backet
*,
941 void *))zvni_neigh_del_hash_entry
,
946 * Look up neighbor hash entry.
948 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
953 memset(&tmp
, 0, sizeof(tmp
));
954 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
955 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
960 /* Process all neigh associated to a mac upon local mac add event */
961 static void zvni_process_neigh_on_local_mac_add(struct zebra_vrf
*zvrf
,
965 zebra_neigh_t
*n
= NULL
;
966 struct listnode
*node
= NULL
;
967 char buf
[ETHER_ADDR_STRLEN
];
968 char buf2
[INET6_ADDRSTRLEN
];
970 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
971 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
972 /* MAC is learnt locally, program all inactive neigh
973 * pointing to this mac */
974 if (IS_ZEBRA_NEIGH_INACTIVE(n
)) {
975 if (IS_ZEBRA_DEBUG_VXLAN
)
977 "%u: neigh %s (MAC %s) on VNI %u is now ACTIVE",
979 ipaddr2str(&n
->ip
, buf2
,
981 prefix_mac2str(&n
->emac
, buf
,
985 ZEBRA_NEIGH_SET_ACTIVE(n
);
986 zvni_neigh_send_add_to_client(
987 zvrf
, zvni
->vni
, &n
->ip
, &n
->emac
, 0);
989 if (IS_ZEBRA_DEBUG_VXLAN
)
991 "%u: neigh %s (MAC %s) on VNI %u should NOT be ACTIVE",
993 ipaddr2str(&n
->ip
, buf2
,
995 prefix_mac2str(&n
->emac
, buf
,
999 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1000 /* TODO: assume the neigh has moved too ?? */
1005 /* Process all neigh associated to a mac upon local mac del event */
1006 static void zvni_process_neigh_on_local_mac_del(struct zebra_vrf
*zvrf
,
1010 zebra_neigh_t
*n
= NULL
;
1011 struct listnode
*node
= NULL
;
1012 char buf
[ETHER_ADDR_STRLEN
];
1013 char buf2
[INET6_ADDRSTRLEN
];
1015 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1016 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1017 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1018 if (IS_ZEBRA_DEBUG_VXLAN
)
1020 "%u: neigh %s (MAC %s) on VNI %u is now INACTIVE",
1022 ipaddr2str(&n
->ip
, buf2
,
1024 prefix_mac2str(&n
->emac
, buf
,
1028 ZEBRA_NEIGH_SET_INACTIVE(n
);
1029 zvni_neigh_send_del_to_client(
1030 zvrf
, zvni
->vni
, &n
->ip
, &n
->emac
, 0);
1032 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1033 if (IS_ZEBRA_DEBUG_VXLAN
)
1035 "%u: local MAC %s getting deleted on VNI %u has remote neigh %s",
1037 prefix_mac2str(&n
->emac
, buf
,
1040 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1045 /* process all neigh associated to a mac entry upon remote mac add */
1046 static void zvni_process_neigh_on_remote_mac_add(struct zebra_vrf
*zvrf
,
1050 zebra_neigh_t
*n
= NULL
;
1051 struct listnode
*node
= NULL
;
1052 char buf
[ETHER_ADDR_STRLEN
];
1053 char buf2
[INET6_ADDRSTRLEN
];
1055 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1056 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1057 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1058 if (IS_ZEBRA_DEBUG_VXLAN
)
1060 "%u: neigh %s (MAC %s) on VNI %u INACTIVE",
1062 ipaddr2str(&n
->ip
, buf2
,
1064 prefix_mac2str(&n
->emac
, buf
,
1068 ZEBRA_NEIGH_SET_INACTIVE(n
);
1069 zvni_neigh_send_del_to_client(
1070 zvrf
, zvni
->vni
, &n
->ip
, &n
->emac
, 0);
1076 /* process all neigh associated to mac entry upon remote mac del */
1077 static void zvni_process_neigh_on_remote_mac_del(struct zebra_vrf
*zvrf
,
1081 zebra_neigh_t
*n
= NULL
;
1082 struct listnode
*node
= NULL
;
1083 char buf
[ETHER_ADDR_STRLEN
];
1084 char buf2
[INET6_ADDRSTRLEN
];
1086 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1087 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1088 if (IS_ZEBRA_DEBUG_VXLAN
)
1090 "%u: remote MAC %s getting deleted on VNI %u has local neigh %s",
1092 prefix_mac2str(&n
->emac
, buf
,
1095 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1101 * Inform BGP about local neighbor addition.
1103 static int zvni_neigh_send_add_to_client(struct zebra_vrf
*zvrf
, vni_t vni
,
1105 struct ethaddr
*macaddr
, u_char flags
)
1107 return zvni_macip_send_msg_to_client(zvrf
, vni
, macaddr
, ip
, flags
,
1112 * Inform BGP about local neighbor deletion.
1114 static int zvni_neigh_send_del_to_client(struct zebra_vrf
*zvrf
, vni_t vni
,
1116 struct ethaddr
*macaddr
, u_char flags
)
1118 return zvni_macip_send_msg_to_client(zvrf
, vni
, macaddr
, ip
, flags
,
1123 * Install remote neighbor into the kernel.
1125 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1127 struct zebra_vrf
*zvrf
;
1128 struct zebra_if
*zif
;
1129 struct zebra_l2info_vxlan
*vxl
;
1130 struct interface
*vlan_if
;
1132 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1135 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
1137 zif
= zvni
->vxlan_if
->info
;
1140 vxl
= &zif
->l2info
.vxl
;
1142 vlan_if
= zvni_map_to_svi(zvrf
, vxl
->access_vlan
,
1143 zif
->brslave_info
.br_if
);
1147 return kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
);
1151 * Uninstall remote neighbor from the kernel.
1153 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1155 struct zebra_vrf
*zvrf
;
1156 struct zebra_if
*zif
;
1157 struct zebra_l2info_vxlan
*vxl
;
1158 struct interface
*vlan_if
;
1160 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1163 if (!zvni
->vxlan_if
) {
1164 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
1169 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
1172 zif
= zvni
->vxlan_if
->info
;
1175 vxl
= &zif
->l2info
.vxl
;
1176 vlan_if
= zvni_map_to_svi(zvrf
, vxl
->access_vlan
,
1177 zif
->brslave_info
.br_if
);
1181 return kernel_del_neigh(vlan_if
, &n
->ip
);
1185 * Install neighbor hash entry - called upon access VLAN change.
1187 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
1190 struct neigh_walk_ctx
*wctx
= ctxt
;
1192 n
= (zebra_neigh_t
*)backet
->data
;
1196 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
1197 zvni_neigh_install(wctx
->zvni
, n
);
1200 /* Get the VRR interface for SVI if any */
1201 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
1203 struct zebra_vrf
*zvrf
= NULL
;
1204 struct interface
*tmp_if
= NULL
;
1205 struct zebra_if
*zif
= NULL
;
1206 struct listnode
*node
;
1208 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1211 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf
)), node
, tmp_if
)) {
1216 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
1219 if (zif
->link
== ifp
)
1226 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1228 struct zebra_vrf
*zvrf
= NULL
;
1229 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1230 struct connected
*c
= NULL
;
1231 struct ethaddr macaddr
;
1233 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
1237 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1239 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1242 memset(&ip
, 0, sizeof(struct ipaddr
));
1243 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1246 if (c
->address
->family
== AF_INET
) {
1247 ip
.ipa_type
= IPADDR_V4
;
1248 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1249 sizeof(struct in_addr
));
1250 } else if (c
->address
->family
== AF_INET6
) {
1251 ip
.ipa_type
= IPADDR_V6
;
1252 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1253 sizeof(struct in6_addr
));
1258 zvni_gw_macip_del(ifp
, zvni
, &ip
);
1264 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1266 struct zebra_vrf
*zvrf
= NULL
;
1267 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1268 struct connected
*c
= NULL
;
1269 struct ethaddr macaddr
;
1271 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
1275 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1277 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1280 memset(&ip
, 0, sizeof(struct ipaddr
));
1281 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1284 if (c
->address
->family
== AF_INET
) {
1285 ip
.ipa_type
= IPADDR_V4
;
1286 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1287 sizeof(struct in_addr
));
1288 } else if (c
->address
->family
== AF_INET6
) {
1289 ip
.ipa_type
= IPADDR_V6
;
1290 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1291 sizeof(struct in6_addr
));
1296 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
1303 * zvni_gw_macip_add_to_client
1305 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
1306 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
1308 struct zebra_vrf
*zvrf
= NULL
;
1309 struct zebra_if
*zif
= NULL
;
1310 struct zebra_l2info_vxlan
*vxl
= NULL
;
1311 zebra_neigh_t
*n
= NULL
;
1312 zebra_mac_t
*mac
= NULL
;
1313 char buf
[ETHER_ADDR_STRLEN
];
1314 char buf2
[INET6_ADDRSTRLEN
];
1316 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
1320 zif
= zvni
->vxlan_if
->info
;
1324 vxl
= &zif
->l2info
.vxl
;
1326 mac
= zvni_mac_lookup(zvni
, macaddr
);
1328 mac
= zvni_mac_add(zvni
, macaddr
);
1330 zlog_err("%u:Failed to add MAC %s intf %s(%u) VID %u",
1332 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1333 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
1338 /* Set "local" forwarding info. */
1339 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
1340 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
1341 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
1342 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
1343 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
1345 n
= zvni_neigh_lookup(zvni
, ip
);
1347 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
1350 "%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1351 ifp
->vrf_id
, ipaddr2str(ip
, buf2
, sizeof(buf2
)),
1352 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1353 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
1358 /* Set "local" forwarding info. */
1359 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
1360 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
1361 n
->ifindex
= ifp
->ifindex
;
1363 if (IS_ZEBRA_DEBUG_VXLAN
)
1365 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s add to BGP",
1366 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1367 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1368 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1370 zvni_neigh_send_add_to_client(zvrf
, zvni
->vni
, ip
, macaddr
,
1377 * zvni_gw_macip_del_from_client
1379 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
1382 struct zebra_vrf
*zvrf
= NULL
;
1383 zebra_neigh_t
*n
= NULL
;
1384 zebra_mac_t
*mac
= NULL
;
1385 char buf1
[ETHER_ADDR_STRLEN
];
1386 char buf2
[INET6_ADDRSTRLEN
];
1388 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
1392 /* If the neigh entry is not present nothing to do*/
1393 n
= zvni_neigh_lookup(zvni
, ip
);
1397 /* mac entry should be present */
1398 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
1400 zlog_err("%u: MAC %s doesnt exists for neigh %s on VNI %u",
1402 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
1403 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1407 /* If the entry is not local nothing to do*/
1408 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
1411 if (IS_ZEBRA_DEBUG_VXLAN
)
1413 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
1414 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1415 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
1416 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1418 /* Remove neighbor from BGP. */
1419 zvni_neigh_send_del_to_client(zvrf
, zvni
->vni
, &n
->ip
, &n
->emac
,
1422 /* Delete this neighbor entry. */
1423 zvni_neigh_del(zvni
, n
);
1425 /* see if the mac needs to be deleted as well*/
1427 zvni_deref_ip2mac(zvni
, mac
, 0);
1432 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
1435 zebra_vni_t
*zvni
= NULL
;
1436 struct zebra_if
*zif
= NULL
;
1437 struct zebra_l2info_vxlan zl2_info
;
1438 struct interface
*vlan_if
= NULL
;
1439 struct interface
*vrr_if
= NULL
;
1440 struct interface
*ifp
;
1442 /* Add primary SVI MAC*/
1443 zvni
= (zebra_vni_t
*)backet
->data
;
1447 ifp
= zvni
->vxlan_if
;
1452 /* If down or not mapped to a bridge, we're done. */
1453 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1456 zl2_info
= zif
->l2info
.vxl
;
1458 vlan_if
= zvni_map_to_svi(zvrf
, zl2_info
.access_vlan
,
1459 zif
->brslave_info
.br_if
);
1463 /* Del primary MAC-IP */
1464 zvni_del_macip_for_intf(vlan_if
, zvni
);
1466 /* Del VRR MAC-IP - if any*/
1467 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1469 zvni_del_macip_for_intf(vrr_if
, zvni
);
1474 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
1477 zebra_vni_t
*zvni
= NULL
;
1478 struct zebra_if
*zif
= NULL
;
1479 struct zebra_l2info_vxlan zl2_info
;
1480 struct interface
*vlan_if
= NULL
;
1481 struct interface
*vrr_if
= NULL
;
1482 struct interface
*ifp
= NULL
;
1484 zvni
= (zebra_vni_t
*)backet
->data
;
1488 if (!advertise_gw_macip_enabled(zvrf
, zvni
))
1491 ifp
= zvni
->vxlan_if
;
1496 /* If down or not mapped to a bridge, we're done. */
1497 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1499 zl2_info
= zif
->l2info
.vxl
;
1501 vlan_if
= zvni_map_to_svi(zvrf
, zl2_info
.access_vlan
,
1502 zif
->brslave_info
.br_if
);
1506 if (!advertise_gw_macip_enabled(zvrf
, zvni
))
1509 /* Add primary SVI MAC-IP */
1510 zvni_add_macip_for_intf(vlan_if
, zvni
);
1512 /* Add VRR MAC-IP - if any*/
1513 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1515 zvni_add_macip_for_intf(vrr_if
, zvni
);
1521 * Make hash key for MAC.
1523 static unsigned int mac_hash_keymake(void *p
)
1525 zebra_mac_t
*pmac
= p
;
1526 const void *pnt
= (void *)pmac
->macaddr
.octet
;
1528 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
1532 * Compare two MAC addresses.
1534 static int mac_cmp(const void *p1
, const void *p2
)
1536 const zebra_mac_t
*pmac1
= p1
;
1537 const zebra_mac_t
*pmac2
= p2
;
1539 if (pmac1
== NULL
&& pmac2
== NULL
)
1542 if (pmac1
== NULL
|| pmac2
== NULL
)
1545 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
,
1551 * Callback to allocate MAC hash entry.
1553 static void *zvni_mac_alloc(void *p
)
1555 const zebra_mac_t
*tmp_mac
= p
;
1558 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
1561 return ((void *)mac
);
1567 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
1569 zebra_mac_t tmp_mac
;
1570 zebra_mac_t
*mac
= NULL
;
1572 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
1573 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
1574 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
1577 mac
->neigh_list
= list_new();
1578 mac
->neigh_list
->cmp
= (int (*)(void *, void *))neigh_cmp
;
1586 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
1588 zebra_mac_t
*tmp_mac
;
1590 list_delete_and_null(&mac
->neigh_list
);
1592 /* Free the VNI hash entry and allocated memory. */
1593 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
1595 XFREE(MTYPE_MAC
, tmp_mac
);
1601 * Free MAC hash entry (callback)
1603 static int zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
1605 struct mac_walk_ctx
*wctx
= arg
;
1606 zebra_mac_t
*mac
= backet
->data
;
1609 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
1610 || ((wctx
->flags
& DEL_REMOTE_MAC
)
1611 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
1612 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
1613 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
1614 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1615 &wctx
->r_vtep_ip
))) {
1616 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
1617 sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1
1619 zvni_mac_send_del_to_client(
1620 wctx
->zvrf
, wctx
->zvni
->vni
, &mac
->macaddr
,
1621 (sticky
? ZEBRA_MAC_TYPE_STICKY
: 0));
1624 if (wctx
->uninstall
)
1625 zvni_mac_uninstall(wctx
->zvni
, mac
, 0);
1627 return zvni_mac_del(wctx
->zvni
, mac
);
1634 * Delete all MAC entries from specific VTEP for a particular VNI.
1636 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
1637 struct in_addr
*r_vtep_ip
)
1639 struct mac_walk_ctx wctx
;
1641 if (!zvni
->mac_table
)
1644 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
1646 wctx
.uninstall
= uninstall
;
1647 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
1648 wctx
.r_vtep_ip
= *r_vtep_ip
;
1650 hash_iterate(zvni
->mac_table
, (void (*)(struct hash_backet
*,
1651 void *))zvni_mac_del_hash_entry
,
1656 * Delete all MAC entries for this VNI.
1658 static void zvni_mac_del_all(struct zebra_vrf
*zvrf
, zebra_vni_t
*zvni
,
1659 int uninstall
, int upd_client
, u_int32_t flags
)
1661 struct mac_walk_ctx wctx
;
1663 if (!zvni
->mac_table
)
1666 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
1669 wctx
.uninstall
= uninstall
;
1670 wctx
.upd_client
= upd_client
;
1673 hash_iterate(zvni
->mac_table
, (void (*)(struct hash_backet
*,
1674 void *))zvni_mac_del_hash_entry
,
1679 * Look up MAC hash entry.
1681 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
1686 memset(&tmp
, 0, sizeof(tmp
));
1687 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
1688 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
1694 * Inform BGP about local MAC addition.
1696 static int zvni_mac_send_add_to_client(struct zebra_vrf
*zvrf
, vni_t vni
,
1697 struct ethaddr
*macaddr
, u_char flags
)
1699 return zvni_macip_send_msg_to_client(zvrf
, vni
, macaddr
, NULL
, flags
,
1704 * Inform BGP about local MAC deletion.
1706 static int zvni_mac_send_del_to_client(struct zebra_vrf
*zvrf
, vni_t vni
,
1707 struct ethaddr
*macaddr
, u_char flags
)
1709 return zvni_macip_send_msg_to_client(zvrf
, vni
, macaddr
, NULL
, flags
,
1714 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
1715 * notifications, to see if there are of interest.
1716 * TODO: Need to make this as a hash table.
1718 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
1719 struct interface
*br_if
, vlanid_t vid
)
1721 struct zebra_vrf
*zvrf
;
1722 struct listnode
*node
;
1723 struct interface
*tmp_if
;
1724 struct zebra_if
*zif
;
1725 struct zebra_l2info_bridge
*br
;
1726 struct zebra_l2info_vxlan
*vxl
;
1727 u_char bridge_vlan_aware
;
1730 /* Locate VRF corresponding to interface. */
1731 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1734 /* Determine if bridge is VLAN-aware or not */
1737 br
= &zif
->l2info
.br
;
1738 bridge_vlan_aware
= br
->vlan_aware
;
1740 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
1741 /* TODO: Optimize with a hash. */
1742 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf
)), node
, tmp_if
)) {
1744 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
1746 if (!if_is_operative(tmp_if
))
1748 vxl
= &zif
->l2info
.vxl
;
1750 if (zif
->brslave_info
.br_if
!= br_if
)
1753 if (!bridge_vlan_aware
)
1756 if (vxl
->access_vlan
== vid
)
1763 zvni
= zvni_lookup(zvrf
, vxl
->vni
);
1768 * Map SVI and associated bridge to a VNI. This is invoked upon getting
1769 * neighbor notifications, to see if they are of interest.
1770 * TODO: Need to make this as a hash table.
1772 static zebra_vni_t
*zvni_map_svi(struct interface
*ifp
, struct interface
*br_if
)
1774 struct zebra_vrf
*zvrf
;
1775 struct listnode
*node
;
1776 struct interface
*tmp_if
;
1777 struct zebra_if
*zif
;
1778 struct zebra_l2info_bridge
*br
;
1779 struct zebra_l2info_vxlan
*vxl
;
1780 u_char bridge_vlan_aware
;
1787 /* Make sure the linked interface is a bridge. */
1788 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
1791 /* Locate VRF corresponding to interface. */
1792 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1795 /* Determine if bridge is VLAN-aware or not */
1798 br
= &zif
->l2info
.br
;
1799 bridge_vlan_aware
= br
->vlan_aware
;
1800 if (bridge_vlan_aware
) {
1801 struct zebra_l2info_vlan
*vl
;
1803 if (!IS_ZEBRA_IF_VLAN(ifp
))
1808 vl
= &zif
->l2info
.vl
;
1812 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
1813 /* TODO: Optimize with a hash. */
1814 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf
)), node
, tmp_if
)) {
1816 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
1818 if (!if_is_operative(tmp_if
))
1820 vxl
= &zif
->l2info
.vxl
;
1822 if (zif
->brslave_info
.br_if
!= br_if
)
1825 if (!bridge_vlan_aware
)
1828 if (vxl
->access_vlan
== vid
)
1835 zvni
= zvni_lookup(zvrf
, vxl
->vni
);
1839 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
1841 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
1842 * linked to the bridge
1843 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
1846 static struct interface
*zvni_map_to_svi(struct zebra_vrf
*zvrf
, vlanid_t vid
,
1847 struct interface
*br_if
)
1849 struct listnode
*node
;
1850 struct interface
*tmp_if
;
1851 struct zebra_if
*zif
;
1852 struct zebra_l2info_bridge
*br
;
1853 struct zebra_l2info_vlan
*vl
;
1854 u_char bridge_vlan_aware
;
1856 /* Defensive check, caller expected to invoke only with valid bridge. */
1860 /* Determine if bridge is VLAN-aware or not */
1863 br
= &zif
->l2info
.br
;
1864 bridge_vlan_aware
= br
->vlan_aware
;
1866 /* Check oper status of the SVI. */
1867 if (!bridge_vlan_aware
)
1868 return if_is_operative(br_if
) ? br_if
: NULL
;
1870 /* Identify corresponding VLAN interface. */
1871 /* TODO: Optimize with a hash. */
1872 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf
)), node
, tmp_if
)) {
1873 /* Check oper status of the SVI. */
1874 if (!if_is_operative(tmp_if
))
1877 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
1878 || zif
->link
!= br_if
)
1880 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
1890 * Install remote MAC into the kernel.
1892 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
1894 struct zebra_if
*zif
;
1895 struct zebra_l2info_vxlan
*vxl
;
1898 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
1901 zif
= zvni
->vxlan_if
->info
;
1904 vxl
= &zif
->l2info
.vxl
;
1906 sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0;
1908 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
1909 mac
->fwd_info
.r_vtep_ip
, sticky
);
1913 * Uninstall remote MAC from the kernel. In the scenario where the MAC
1914 * moves to remote, we have to uninstall any existing local entry first.
1916 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
)
1918 struct zebra_if
*zif
;
1919 struct zebra_l2info_vxlan
*vxl
;
1920 struct in_addr vtep_ip
= {.s_addr
= 0};
1921 struct zebra_ns
*zns
;
1922 struct interface
*ifp
;
1924 if (!local
&& !(mac
->flags
& ZEBRA_MAC_REMOTE
))
1927 if (!zvni
->vxlan_if
) {
1928 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
1933 zif
= zvni
->vxlan_if
->info
;
1936 vxl
= &zif
->l2info
.vxl
;
1939 zns
= zebra_ns_lookup(NS_DEFAULT
);
1940 ifp
= if_lookup_by_index_per_ns(zns
,
1941 mac
->fwd_info
.local
.ifindex
);
1942 if (!ifp
) // unexpected
1945 ifp
= zvni
->vxlan_if
;
1946 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
1949 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
,
1954 * Install MAC hash entry - called upon access VLAN change.
1956 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
1959 struct mac_walk_ctx
*wctx
= ctxt
;
1961 mac
= (zebra_mac_t
*)backet
->data
;
1965 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
1966 zvni_mac_install(wctx
->zvni
, mac
);
1970 * Decrement neighbor refcount of MAC; uninstall and free it if
1973 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
1976 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)
1977 || !list_isempty(mac
->neigh_list
))
1981 zvni_mac_uninstall(zvni
, mac
, 0);
1983 zvni_mac_del(zvni
, mac
);
1987 * Read and populate local MACs and neighbors corresponding to this VNI.
1989 static void zvni_read_mac_neigh(struct zebra_vrf
*zvrf
, zebra_vni_t
*zvni
,
1990 struct interface
*ifp
)
1992 struct zebra_if
*zif
;
1993 struct interface
*vlan_if
;
1994 struct zebra_l2info_vxlan
*vxl
;
1995 struct interface
*vrr_if
;
1998 vxl
= &zif
->l2info
.vxl
;
2000 if (IS_ZEBRA_DEBUG_VXLAN
)
2002 "%u:Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2003 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2004 zif
->brslave_info
.bridge_ifindex
);
2006 macfdb_read_for_bridge(zvrf
->zns
, ifp
, zif
->brslave_info
.br_if
);
2007 vlan_if
= zvni_map_to_svi(zvrf
, vxl
->access_vlan
,
2008 zif
->brslave_info
.br_if
);
2011 if (advertise_gw_macip_enabled(zvrf
, zvni
)) {
2012 /* Add SVI MAC-IP */
2013 zvni_add_macip_for_intf(vlan_if
, zvni
);
2015 /* Add VRR MAC-IP - if any*/
2016 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2018 zvni_add_macip_for_intf(vrr_if
, zvni
);
2021 neigh_read_for_vlan(zvrf
->zns
, vlan_if
);
2026 * Hash function for VNI.
2028 static unsigned int vni_hash_keymake(void *p
)
2030 const zebra_vni_t
*zvni
= p
;
2032 return (jhash_1word(zvni
->vni
, 0));
2036 * Compare 2 VNI hash entries.
2038 static int vni_hash_cmp(const void *p1
, const void *p2
)
2040 const zebra_vni_t
*zvni1
= p1
;
2041 const zebra_vni_t
*zvni2
= p2
;
2043 return (zvni1
->vni
== zvni2
->vni
);
2047 * Callback to allocate VNI hash entry.
2049 static void *zvni_alloc(void *p
)
2051 const zebra_vni_t
*tmp_vni
= p
;
2054 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
2055 zvni
->vni
= tmp_vni
->vni
;
2056 return ((void *)zvni
);
2060 * Look up VNI hash entry.
2062 static zebra_vni_t
*zvni_lookup(struct zebra_vrf
*zvrf
, vni_t vni
)
2064 zebra_vni_t tmp_vni
;
2065 zebra_vni_t
*zvni
= NULL
;
2067 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
2069 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
2075 * Add VNI hash entry.
2077 static zebra_vni_t
*zvni_add(struct zebra_vrf
*zvrf
, vni_t vni
)
2079 zebra_vni_t tmp_zvni
;
2080 zebra_vni_t
*zvni
= NULL
;
2082 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
2084 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
2087 /* Create hash table for MAC */
2089 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
2091 /* Create hash table for neighbors */
2092 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
2093 "Zebra VNI Neighbor Table");
2099 * Delete VNI hash entry.
2101 static int zvni_del(struct zebra_vrf
*zvrf
, zebra_vni_t
*zvni
)
2103 zebra_vni_t
*tmp_zvni
;
2105 zvni
->vxlan_if
= NULL
;
2107 /* Free the neighbor hash table. */
2108 hash_free(zvni
->neigh_table
);
2109 zvni
->neigh_table
= NULL
;
2111 /* Free the MAC hash table. */
2112 hash_free(zvni
->mac_table
);
2113 zvni
->mac_table
= NULL
;
2115 /* Free the VNI hash entry and allocated memory. */
2116 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
2118 XFREE(MTYPE_ZVNI
, tmp_zvni
);
2124 * Inform BGP about local VNI addition.
2126 static int zvni_send_add_to_client(struct zebra_vrf
*zvrf
, zebra_vni_t
*zvni
)
2128 struct zserv
*client
;
2131 client
= zebra_find_client(ZEBRA_ROUTE_BGP
);
2132 /* BGP may not be running. */
2139 zserv_create_header(s
, ZEBRA_VNI_ADD
, zvrf_id(zvrf
));
2140 stream_putl(s
, zvni
->vni
);
2141 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
2143 /* Write packet size. */
2144 stream_putw_at(s
, 0, stream_get_endp(s
));
2146 if (IS_ZEBRA_DEBUG_VXLAN
)
2147 zlog_debug("%u:Send VNI_ADD %u %s to %s", zvrf_id(zvrf
),
2148 zvni
->vni
, inet_ntoa(zvni
->local_vtep_ip
),
2149 zebra_route_string(client
->proto
));
2151 client
->vniadd_cnt
++;
2152 return zebra_server_send_message(client
);
2156 * Inform BGP about local VNI deletion.
2158 static int zvni_send_del_to_client(struct zebra_vrf
*zvrf
, vni_t vni
)
2160 struct zserv
*client
;
2163 client
= zebra_find_client(ZEBRA_ROUTE_BGP
);
2164 /* BGP may not be running. */
2171 zserv_create_header(s
, ZEBRA_VNI_DEL
, zvrf_id(zvrf
));
2172 stream_putl(s
, vni
);
2174 /* Write packet size. */
2175 stream_putw_at(s
, 0, stream_get_endp(s
));
2177 if (IS_ZEBRA_DEBUG_VXLAN
)
2178 zlog_debug("%u:Send VNI_DEL %u to %s", zvrf_id(zvrf
), vni
,
2179 zebra_route_string(client
->proto
));
2181 client
->vnidel_cnt
++;
2182 return zebra_server_send_message(client
);
2186 * Build the VNI hash table by going over the VxLAN interfaces. This
2187 * is called when EVPN (advertise-all-vni) is enabled.
2189 static void zvni_build_hash_table(struct zebra_vrf
*zvrf
)
2191 struct listnode
*node
;
2192 struct interface
*ifp
;
2194 /* Walk VxLAN interfaces and create VNI hash. */
2195 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf
)), node
, ifp
)) {
2196 struct zebra_if
*zif
;
2197 struct zebra_l2info_vxlan
*vxl
;
2202 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2204 vxl
= &zif
->l2info
.vxl
;
2208 if (IS_ZEBRA_DEBUG_VXLAN
)
2210 "%u:Create VNI hash for intf %s(%u) VNI %u local IP %s",
2211 zvrf_id(zvrf
), ifp
->name
, ifp
->ifindex
, vni
,
2212 inet_ntoa(vxl
->vtep_ip
));
2214 /* VNI hash entry is not expected to exist. */
2215 zvni
= zvni_lookup(zvrf
, vni
);
2218 "VNI hash already present for VRF %d IF %s(%u) VNI %u",
2219 zvrf_id(zvrf
), ifp
->name
, ifp
->ifindex
, vni
);
2223 zvni
= zvni_add(zvrf
, vni
);
2226 "Failed to add VNI hash, VRF %d IF %s(%u) VNI %u",
2227 zvrf_id(zvrf
), ifp
->name
, ifp
->ifindex
, vni
);
2231 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
2232 zvni
->vxlan_if
= ifp
;
2234 /* Inform BGP if interface is up and mapped to bridge. */
2235 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
2236 zvni_send_add_to_client(zvrf
, zvni
);
2241 * See if remote VTEP matches with prefix.
2243 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
2245 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
2249 * Locate remote VTEP in VNI hash table.
2251 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2253 zebra_vtep_t
*zvtep
;
2258 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2259 if (zvni_vtep_match(vtep_ip
, zvtep
))
2267 * Add remote VTEP to VNI hash table.
2269 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2271 zebra_vtep_t
*zvtep
;
2273 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
2275 zlog_err("Failed to alloc VTEP entry, VNI %u", zvni
->vni
);
2279 zvtep
->vtep_ip
= *vtep_ip
;
2282 zvni
->vteps
->prev
= zvtep
;
2283 zvtep
->next
= zvni
->vteps
;
2284 zvni
->vteps
= zvtep
;
2290 * Remove remote VTEP from VNI hash table.
2292 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
2295 zvtep
->next
->prev
= zvtep
->prev
;
2297 zvtep
->prev
->next
= zvtep
->next
;
2299 zvni
->vteps
= zvtep
->next
;
2301 zvtep
->prev
= zvtep
->next
= NULL
;
2302 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
2308 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
2309 * uninstall from kernel if asked to.
2311 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
2313 zebra_vtep_t
*zvtep
, *zvtep_next
;
2318 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
2319 zvtep_next
= zvtep
->next
;
2321 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
2322 zvni_vtep_del(zvni
, zvtep
);
2329 * Install remote VTEP into the kernel.
2331 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2333 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
2337 * Uninstall remote VTEP from the kernel.
2339 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2341 if (!zvni
->vxlan_if
) {
2342 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2347 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
2351 * Cleanup VNI/VTEP and update kernel
2353 static void zvni_cleanup_all(struct hash_backet
*backet
, void *zvrf
)
2357 zvni
= (zebra_vni_t
*)backet
->data
;
2361 /* Free up all neighbors and MACs, if any. */
2362 zvni_neigh_del_all(zvrf
, zvni
, 1, 0, DEL_ALL_NEIGH
);
2363 zvni_mac_del_all(zvrf
, zvni
, 1, 0, DEL_ALL_MAC
);
2365 /* Free up all remote VTEPs, if any. */
2366 zvni_vtep_del_all(zvni
, 1);
2368 /* Delete the hash entry. */
2369 zvni_del(zvrf
, zvni
);
2373 /* Public functions */
2376 * Display Neighbors for a VNI (VTY command handler).
2378 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2379 vni_t vni
, u_char use_json
)
2382 u_int32_t num_neigh
;
2383 struct neigh_walk_ctx wctx
;
2384 json_object
*json
= NULL
;
2386 if (!EVPN_ENABLED(zvrf
))
2388 zvni
= zvni_lookup(zvrf
, vni
);
2391 vty_out(vty
, "{}\n");
2393 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2396 num_neigh
= hashcount(zvni
->neigh_table
);
2401 json
= json_object_new_object();
2403 /* Since we have IPv6 addresses to deal with which can vary widely in
2404 * size, we try to be a bit more elegant in display by first computing
2405 * the maximum width.
2407 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2410 wctx
.addr_width
= 15;
2412 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
2416 "Number of ARPs (local and remote) known for this VNI: %u\n",
2418 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
2419 "Type", "MAC", "Remote VTEP");
2421 json_object_int_add(json
, "numArpNd", num_neigh
);
2423 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
2425 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2426 json
, JSON_C_TO_STRING_PRETTY
));
2427 json_object_free(json
);
2432 * Display neighbors across all VNIs (VTY command handler).
2434 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2437 json_object
*json
= NULL
;
2440 if (!EVPN_ENABLED(zvrf
))
2444 json
= json_object_new_object();
2448 hash_iterate(zvrf
->vni_table
,
2449 (void (*)(struct hash_backet
*,
2450 void *))zvni_print_neigh_hash_all_vni
,
2453 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2454 json
, JSON_C_TO_STRING_PRETTY
));
2455 json_object_free(json
);
2460 * Display specific neighbor for a VNI, if present (VTY command handler).
2462 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
2463 struct zebra_vrf
*zvrf
, vni_t vni
,
2464 struct ipaddr
*ip
, u_char use_json
)
2468 json_object
*json
= NULL
;
2470 if (!EVPN_ENABLED(zvrf
))
2472 zvni
= zvni_lookup(zvrf
, vni
);
2475 vty_out(vty
, "{}\n");
2477 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2480 n
= zvni_neigh_lookup(zvni
, ip
);
2484 "%% Requested neighbor does not exist in VNI %u\n",
2489 json
= json_object_new_object();
2491 zvni_print_neigh(n
, vty
, json
);
2494 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2495 json
, JSON_C_TO_STRING_PRETTY
));
2496 json_object_free(json
);
2501 * Display neighbors for a VNI from specific VTEP (VTY command handler).
2502 * By definition, these are remote neighbors.
2504 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2505 vni_t vni
, struct in_addr vtep_ip
,
2509 u_int32_t num_neigh
;
2510 struct neigh_walk_ctx wctx
;
2511 json_object
*json
= NULL
;
2513 if (!EVPN_ENABLED(zvrf
))
2515 zvni
= zvni_lookup(zvrf
, vni
);
2518 vty_out(vty
, "{}\n");
2520 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2523 num_neigh
= hashcount(zvni
->neigh_table
);
2527 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2530 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
2531 wctx
.r_vtep_ip
= vtep_ip
;
2533 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
2536 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2537 json
, JSON_C_TO_STRING_PRETTY
));
2538 json_object_free(json
);
2543 * Display MACs for a VNI (VTY command handler).
2545 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2546 vni_t vni
, u_char use_json
)
2550 struct mac_walk_ctx wctx
;
2551 json_object
*json
= NULL
;
2552 json_object
*json_mac
= NULL
;
2554 if (!EVPN_ENABLED(zvrf
))
2556 zvni
= zvni_lookup(zvrf
, vni
);
2559 vty_out(vty
, "{}\n");
2561 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2564 num_macs
= hashcount(zvni
->mac_table
);
2569 json
= json_object_new_object();
2570 json_mac
= json_object_new_object();
2573 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2576 wctx
.json
= json_mac
;
2580 "Number of MACs (local and remote) known for this VNI: %u\n",
2582 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
2583 "Intf/Remote VTEP", "VLAN");
2585 json_object_int_add(json
, "numMacs", num_macs
);
2587 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
2590 json_object_object_add(json
, "macs", json_mac
);
2591 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2592 json
, JSON_C_TO_STRING_PRETTY
));
2593 json_object_free(json
);
2598 * Display MACs for all VNIs (VTY command handler).
2600 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2603 struct mac_walk_ctx wctx
;
2604 json_object
*json
= NULL
;
2606 if (!EVPN_ENABLED(zvrf
)) {
2608 vty_out(vty
, "{}\n");
2612 json
= json_object_new_object();
2614 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2617 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
2620 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2621 json
, JSON_C_TO_STRING_PRETTY
));
2622 json_object_free(json
);
2627 * Display MACs for all VNIs (VTY command handler).
2629 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
2630 struct zebra_vrf
*zvrf
,
2631 struct in_addr vtep_ip
,
2634 struct mac_walk_ctx wctx
;
2635 json_object
*json
= NULL
;
2637 if (!EVPN_ENABLED(zvrf
))
2641 json
= json_object_new_object();
2643 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2645 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
2646 wctx
.r_vtep_ip
= vtep_ip
;
2648 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
2651 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2652 json
, JSON_C_TO_STRING_PRETTY
));
2653 json_object_free(json
);
2658 * Display specific MAC for a VNI, if present (VTY command handler).
2660 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2661 vni_t vni
, struct ethaddr
*macaddr
)
2666 if (!EVPN_ENABLED(zvrf
))
2668 zvni
= zvni_lookup(zvrf
, vni
);
2670 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2673 mac
= zvni_mac_lookup(zvni
, macaddr
);
2675 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
2680 zvni_print_mac(mac
, vty
);
2684 * Display MACs for a VNI from specific VTEP (VTY command handler).
2686 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2687 vni_t vni
, struct in_addr vtep_ip
,
2692 struct mac_walk_ctx wctx
;
2693 json_object
*json
= NULL
;
2694 json_object
*json_mac
= NULL
;
2696 if (!EVPN_ENABLED(zvrf
))
2698 zvni
= zvni_lookup(zvrf
, vni
);
2701 vty_out(vty
, "{}\n");
2703 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2706 num_macs
= hashcount(zvni
->mac_table
);
2711 json
= json_object_new_object();
2712 json_mac
= json_object_new_object();
2715 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2718 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
2719 wctx
.r_vtep_ip
= vtep_ip
;
2720 wctx
.json
= json_mac
;
2721 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
2724 json_object_int_add(json
, "numMacs", wctx
.count
);
2726 json_object_object_add(json
, "macs", json_mac
);
2727 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2728 json
, JSON_C_TO_STRING_PRETTY
));
2729 json_object_free(json
);
2735 * Display VNI information (VTY command handler).
2737 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
2741 json_object
*json
= NULL
;
2744 if (!EVPN_ENABLED(zvrf
))
2746 zvni
= zvni_lookup(zvrf
, vni
);
2749 vty_out(vty
, "{}\n");
2751 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2755 json
= json_object_new_object();
2758 zvni_print(zvni
, (void *)args
);
2760 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2761 json
, JSON_C_TO_STRING_PRETTY
));
2762 json_object_free(json
);
2767 * Display VNI hash table (VTY command handler).
2769 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2773 json_object
*json
= NULL
;
2776 if (!EVPN_ENABLED(zvrf
))
2778 num_vnis
= hashcount(zvrf
->vni_table
);
2781 vty_out(vty
, "{}\n");
2785 json
= json_object_new_object();
2786 json_object_string_add(json
, "advertiseGatewayMacip",
2787 zvrf
->advertise_gw_macip
? "Yes" : "No");
2788 json_object_int_add(json
, "numVnis", num_vnis
);
2790 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
2791 zvrf
->advertise_gw_macip
? "Yes" : "No");
2792 vty_out(vty
, "Number of VNIs: %u\n", num_vnis
);
2793 vty_out(vty
, "%-10s %-21s %-15s %-8s %-8s %-15s\n", "VNI",
2794 "VxLAN IF", "VTEP IP", "# MACs", "# ARPs",
2800 hash_iterate(zvrf
->vni_table
,
2801 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
2805 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2806 json
, JSON_C_TO_STRING_PRETTY
));
2807 json_object_free(json
);
2812 * Handle neighbor delete (on a VLAN device / L3 interface) from the
2813 * kernel. This may result in either the neighbor getting deleted from
2814 * our database or being re-added to the kernel (if it is a valid
2817 int zebra_vxlan_local_neigh_del(struct interface
*ifp
,
2818 struct interface
*link_if
, struct ipaddr
*ip
)
2822 struct zebra_vrf
*zvrf
;
2823 char buf
[INET6_ADDRSTRLEN
];
2824 char buf2
[ETHER_ADDR_STRLEN
];
2827 /* We are only interested in neighbors on an SVI that resides on top
2828 * of a VxLAN bridge.
2830 zvni
= zvni_map_svi(ifp
, link_if
);
2833 if (!zvni
->vxlan_if
) {
2835 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
2840 if (IS_ZEBRA_DEBUG_VXLAN
)
2841 zlog_debug("%u:Del neighbor %s intf %s(%u) -> VNI %u",
2842 ifp
->vrf_id
, ipaddr2str(ip
, buf
, sizeof(buf
)),
2843 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2845 /* If entry doesn't exist, nothing to do. */
2846 n
= zvni_neigh_lookup(zvni
, ip
);
2850 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2852 if (IS_ZEBRA_DEBUG_VXLAN
)
2854 "%u: trying to del a neigh %s without a mac %s on VNI %u",
2855 ifp
->vrf_id
, ipaddr2str(ip
, buf
, sizeof(buf
)),
2856 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
2862 /* If it is a remote entry, the kernel has aged this out or someone has
2863 * deleted it, it needs to be re-installed as Quagga is the owner.
2865 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2866 zvni_neigh_install(zvni
, n
);
2870 /* Locate VRF corresponding to interface. */
2871 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2874 /* Remove neighbor from BGP. */
2875 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
2876 zvni_neigh_send_del_to_client(zvrf
, zvni
->vni
, &n
->ip
, &n
->emac
,
2879 /* Delete this neighbor entry. */
2880 zvni_neigh_del(zvni
, n
);
2882 /* see if the AUTO mac needs to be deleted */
2883 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
2884 && !listcount(zmac
->neigh_list
))
2885 zvni_mac_del(zvni
, zmac
);
2891 * Handle neighbor add or update (on a VLAN device / L3 interface)
2894 int zebra_vxlan_local_neigh_add_update(struct interface
*ifp
,
2895 struct interface
*link_if
,
2897 struct ethaddr
*macaddr
, u_int16_t state
,
2902 struct zebra_vrf
*zvrf
;
2903 zebra_mac_t
*zmac
, *old_zmac
;
2904 char buf
[ETHER_ADDR_STRLEN
];
2905 char buf2
[INET6_ADDRSTRLEN
];
2907 /* We are only interested in neighbors on an SVI that resides on top
2908 * of a VxLAN bridge.
2910 zvni
= zvni_map_svi(ifp
, link_if
);
2914 /* Locate VRF corresponding to interface. */
2915 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2918 if (IS_ZEBRA_DEBUG_VXLAN
)
2920 "%u:Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x "
2922 ifp
->vrf_id
, ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2923 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
2924 ifp
->ifindex
, state
, ext_learned
? "ext-learned " : "",
2927 /* create a dummy MAC if the MAC is not already present */
2928 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2930 if (IS_ZEBRA_DEBUG_VXLAN
)
2932 "%u: AUTO MAC %s created for neigh %s on VNI %u",
2934 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2935 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2937 zmac
= zvni_mac_add(zvni
, macaddr
);
2939 zlog_warn("%u:Failed to add MAC %s VNI %u",
2941 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2946 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
2947 memset(&zmac
->flags
, 0, sizeof(u_int32_t
));
2948 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2951 /* If same entry already exists, it might be a change or it might be a
2952 * move from remote to local.
2954 n
= zvni_neigh_lookup(zvni
, ip
);
2956 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2957 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2960 /* Update any params and return - client doesn't
2961 * care about a purely local change.
2963 n
->ifindex
= ifp
->ifindex
;
2967 /* If the MAC has changed,
2968 * need to issue a delete first
2969 * as this means a different MACIP route.
2970 * Also, need to do some unlinking/relinking.
2972 zvni_neigh_send_del_to_client(zvrf
, zvni
->vni
, &n
->ip
,
2974 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2976 listnode_delete(old_zmac
->neigh_list
, n
);
2977 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
2980 /* Set "local" forwarding info. */
2981 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2982 n
->ifindex
= ifp
->ifindex
;
2983 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2985 /* Link to new MAC */
2986 listnode_add_sort(zmac
->neigh_list
, n
);
2987 } else if (ext_learned
)
2988 /* The neighbor is remote and that is the notification we got.
2991 /* TODO: Evaluate if we need to do anything here. */
2994 /* Neighbor has moved from remote to local. */
2996 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2997 n
->r_vtep_ip
.s_addr
= 0;
2998 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2999 n
->ifindex
= ifp
->ifindex
;
3002 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
3005 "%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3006 ifp
->vrf_id
, ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3007 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3008 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3011 /* Set "local" forwarding info. */
3012 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3013 n
->ifindex
= ifp
->ifindex
;
3016 /* Before we program this in BGP, we need to check if MAC is locally
3018 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3019 if (IS_ZEBRA_DEBUG_VXLAN
)
3021 "%u: Skipping neigh %s add to client as MAC %s is not local on VNI %u",
3022 ifp
->vrf_id
, ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3023 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3030 if (IS_ZEBRA_DEBUG_VXLAN
)
3031 zlog_debug("%u: neigh %s (MAC %s) is now ACTIVE on VNI %u",
3032 ifp
->vrf_id
, ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3033 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3036 ZEBRA_NEIGH_SET_ACTIVE(n
);
3037 return zvni_neigh_send_add_to_client(zvrf
, zvni
->vni
, ip
, macaddr
, 0);
3042 * Handle message from client to delete a remote MACIP for a VNI.
3044 int zebra_vxlan_remote_macip_del(struct zserv
*client
, int sock
, u_short length
,
3045 struct zebra_vrf
*zvrf
)
3049 struct ethaddr macaddr
;
3051 struct in_addr vtep_ip
;
3055 u_short l
= 0, ipa_len
;
3056 char buf
[ETHER_ADDR_STRLEN
];
3057 char buf1
[INET6_ADDRSTRLEN
];
3058 struct interface
*ifp
= NULL
;
3059 struct zebra_if
*zif
= NULL
;
3063 while (l
< length
) {
3064 /* Obtain each remote MACIP and process. */
3065 /* Message contains VNI, followed by MAC followed by IP (if any)
3066 * followed by remote VTEP IP.
3070 memset(&ip
, 0, sizeof(ip
));
3071 vni
= (vni_t
)stream_getl(s
);
3072 stream_get(&macaddr
.octet
, s
, ETH_ALEN
);
3073 ipa_len
= stream_getl(s
);
3075 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
3077 stream_get(&ip
.ip
.addr
, s
, ipa_len
);
3079 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
3080 vtep_ip
.s_addr
= stream_get_ipv4(s
);
3081 l
+= IPV4_MAX_BYTELEN
;
3083 if (IS_ZEBRA_DEBUG_VXLAN
)
3085 "%u:Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
3087 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
3088 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
3090 zebra_route_string(client
->proto
));
3092 /* Locate VNI hash entry - expected to exist. */
3093 zvni
= zvni_lookup(zvrf
, vni
);
3095 if (IS_ZEBRA_DEBUG_VXLAN
)
3097 "Failed to locate VNI hash upon remote MACIP DEL, "
3099 zvrf_id(zvrf
), vni
);
3102 ifp
= zvni
->vxlan_if
;
3105 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
3111 /* If down or not mapped to a bridge, we're done. */
3112 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
3115 /* The remote VTEP specified is normally expected to exist, but
3117 * possible that the peer may delete the VTEP before deleting
3119 * referring to the VTEP, in which case the handler (see
3121 * would have already deleted the MACs.
3123 if (!zvni_vtep_find(zvni
, &vtep_ip
))
3126 mac
= zvni_mac_lookup(zvni
, &macaddr
);
3128 n
= zvni_neigh_lookup(zvni
, &ip
);
3132 "failed to locate MAC %s for neigh %s in VRF %u VNI %u",
3133 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
3134 ipaddr2str(&ip
, buf1
, sizeof(buf1
)),
3135 zvrf_id(zvrf
), vni
);
3139 /* If the remote mac or neighbor doesn't exist there is nothing
3141 * to do. Otherwise, uninstall the entry and then remove it.
3146 /* Uninstall remote neighbor or MAC. */
3148 /* When the MAC changes for an IP, it is possible the
3150 * update the new MAC before trying to delete the "old"
3152 * (as these are two different MACIP routes). Do the
3154 * if the MAC matches.
3156 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
3157 && (memcmp(n
->emac
.octet
, macaddr
.octet
,
3160 zvni_neigh_uninstall(zvni
, n
);
3161 zvni_neigh_del(zvni
, n
);
3162 zvni_deref_ip2mac(zvni
, mac
, 1);
3165 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
3166 zvni_process_neigh_on_remote_mac_del(zvrf
, zvni
,
3169 if (list_isempty(mac
->neigh_list
)) {
3170 zvni_mac_uninstall(zvni
, mac
, 0);
3171 zvni_mac_del(zvni
, mac
);
3173 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
3182 * Handle message from client to add a remote MACIP for a VNI. This
3183 * could be just the add of a MAC address or the add of a neighbor
3186 int zebra_vxlan_remote_macip_add(struct zserv
*client
, int sock
, u_short length
,
3187 struct zebra_vrf
*zvrf
)
3191 struct ethaddr macaddr
;
3193 struct in_addr vtep_ip
;
3195 zebra_vtep_t
*zvtep
;
3196 zebra_mac_t
*mac
, *old_mac
;
3198 u_short l
= 0, ipa_len
;
3199 int update_mac
= 0, update_neigh
= 0;
3200 char buf
[ETHER_ADDR_STRLEN
];
3201 char buf1
[INET6_ADDRSTRLEN
];
3203 struct interface
*ifp
= NULL
;
3204 struct zebra_if
*zif
= NULL
;
3206 assert(EVPN_ENABLED(zvrf
));
3210 while (l
< length
) {
3211 /* Obtain each remote MACIP and process. */
3212 /* Message contains VNI, followed by MAC followed by IP (if any)
3213 * followed by remote VTEP IP.
3215 update_mac
= update_neigh
= 0;
3218 memset(&ip
, 0, sizeof(ip
));
3219 vni
= (vni_t
)stream_getl(s
);
3220 stream_get(&macaddr
.octet
, s
, ETH_ALEN
);
3221 ipa_len
= stream_getl(s
);
3223 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
3225 stream_get(&ip
.ip
.addr
, s
, ipa_len
);
3227 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
3228 vtep_ip
.s_addr
= stream_get_ipv4(s
);
3229 l
+= IPV4_MAX_BYTELEN
;
3231 /* Get 'sticky' flag. */
3232 sticky
= stream_getc(s
);
3235 if (IS_ZEBRA_DEBUG_VXLAN
)
3237 "%u:Recv MACIP Add %sMAC %s IP %s VNI %u Remote VTEP %s from %s",
3238 zvrf_id(zvrf
), sticky
? "sticky " : "",
3239 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
3240 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
3242 zebra_route_string(client
->proto
));
3244 /* Locate VNI hash entry - expected to exist. */
3245 zvni
= zvni_lookup(zvrf
, vni
);
3248 "Failed to locate VNI hash upon remote MACIP ADD, VRF %d VNI %u",
3249 zvrf_id(zvrf
), vni
);
3252 ifp
= zvni
->vxlan_if
;
3255 "VNI %u hash %p doesn't have intf upon remote MACIP add",
3261 /* If down or not mapped to a bridge, we're done. */
3262 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
3265 /* The remote VTEP specified should normally exist, but it is
3267 * that when peering comes up, peer may advertise MACIP routes
3269 * advertising type-3 routes.
3271 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
3273 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
3275 "Failed to add remote VTEP, VRF %d VNI %u zvni %p",
3276 zvrf_id(zvrf
), vni
, zvni
);
3280 zvni_vtep_install(zvni
, &vtep_ip
);
3283 /* First, check if the remote MAC is unknown or has a change. If
3285 * that needs to be updated first. Note that client could
3287 * MAC and MACIP separately or just install the latter.
3289 mac
= zvni_mac_lookup(zvni
, &macaddr
);
3290 if (!mac
|| !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
3291 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0)
3293 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
))
3298 mac
= zvni_mac_add(zvni
, &macaddr
);
3301 "%u:Failed to add MAC %s VNI %u Remote VTEP %s",
3303 prefix_mac2str(&macaddr
, buf
,
3305 vni
, inet_ntoa(vtep_ip
));
3309 /* Is this MAC created for a MACIP? */
3311 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
3314 /* Set "auto" and "remote" forwarding info. */
3315 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
3316 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
3317 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3318 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
3321 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
3323 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
3325 zvni_process_neigh_on_remote_mac_add(zvrf
, zvni
, mac
);
3327 /* Install the entry. */
3328 zvni_mac_install(zvni
, mac
);
3331 /* If there is no IP, continue - after clearing AUTO flag of
3334 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
3338 /* Check if the remote neighbor itself is unknown or has a
3340 * If so, create or update and then install the entry.
3342 n
= zvni_neigh_lookup(zvni
, &ip
);
3343 if (!n
|| !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
3344 || (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
)) != 0)
3345 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
))
3350 n
= zvni_neigh_add(zvni
, &ip
, &macaddr
);
3353 "%u:Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
3355 ipaddr2str(&ip
, buf1
,
3357 prefix_mac2str(&macaddr
, buf
,
3359 vni
, inet_ntoa(vtep_ip
));
3363 } else if (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
))
3365 /* MAC change, update neigh list for old and new
3367 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
3369 listnode_delete(old_mac
->neigh_list
, n
);
3370 zvni_deref_ip2mac(zvni
, old_mac
, 1);
3372 listnode_add_sort(mac
->neigh_list
, n
);
3373 memcpy(&n
->emac
, &macaddr
, ETH_ALEN
);
3376 /* Set "remote" forwarding info. */
3377 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3378 /* TODO: Handle MAC change. */
3379 n
->r_vtep_ip
= vtep_ip
;
3380 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3382 /* Install the entry. */
3383 zvni_neigh_install(zvni
, n
);
3391 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
3392 * us, this must involve a multihoming scenario. Treat this as implicit delete
3393 * of any prior local MAC.
3395 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
3396 struct interface
*br_if
,
3397 struct ethaddr
*macaddr
, vlanid_t vid
)
3399 struct zebra_if
*zif
;
3400 struct zebra_vrf
*zvrf
;
3401 struct zebra_l2info_vxlan
*vxl
;
3405 char buf
[ETHER_ADDR_STRLEN
];
3410 vxl
= &zif
->l2info
.vxl
;
3413 /* Locate VRF corresponding to interface. */
3414 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
3417 /* If EVPN is not enabled, nothing to do. */
3418 if (!EVPN_ENABLED(zvrf
))
3421 /* Locate hash entry; it is expected to exist. */
3422 zvni
= zvni_lookup(zvrf
, vni
);
3426 /* If entry doesn't exist, nothing to do. */
3427 mac
= zvni_mac_lookup(zvni
, macaddr
);
3431 /* Is it a local entry? */
3432 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
3435 if (IS_ZEBRA_DEBUG_VXLAN
)
3437 "%u:Add/update remote MAC %s intf %s(%u) VNI %u - del local",
3438 ifp
->vrf_id
, prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3439 ifp
->name
, ifp
->ifindex
, vni
);
3441 /* Remove MAC from BGP. */
3442 sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0;
3443 zvni_mac_send_del_to_client(zvrf
, zvni
->vni
, macaddr
,
3444 (sticky
? ZEBRA_MAC_TYPE_STICKY
: 0));
3447 * If there are no neigh associated with the mac delete the mac
3448 * else mark it as AUTO for forward reference
3450 if (!listcount(mac
->neigh_list
)) {
3451 zvni_mac_del(zvni
, mac
);
3453 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
3454 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
3461 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
3462 * This can happen because the remote MAC entries are also added as "dynamic",
3463 * so the kernel can ageout the entry.
3465 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
3466 struct interface
*br_if
,
3467 struct ethaddr
*macaddr
, vlanid_t vid
)
3469 struct zebra_if
*zif
;
3470 struct zebra_vrf
*zvrf
;
3471 struct zebra_l2info_vxlan
*vxl
;
3475 char buf
[ETHER_ADDR_STRLEN
];
3479 vxl
= &zif
->l2info
.vxl
;
3482 /* Locate VRF corresponding to interface. */
3483 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
3486 /* If EVPN is not enabled, nothing to do. */
3487 if (!EVPN_ENABLED(zvrf
))
3490 /* Locate hash entry; it is expected to exist. */
3491 zvni
= zvni_lookup(zvrf
, vni
);
3495 /* If entry doesn't exist, nothing to do. */
3496 mac
= zvni_mac_lookup(zvni
, macaddr
);
3500 /* Is it a remote entry? */
3501 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3504 if (IS_ZEBRA_DEBUG_VXLAN
)
3505 zlog_debug("%u:Del remote MAC %s intf %s(%u) VNI %u - readd",
3507 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
3510 zvni_mac_install(zvni
, mac
);
3515 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
3517 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
3518 struct ethaddr
*macaddr
, vlanid_t vid
)
3522 struct zebra_vrf
*zvrf
;
3523 char buf
[ETHER_ADDR_STRLEN
];
3526 /* We are interested in MACs only on ports or (port, VLAN) that
3529 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
3532 if (!zvni
->vxlan_if
) {
3533 zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL",
3538 if (IS_ZEBRA_DEBUG_VXLAN
)
3539 zlog_debug("%u:Del MAC %s intf %s(%u) VID %u -> VNI %u",
3541 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
3542 ifp
->ifindex
, vid
, zvni
->vni
);
3544 /* If entry doesn't exist, nothing to do. */
3545 mac
= zvni_mac_lookup(zvni
, macaddr
);
3549 /* Is it a local entry? */
3550 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
3553 /* Locate VRF corresponding to interface. */
3554 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
3557 /* Remove MAC from BGP. */
3558 sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0;
3559 zvni_mac_send_del_to_client(zvrf
, zvni
->vni
, macaddr
,
3560 (sticky
? ZEBRA_MAC_TYPE_STICKY
: 0));
3562 /* Update all the neigh entries associated with this mac */
3563 zvni_process_neigh_on_local_mac_del(zvrf
, zvni
, mac
);
3566 * If there are no neigh associated with the mac delete the mac
3567 * else mark it as AUTO for forward reference
3569 if (!listcount(mac
->neigh_list
)) {
3570 zvni_mac_del(zvni
, mac
);
3572 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
3573 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
3580 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
3582 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
3583 struct interface
*br_if
,
3584 struct ethaddr
*macaddr
, vlanid_t vid
,
3589 struct zebra_vrf
*zvrf
;
3590 char buf
[ETHER_ADDR_STRLEN
];
3594 /* We are interested in MACs only on ports or (port, VLAN) that
3597 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
3599 if (IS_ZEBRA_DEBUG_VXLAN
)
3601 "%u:Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
3602 ifp
->vrf_id
, sticky
? "sticky " : "",
3603 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3604 ifp
->name
, ifp
->ifindex
, vid
);
3608 if (!zvni
->vxlan_if
) {
3609 zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD",
3614 if (IS_ZEBRA_DEBUG_VXLAN
)
3616 "%u:Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
3617 ifp
->vrf_id
, sticky
? "sticky " : "",
3618 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
3619 ifp
->ifindex
, vid
, zvni
->vni
);
3621 /* If same entry already exists, nothing to do. */
3622 mac
= zvni_mac_lookup(zvni
, macaddr
);
3624 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
3625 mac_sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
3631 * return if nothing has changed.
3632 * inform bgp if sticky flag has changed
3633 * update locally and do not inform bgp if local
3634 * parameters like interface has changed
3636 if (mac_sticky
== sticky
3637 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
3638 && mac
->fwd_info
.local
.vid
== vid
) {
3639 if (IS_ZEBRA_DEBUG_VXLAN
)
3641 "%u:Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
3642 "entry exists and has not changed ",
3644 sticky
? "sticky " : "",
3645 prefix_mac2str(macaddr
, buf
,
3647 ifp
->name
, ifp
->ifindex
, vid
,
3650 } else if (mac_sticky
!= sticky
) {
3653 add
= 0; /* This is an update of local
3656 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
3658 * If we have already learned the MAC as a remote sticky
3660 * this is a operator error and we must log a warning
3662 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
3664 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
3665 prefix_mac2str(macaddr
, buf
,
3667 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
3674 /* Locate VRF corresponding to interface. */
3675 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
3679 mac
= zvni_mac_add(zvni
, macaddr
);
3681 zlog_err("%u:Failed to add MAC %s intf %s(%u) VID %u",
3683 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3684 ifp
->name
, ifp
->ifindex
, vid
);
3689 /* Set "local" forwarding info. */
3690 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3691 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
3692 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
3693 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
3694 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
3695 mac
->fwd_info
.local
.vid
= vid
;
3698 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
3700 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
3702 /* Inform BGP if required. */
3704 zvni_process_neigh_on_local_mac_add(zvrf
, zvni
, mac
);
3705 return zvni_mac_send_add_to_client(zvrf
, zvni
->vni
, macaddr
,
3713 * Handle message from client to delete a remote VTEP for a VNI.
3715 int zebra_vxlan_remote_vtep_del(struct zserv
*client
, int sock
, u_short length
,
3716 struct zebra_vrf
*zvrf
)
3721 struct in_addr vtep_ip
;
3723 zebra_vtep_t
*zvtep
;
3724 struct interface
*ifp
;
3725 struct zebra_if
*zif
;
3729 while (l
< length
) {
3730 /* Obtain each remote VTEP and process. */
3731 vni
= (vni_t
)stream_getl(s
);
3733 vtep_ip
.s_addr
= stream_get_ipv4(s
);
3734 l
+= IPV4_MAX_BYTELEN
;
3736 if (IS_ZEBRA_DEBUG_VXLAN
)
3737 zlog_debug("%u:Recv VTEP_DEL %s VNI %u from %s",
3738 zvrf_id(zvrf
), inet_ntoa(vtep_ip
), vni
,
3739 zebra_route_string(client
->proto
));
3741 /* Locate VNI hash entry - expected to exist. */
3742 zvni
= zvni_lookup(zvrf
, vni
);
3744 if (IS_ZEBRA_DEBUG_VXLAN
)
3746 "Failed to locate VNI hash upon remote VTEP DEL, "
3748 zvrf_id(zvrf
), vni
);
3752 ifp
= zvni
->vxlan_if
;
3755 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
3761 /* If down or not mapped to a bridge, we're done. */
3762 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
3765 /* If the remote VTEP does not exist, there's nothing more to
3767 * Otherwise, uninstall any remote MACs pointing to this VTEP
3769 * then, the VTEP entry itself and remove it.
3771 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
3775 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
3776 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
3777 zvni_vtep_uninstall(zvni
, &vtep_ip
);
3778 zvni_vtep_del(zvni
, zvtep
);
3785 * Handle message from client to add a remote VTEP for a VNI.
3787 int zebra_vxlan_remote_vtep_add(struct zserv
*client
, int sock
, u_short length
,
3788 struct zebra_vrf
*zvrf
)
3793 struct in_addr vtep_ip
;
3795 struct interface
*ifp
;
3796 struct zebra_if
*zif
;
3798 assert(EVPN_ENABLED(zvrf
));
3802 while (l
< length
) {
3803 /* Obtain each remote VTEP and process. */
3804 vni
= (vni_t
)stream_getl(s
);
3806 vtep_ip
.s_addr
= stream_get_ipv4(s
);
3807 l
+= IPV4_MAX_BYTELEN
;
3809 if (IS_ZEBRA_DEBUG_VXLAN
)
3810 zlog_debug("%u:Recv VTEP_ADD %s VNI %u from %s",
3811 zvrf_id(zvrf
), inet_ntoa(vtep_ip
), vni
,
3812 zebra_route_string(client
->proto
));
3814 /* Locate VNI hash entry - expected to exist. */
3815 zvni
= zvni_lookup(zvrf
, vni
);
3818 "Failed to locate VNI hash upon remote VTEP ADD, VRF %d VNI %u",
3819 zvrf_id(zvrf
), vni
);
3823 ifp
= zvni
->vxlan_if
;
3826 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
3833 /* If down or not mapped to a bridge, we're done. */
3834 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
3837 /* If the remote VTEP already exists,
3838 there's nothing more to do. */
3839 if (zvni_vtep_find(zvni
, &vtep_ip
))
3842 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
3844 "Failed to add remote VTEP, VRF %d VNI %u zvni %p",
3845 zvrf_id(zvrf
), vni
, zvni
);
3849 zvni_vtep_install(zvni
, &vtep_ip
);
3856 * Add/Del gateway macip to evpn
3858 * 1. SVI interface on a vlan aware bridge
3859 * 2. SVI interface on a vlan unaware bridge
3860 * 3. vrr interface (MACVLAN) associated to a SVI
3861 * We advertise macip routes for an interface if it is associated to VxLan vlan
3863 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
3867 struct ethaddr macaddr
;
3868 zebra_vni_t
*zvni
= NULL
;
3869 struct zebra_vrf
*zvrf
= NULL
;
3871 memset(&ip
, 0, sizeof(struct ipaddr
));
3872 memset(&macaddr
, 0, sizeof(struct ethaddr
));
3874 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
3878 if (!EVPN_ENABLED(zvrf
))
3881 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
3882 struct interface
*svi_if
=
3883 NULL
; /* SVI corresponding to the MACVLAN */
3884 struct zebra_if
*ifp_zif
=
3885 NULL
; /* Zebra daemon specific info for MACVLAN */
3886 struct zebra_if
*svi_if_zif
=
3887 NULL
; /* Zebra daemon specific info for SVI*/
3889 ifp_zif
= ifp
->info
;
3894 * for a MACVLAN interface the link represents the svi_if
3896 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
3897 ifp_zif
->link_ifindex
);
3899 zlog_err("%u:MACVLAN %s(%u) without link information",
3900 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
);
3904 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
3906 * If it is a vlan aware bridge then the link gives the
3907 * bridge information
3909 struct interface
*svi_if_link
= NULL
;
3911 svi_if_zif
= svi_if
->info
;
3913 svi_if_link
= if_lookup_by_index_per_ns(
3914 zebra_ns_lookup(NS_DEFAULT
),
3915 svi_if_zif
->link_ifindex
);
3916 zvni
= zvni_map_svi(svi_if
, svi_if_link
);
3918 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
3920 * If it is a vlan unaware bridge then svi is the bridge
3923 zvni
= zvni_map_svi(svi_if
, svi_if
);
3925 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
3926 struct zebra_if
*svi_if_zif
=
3927 NULL
; /* Zebra daemon specific info for SVI */
3928 struct interface
*svi_if_link
=
3929 NULL
; /* link info for the SVI = bridge info */
3931 svi_if_zif
= ifp
->info
;
3932 svi_if_link
= if_lookup_by_index_per_ns(
3933 zebra_ns_lookup(NS_DEFAULT
), svi_if_zif
->link_ifindex
);
3934 if (svi_if_zif
&& svi_if_link
)
3935 zvni
= zvni_map_svi(ifp
, svi_if_link
);
3936 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
3937 zvni
= zvni_map_svi(ifp
, ifp
);
3943 if (!zvni
->vxlan_if
) {
3944 zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
3950 /* check if we are advertising gw macip routes */
3951 if (!advertise_gw_macip_enabled(zvrf
, zvni
))
3954 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
3956 if (p
->family
== AF_INET
) {
3957 ip
.ipa_type
= IPADDR_V4
;
3958 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
3959 sizeof(struct in_addr
));
3960 } else if (p
->family
== AF_INET6
) {
3961 ip
.ipa_type
= IPADDR_V6
;
3962 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
3963 sizeof(struct in6_addr
));
3968 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
3970 zvni_gw_macip_del(ifp
, zvni
, &ip
);
3976 * Handle SVI interface going down. At this point, this is a NOP since
3977 * the kernel deletes the neighbor entries on this SVI (if any).
3979 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
3985 * Handle SVI interface coming up. This may or may not be of interest,
3986 * but if this is a SVI on a VxLAN bridge, we need to install any remote
3987 * neighbor entries (which will be used for EVPN ARP suppression).
3989 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
3992 struct neigh_walk_ctx n_wctx
;
3994 zvni
= zvni_map_svi(ifp
, link_if
);
3998 if (!zvni
->vxlan_if
) {
3999 zlog_err("VNI %u hash %p doesn't have intf upon SVI up",
4004 if (IS_ZEBRA_DEBUG_VXLAN
)
4005 zlog_debug("%u:SVI %s(%u) VNI %u is UP, installing neighbors",
4006 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
4008 /* Install any remote neighbors for this VNI. */
4009 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
4011 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
, &n_wctx
);
4017 * Handle VxLAN interface down - update BGP if required, and do
4020 int zebra_vxlan_if_down(struct interface
*ifp
)
4022 struct zebra_if
*zif
;
4023 struct zebra_vrf
*zvrf
;
4025 struct zebra_l2info_vxlan
*vxl
;
4028 /* Locate VRF corresponding to interface. */
4029 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
4032 /* If EVPN is not enabled, nothing further to be done. */
4033 if (!EVPN_ENABLED(zvrf
))
4038 vxl
= &zif
->l2info
.vxl
;
4041 if (IS_ZEBRA_DEBUG_VXLAN
)
4042 zlog_debug("%u:Intf %s(%u) VNI %u is DOWN", ifp
->vrf_id
,
4043 ifp
->name
, ifp
->ifindex
, vni
);
4045 /* Locate hash entry; it is expected to exist. */
4046 zvni
= zvni_lookup(zvrf
, vni
);
4049 "Failed to locate VNI hash at DOWN, VRF %d IF %s(%u) VNI %u",
4050 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, vni
);
4054 assert(zvni
->vxlan_if
== ifp
);
4056 /* Delete this VNI from BGP. */
4057 zvni_send_del_to_client(zvrf
, zvni
->vni
);
4059 /* Free up all neighbors and MACs, if any. */
4060 zvni_neigh_del_all(zvrf
, zvni
, 1, 0, DEL_ALL_NEIGH
);
4061 zvni_mac_del_all(zvrf
, zvni
, 1, 0, DEL_ALL_MAC
);
4063 /* Free up all remote VTEPs, if any. */
4064 zvni_vtep_del_all(zvni
, 1);
4070 * Handle VxLAN interface up - update BGP if required.
4072 int zebra_vxlan_if_up(struct interface
*ifp
)
4074 struct zebra_if
*zif
;
4075 struct zebra_vrf
*zvrf
;
4077 struct zebra_l2info_vxlan
*vxl
;
4080 /* Locate VRF corresponding to interface. */
4081 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
4084 /* If EVPN is not enabled, nothing further to be done. */
4085 if (!EVPN_ENABLED(zvrf
))
4090 vxl
= &zif
->l2info
.vxl
;
4093 if (IS_ZEBRA_DEBUG_VXLAN
)
4094 zlog_debug("%u:Intf %s(%u) VNI %u is UP", ifp
->vrf_id
,
4095 ifp
->name
, ifp
->ifindex
, vni
);
4097 /* Locate hash entry; it is expected to exist. */
4098 zvni
= zvni_lookup(zvrf
, vni
);
4101 "Failed to locate VNI hash at UP, VRF %d IF %s(%u) VNI %u",
4102 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, vni
);
4106 assert(zvni
->vxlan_if
== ifp
);
4108 /* If part of a bridge, inform BGP about this VNI. */
4109 /* Also, read and populate local MACs and neighbors. */
4110 if (zif
->brslave_info
.br_if
) {
4111 zvni_send_add_to_client(zvrf
, zvni
);
4112 zvni_read_mac_neigh(zvrf
, zvni
, ifp
);
4119 * Handle VxLAN interface delete. Locate and remove entry in hash table
4120 * and update BGP, if required.
4122 int zebra_vxlan_if_del(struct interface
*ifp
)
4124 struct zebra_if
*zif
;
4125 struct zebra_vrf
*zvrf
;
4127 struct zebra_l2info_vxlan
*vxl
;
4130 /* Locate VRF corresponding to interface. */
4131 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
4134 /* If EVPN is not enabled, nothing further to be done. */
4135 if (!EVPN_ENABLED(zvrf
))
4140 vxl
= &zif
->l2info
.vxl
;
4143 if (IS_ZEBRA_DEBUG_VXLAN
)
4144 zlog_debug("%u:Del VNI %u intf %s(%u)", ifp
->vrf_id
, vni
,
4145 ifp
->name
, ifp
->ifindex
);
4147 /* Locate hash entry; it is expected to exist. */
4148 zvni
= zvni_lookup(zvrf
, vni
);
4151 "Failed to locate VNI hash at del, VRF %d IF %s(%u) VNI %u",
4152 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, vni
);
4156 /* Delete VNI from BGP. */
4157 zvni_send_del_to_client(zvrf
, zvni
->vni
);
4159 /* Free up all neighbors and MAC, if any. */
4160 zvni_neigh_del_all(zvrf
, zvni
, 0, 0, DEL_ALL_NEIGH
);
4161 zvni_mac_del_all(zvrf
, zvni
, 0, 0, DEL_ALL_MAC
);
4163 /* Free up all remote VTEPs, if any. */
4164 zvni_vtep_del_all(zvni
, 0);
4166 /* Delete the hash entry. */
4167 if (zvni_del(zvrf
, zvni
)) {
4168 zlog_err("Failed to del VNI hash %p, VRF %d IF %s(%u) VNI %u",
4169 zvni
, ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
4177 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
4179 int zebra_vxlan_if_update(struct interface
*ifp
, u_int16_t chgflags
)
4181 struct zebra_if
*zif
;
4182 struct zebra_vrf
*zvrf
;
4184 struct zebra_l2info_vxlan
*vxl
;
4187 /* Locate VRF corresponding to interface. */
4188 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
4191 /* If EVPN is not enabled, nothing further to be done. */
4192 if (!EVPN_ENABLED(zvrf
))
4197 vxl
= &zif
->l2info
.vxl
;
4200 /* Update VNI hash. */
4201 zvni
= zvni_lookup(zvrf
, vni
);
4204 "Failed to find VNI hash on update, VRF %d IF %s(%u) VNI %u",
4205 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, vni
);
4209 if (IS_ZEBRA_DEBUG_VXLAN
)
4211 "%u:Update VNI %u intf %s(%u) VLAN %u local IP %s "
4212 "master %u chg 0x%x",
4213 ifp
->vrf_id
, vni
, ifp
->name
, ifp
->ifindex
,
4214 vxl
->access_vlan
, inet_ntoa(vxl
->vtep_ip
),
4215 zif
->brslave_info
.bridge_ifindex
, chgflags
);
4217 /* Removed from bridge? Cleanup and return */
4218 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
4219 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
4220 /* Delete from client, remove all remote VTEPs */
4221 /* Also, free up all MACs and neighbors. */
4222 zvni_send_del_to_client(zvrf
, zvni
->vni
);
4223 zvni_neigh_del_all(zvrf
, zvni
, 1, 0, DEL_ALL_NEIGH
);
4224 zvni_mac_del_all(zvrf
, zvni
, 1, 0, DEL_ALL_MAC
);
4225 zvni_vtep_del_all(zvni
, 1);
4229 /* Handle other changes. */
4230 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
4231 /* Remove all existing local neighbors and MACs for this VNI
4232 * (including from BGP)
4234 zvni_neigh_del_all(zvrf
, zvni
, 0, 1, DEL_LOCAL_MAC
);
4235 zvni_mac_del_all(zvrf
, zvni
, 0, 1, DEL_LOCAL_MAC
);
4238 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4239 zvni
->vxlan_if
= ifp
;
4241 /* Take further actions needed. Note that if we are here, there is a
4242 * change of interest.
4244 /* If down or not mapped to a bridge, we're done. */
4245 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
4248 /* Inform BGP, if there is a change of interest. */
4250 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
4251 zvni_send_add_to_client(zvrf
, zvni
);
4253 /* If there is a valid new master or a VLAN mapping change, read and
4254 * populate local MACs and neighbors. Also, reinstall any remote MACs
4255 * and neighbors for this VNI (based on new VLAN).
4257 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
4258 zvni_read_mac_neigh(zvrf
, zvni
, ifp
);
4259 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
4260 struct mac_walk_ctx m_wctx
;
4261 struct neigh_walk_ctx n_wctx
;
4263 zvni_read_mac_neigh(zvrf
, zvni
, ifp
);
4265 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
4267 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
, &m_wctx
);
4269 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
4271 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
4279 * Handle VxLAN interface add.
4281 int zebra_vxlan_if_add(struct interface
*ifp
)
4283 struct zebra_if
*zif
;
4284 struct zebra_vrf
*zvrf
;
4286 struct zebra_l2info_vxlan
*vxl
;
4289 /* Locate VRF corresponding to interface. */
4290 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
4293 /* If EVPN is not enabled, nothing further to be done. */
4294 if (!EVPN_ENABLED(zvrf
))
4299 vxl
= &zif
->l2info
.vxl
;
4302 if (IS_ZEBRA_DEBUG_VXLAN
)
4304 "%u:Add VNI %u intf %s(%u) VLAN %u local IP %s master %u",
4305 ifp
->vrf_id
, vni
, ifp
->name
, ifp
->ifindex
,
4306 vxl
->access_vlan
, inet_ntoa(vxl
->vtep_ip
),
4307 zif
->brslave_info
.bridge_ifindex
);
4309 /* Create or update VNI hash. */
4310 zvni
= zvni_lookup(zvrf
, vni
);
4312 zvni
= zvni_add(zvrf
, vni
);
4315 "Failed to add VNI hash, VRF %d IF %s(%u) VNI %u",
4316 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, vni
);
4321 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4322 zvni
->vxlan_if
= ifp
;
4324 /* If down or not mapped to a bridge, we're done. */
4325 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
4329 zvni_send_add_to_client(zvrf
, zvni
);
4331 /* Read and populate local MACs and neighbors */
4332 zvni_read_mac_neigh(zvrf
, zvni
, ifp
);
4338 * Handle message from client to enable/disable advertisement of g/w macip
4341 int zebra_vxlan_advertise_gw_macip(struct zserv
*client
, int sock
,
4342 u_short length
, struct zebra_vrf
*zvrf
)
4347 zebra_vni_t
*zvni
= NULL
;
4348 struct interface
*ifp
= NULL
;
4351 advertise
= stream_getc(s
);
4352 vni
= stream_get3(s
);
4355 if (IS_ZEBRA_DEBUG_VXLAN
)
4356 zlog_debug("%u:EVPN gateway macip Adv %s, currently %s",
4358 advertise
? "enabled" : "disabled",
4359 advertise_gw_macip_enabled(zvrf
, NULL
)
4363 if (zvrf
->advertise_gw_macip
== advertise
)
4366 zvrf
->advertise_gw_macip
= advertise
;
4368 if (advertise_gw_macip_enabled(zvrf
, zvni
))
4369 hash_iterate(zvrf
->vni_table
,
4370 zvni_gw_macip_add_for_vni_hash
, zvrf
);
4372 hash_iterate(zvrf
->vni_table
,
4373 zvni_gw_macip_del_for_vni_hash
, zvrf
);
4376 struct zebra_if
*zif
= NULL
;
4377 struct zebra_l2info_vxlan zl2_info
;
4378 struct interface
*vlan_if
= NULL
;
4379 struct interface
*vrr_if
= NULL
;
4381 if (IS_ZEBRA_DEBUG_VXLAN
)
4383 "%u:EVPN gateway macip Adv %s on VNI %d , currently %s",
4385 advertise
? "enabled" : "disabled", vni
,
4386 advertise_gw_macip_enabled(zvrf
, zvni
)
4390 zvni
= zvni_lookup(zvrf
, vni
);
4394 if (zvni
->advertise_gw_macip
== advertise
)
4397 zvni
->advertise_gw_macip
= advertise
;
4399 ifp
= zvni
->vxlan_if
;
4405 /* If down or not mapped to a bridge, we're done. */
4406 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
4409 zl2_info
= zif
->l2info
.vxl
;
4411 vlan_if
= zvni_map_to_svi(zvrf
, zl2_info
.access_vlan
,
4412 zif
->brslave_info
.br_if
);
4416 if (advertise_gw_macip_enabled(zvrf
, zvni
)) {
4417 /* Add primary SVI MAC-IP */
4418 zvni_add_macip_for_intf(vlan_if
, zvni
);
4420 /* Add VRR MAC-IP - if any*/
4421 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
4423 zvni_add_macip_for_intf(vrr_if
, zvni
);
4425 /* Del primary MAC-IP */
4426 zvni_del_macip_for_intf(vlan_if
, zvni
);
4428 /* Del VRR MAC-IP - if any*/
4429 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
4431 zvni_del_macip_for_intf(vrr_if
, zvni
);
4440 * Handle message from client to learn (or stop learning) about VNIs and MACs.
4441 * When enabled, the VNI hash table will be built and MAC FDB table read;
4442 * when disabled, the entries should be deleted and remote VTEPs and MACs
4443 * uninstalled from the kernel.
4445 int zebra_vxlan_advertise_all_vni(struct zserv
*client
, int sock
,
4446 u_short length
, struct zebra_vrf
*zvrf
)
4452 advertise
= stream_getc(s
);
4454 if (IS_ZEBRA_DEBUG_VXLAN
)
4455 zlog_debug("%u:EVPN VNI Adv %s, currently %s", zvrf_id(zvrf
),
4456 advertise
? "enabled" : "disabled",
4457 EVPN_ENABLED(zvrf
) ? "enabled" : "disabled");
4459 if (zvrf
->advertise_all_vni
== advertise
)
4462 zvrf
->advertise_all_vni
= advertise
;
4463 if (EVPN_ENABLED(zvrf
)) {
4464 /* Build VNI hash table and inform BGP. */
4465 zvni_build_hash_table(zvrf
);
4467 /* Add all SVI (L3 GW) MACs to BGP*/
4468 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
4471 /* Read the MAC FDB */
4472 macfdb_read(zvrf
->zns
);
4474 /* Read neighbors */
4475 neigh_read(zvrf
->zns
);
4477 /* Cleanup VTEPs for all VNIs - uninstall from
4478 * kernel and free entries.
4480 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
4487 * Allocate VNI hash table for this VRF and do other initialization.
4488 * NOTE: Currently supported only for default VRF.
4490 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
4494 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
4495 "Zebra VRF VNI Table");
4498 /* Close all VNI handling */
4499 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
4501 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
4502 hash_free(zvrf
->vni_table
);