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"
50 DEFINE_MTYPE_STATIC(ZEBRA
, HOST_PREFIX
, "host prefix");
51 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI
, "VNI hash");
52 DEFINE_MTYPE_STATIC(ZEBRA
, ZL3VNI
, "L3 VNI hash");
53 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI_VTEP
, "VNI remote VTEP");
54 DEFINE_MTYPE_STATIC(ZEBRA
, MAC
, "VNI MAC");
55 DEFINE_MTYPE_STATIC(ZEBRA
, NEIGH
, "VNI Neighbor");
60 /* static function declarations */
61 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
63 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
64 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
);
65 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
67 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
69 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
71 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
);
72 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
);
73 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
);
74 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
75 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[]);
77 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
78 struct ipaddr
*ip
, uint8_t flags
,
80 static unsigned int neigh_hash_keymake(void *p
);
81 static int neigh_cmp(const void *p1
, const void *p2
);
82 static void *zvni_neigh_alloc(void *p
);
83 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
85 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
86 static int zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
);
87 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
88 struct in_addr
*r_vtep_ip
);
89 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
91 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
);
92 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
93 struct ethaddr
*macaddr
,
95 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
96 struct ethaddr
*macaddr
,
98 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
99 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
100 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
101 struct interface
*br_if
);
102 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
);
104 /* l3-vni next-hop neigh related APIs */
105 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
107 static void *zl3vni_nh_alloc(void *p
);
108 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
109 struct ipaddr
*vtep_ip
,
110 struct ethaddr
*rmac
);
111 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
112 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
113 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
115 /* l3-vni rmac related APIs */
116 static void zl3vni_print_rmac_hash(struct hash_backet
*, void *);
117 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
118 struct ethaddr
*rmac
);
119 static void *zl3vni_rmac_alloc(void *p
);
120 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
121 struct ethaddr
*rmac
);
122 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
123 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
124 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
126 /* l3-vni related APIs*/
127 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
);
128 static void *zl3vni_alloc(void *p
);
129 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
130 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
131 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t
);
132 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
);
133 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
);
134 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
135 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
137 static unsigned int mac_hash_keymake(void *p
);
138 static int mac_cmp(const void *p1
, const void *p2
);
139 static void *zvni_mac_alloc(void *p
);
140 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
141 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
142 static int zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
);
143 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
144 struct in_addr
*r_vtep_ip
);
145 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
147 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
148 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
150 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
152 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
153 struct interface
*br_if
, vlanid_t vid
);
154 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
155 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
);
156 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
);
158 static unsigned int vni_hash_keymake(void *p
);
159 static int vni_hash_cmp(const void *p1
, const void *p2
);
160 static void *zvni_alloc(void *p
);
161 static zebra_vni_t
*zvni_lookup(vni_t vni
);
162 static zebra_vni_t
*zvni_add(vni_t vni
);
163 static int zvni_del(zebra_vni_t
*zvni
);
164 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
165 static int zvni_send_del_to_client(vni_t vni
);
166 static void zvni_build_hash_table();
167 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
168 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
169 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
170 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
171 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
172 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
173 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
174 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
175 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
176 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
177 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
178 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
180 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
181 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
182 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
185 /* Private functions */
188 * Return number of valid MACs in a VNI's MAC hash table - all
189 * remote MACs and non-internal (auto) local MACs count.
191 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
194 uint32_t num_macs
= 0;
196 struct hash_backet
*hb
;
199 hash
= zvni
->mac_table
;
202 for (i
= 0; i
< hash
->size
; i
++) {
203 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
204 mac
= (zebra_mac_t
*)hb
->data
;
205 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
206 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
214 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
216 struct zebra_vrf
*zvrf
;
218 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
219 if (zvrf
&& zvrf
->advertise_gw_macip
)
222 if (zvni
&& zvni
->advertise_gw_macip
)
229 * Helper function to determine maximum width of neighbor IP address for
230 * display - just because we're dealing with IPv6 addresses that can
233 static void zvni_find_neigh_addr_width(struct hash_backet
*backet
, void *ctxt
)
236 char buf
[INET6_ADDRSTRLEN
];
237 struct neigh_walk_ctx
*wctx
= ctxt
;
240 n
= (zebra_neigh_t
*)backet
->data
;
244 ipaddr2str(&n
->ip
, buf
, sizeof(buf
)), width
= strlen(buf
);
245 if (width
> wctx
->addr_width
)
246 wctx
->addr_width
= width
;
250 * Print a specific neighbor entry.
252 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
255 char buf1
[ETHER_ADDR_STRLEN
];
256 char buf2
[INET6_ADDRSTRLEN
];
258 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
259 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
260 vty
= (struct vty
*)ctxt
;
262 vty_out(vty
, "IP: %s\n",
263 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
264 vty_out(vty
, " MAC: %s",
265 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
267 json_object_string_add(json
, "ip", buf2
);
268 json_object_string_add(json
, "mac", buf1
);
270 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
272 vty_out(vty
, " Remote VTEP: %s",
273 inet_ntoa(n
->r_vtep_ip
));
275 json_object_string_add(json
, "remoteVtep",
276 inet_ntoa(n
->r_vtep_ip
));
278 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
281 vty_out(vty
, " State: %s",
282 IS_ZEBRA_NEIGH_ACTIVE(n
) ? "Active"
286 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
288 vty_out(vty
, " Default-gateway");
290 json_object_boolean_true_add(json
, "defaultGateway");
297 * Print neighbor hash entry - called for display of all neighbors.
299 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
302 json_object
*json_vni
= NULL
, *json_row
= NULL
;
304 char buf1
[ETHER_ADDR_STRLEN
];
305 char buf2
[INET6_ADDRSTRLEN
];
306 struct neigh_walk_ctx
*wctx
= ctxt
;
309 json_vni
= wctx
->json
;
310 n
= (zebra_neigh_t
*)backet
->data
;
315 json_row
= json_object_new_object();
317 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
318 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
319 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)
320 && !(wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)) {
321 if (json_vni
== NULL
) {
322 vty_out(vty
, "%*s %-6s %-17s\n", -wctx
->addr_width
,
323 buf2
, "local", buf1
);
325 json_object_string_add(json_row
, "type", "local");
326 json_object_string_add(json_row
, "mac", buf1
);
330 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) {
331 if (IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
)) {
332 if (json_vni
== NULL
) {
333 if (wctx
->count
== 0)
335 "%*s %-6s %-17s %-21s\n",
338 "MAC", "Remote VTEP");
339 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
340 -wctx
->addr_width
, buf2
,
342 inet_ntoa(n
->r_vtep_ip
));
344 json_object_string_add(json_row
, "type",
346 json_object_string_add(json_row
, "mac",
348 json_object_string_add(
349 json_row
, "remoteVtep",
350 inet_ntoa(n
->r_vtep_ip
));
355 if (json_vni
== NULL
) {
356 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
357 -wctx
->addr_width
, buf2
, "remote", buf1
,
358 inet_ntoa(n
->r_vtep_ip
));
360 json_object_string_add(json_row
, "type",
362 json_object_string_add(json_row
, "mac", buf1
);
363 json_object_string_add(json_row
, "remoteVtep",
364 inet_ntoa(n
->r_vtep_ip
));
371 json_object_object_add(json_vni
, buf2
, json_row
);
375 * Print neighbors for all VNI.
377 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
381 json_object
*json
= NULL
, *json_vni
= NULL
;
384 struct neigh_walk_ctx wctx
;
385 char vni_str
[VNI_STR_LEN
];
387 vty
= (struct vty
*)args
[0];
388 json
= (json_object
*)args
[1];
390 zvni
= (zebra_vni_t
*)backet
->data
;
393 vty_out(vty
, "{}\n");
396 num_neigh
= hashcount(zvni
->neigh_table
);
399 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
400 zvni
->vni
, num_neigh
);
402 json_vni
= json_object_new_object();
403 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
404 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
408 json_object_object_add(json
, vni_str
, json_vni
);
412 /* Since we have IPv6 addresses to deal with which can vary widely in
413 * size, we try to be a bit more elegant in display by first computing
416 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
419 wctx
.addr_width
= 15;
420 wctx
.json
= json_vni
;
421 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
424 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
425 "Type", "MAC", "Remote VTEP");
426 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
429 json_object_object_add(json
, vni_str
, json_vni
);
432 /* print a specific next hop for an l3vni */
433 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
436 char buf1
[ETHER_ADDR_STRLEN
];
437 char buf2
[INET6_ADDRSTRLEN
];
438 struct listnode
*node
= NULL
;
439 struct prefix
*p
= NULL
;
440 json_object
*json_hosts
= NULL
;
443 vty_out(vty
, "Ip: %s\n",
444 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
445 vty_out(vty
, " RMAC: %s\n",
446 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
447 vty_out(vty
, " Refcount: %d\n", listcount(n
->host_list
));
448 vty_out(vty
, " Prefixes:\n");
449 for (ALL_LIST_ELEMENTS_RO(n
->host_list
, node
, p
))
450 vty_out(vty
, " %s\n",
451 prefix2str(p
, buf2
, sizeof(buf2
)));
453 json_hosts
= json_object_new_array();
454 json_object_string_add(
455 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
456 json_object_string_add(
458 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
459 json_object_int_add(json
, "refCount", listcount(n
->host_list
));
460 for (ALL_LIST_ELEMENTS_RO(n
->host_list
, node
, p
))
461 json_object_array_add(json_hosts
,
462 json_object_new_string(prefix2str(
463 p
, buf2
, sizeof(buf2
))));
464 json_object_object_add(json
, "prefixList", json_hosts
);
468 /* Print a specific RMAC entry */
469 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
472 char buf1
[ETHER_ADDR_STRLEN
];
473 char buf2
[PREFIX_STRLEN
];
474 struct listnode
*node
= NULL
;
475 struct prefix
*p
= NULL
;
476 json_object
*json_hosts
= NULL
;
479 vty_out(vty
, "MAC: %s\n",
480 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
481 vty_out(vty
, " Remote VTEP: %s\n",
482 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
483 vty_out(vty
, " Refcount: %d\n", listcount(zrmac
->host_list
));
484 vty_out(vty
, " Prefixes:\n");
485 for (ALL_LIST_ELEMENTS_RO(zrmac
->host_list
, node
, p
))
486 vty_out(vty
, " %s\n",
487 prefix2str(p
, buf2
, sizeof(buf2
)));
489 json_hosts
= json_object_new_array();
490 json_object_string_add(
492 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
493 json_object_string_add(json
, "vtepIp",
494 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
495 json_object_int_add(json
, "refCount",
496 listcount(zrmac
->host_list
));
497 for (ALL_LIST_ELEMENTS_RO(zrmac
->host_list
, node
, p
))
498 json_object_array_add(json_hosts
,
499 json_object_new_string(prefix2str(
500 p
, buf2
, sizeof(buf2
))));
501 json_object_object_add(json
, "prefixList", json_hosts
);
506 * Print a specific MAC entry.
508 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
)
511 zebra_neigh_t
*n
= NULL
;
512 struct listnode
*node
= NULL
;
514 char buf2
[INET6_ADDRSTRLEN
];
516 vty
= (struct vty
*)ctxt
;
517 vty_out(vty
, "MAC: %s",
518 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
)));
519 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
520 struct zebra_ns
*zns
;
521 struct interface
*ifp
;
524 ifindex
= mac
->fwd_info
.local
.ifindex
;
525 zns
= zebra_ns_lookup(NS_DEFAULT
);
526 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
527 if (!ifp
) // unexpected
529 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
530 if (mac
->fwd_info
.local
.vid
)
531 vty_out(vty
, " VLAN: %u", mac
->fwd_info
.local
.vid
);
532 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
533 vty_out(vty
, " Remote VTEP: %s",
534 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
535 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
536 vty_out(vty
, " Auto Mac ");
539 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
540 vty_out(vty
, " Sticky Mac ");
542 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
543 vty_out(vty
, " Default-gateway Mac ");
546 /* print all the associated neigh */
547 vty_out(vty
, " Neighbors:\n");
548 if (!listcount(mac
->neigh_list
))
549 vty_out(vty
, " No Neighbors\n");
551 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
552 vty_out(vty
, " %s %s\n",
553 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
554 CHECK_FLAG(n
->flags
, ZEBRA_MAC_LOCAL
)
555 ? (IS_ZEBRA_NEIGH_ACTIVE(n
)
566 * Print MAC hash entry - called for display of all MACs.
568 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
571 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
574 struct mac_walk_ctx
*wctx
= ctxt
;
577 json_mac_hdr
= wctx
->json
;
578 mac
= (zebra_mac_t
*)backet
->data
;
582 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
585 json_mac
= json_object_new_object();
587 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
588 && !(wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)) {
589 struct zebra_ns
*zns
;
591 struct interface
*ifp
;
594 zns
= zebra_ns_lookup(NS_DEFAULT
);
595 ifindex
= mac
->fwd_info
.local
.ifindex
;
596 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
597 if (!ifp
) // unexpected
599 vid
= mac
->fwd_info
.local
.vid
;
600 if (json_mac_hdr
== NULL
)
601 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
604 json_object_string_add(json_mac
, "type", "local");
605 json_object_string_add(json_mac
, "intf", ifp
->name
);
608 if (json_mac_hdr
== NULL
)
609 vty_out(vty
, " %-5u", vid
);
611 json_object_int_add(json_mac
, "vlan", vid
);
613 if (json_mac_hdr
== NULL
)
616 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
618 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
619 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) {
620 if (IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
622 if (wctx
->count
== 0) {
623 if (json_mac_hdr
== NULL
) {
624 vty_out(vty
, "\nVNI %u\n\n",
627 "%-17s %-6s %-21s %-5s\n",
633 if (json_mac_hdr
== NULL
)
634 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
636 inet_ntoa(mac
->fwd_info
639 json_object_string_add(json_mac
, "type",
641 json_object_string_add(
642 json_mac
, "remoteVtep",
643 inet_ntoa(mac
->fwd_info
645 json_object_object_add(json_mac_hdr
,
651 if (json_mac_hdr
== NULL
)
652 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
654 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
656 json_object_string_add(json_mac
, "type",
658 json_object_string_add(
659 json_mac
, "remoteVtep",
660 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
661 json_object_object_add(json_mac_hdr
, buf1
,
670 * Print MACs for all VNI.
672 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
675 json_object
*json
= NULL
, *json_vni
= NULL
;
676 json_object
*json_mac
= NULL
;
679 struct mac_walk_ctx
*wctx
= ctxt
;
680 char vni_str
[VNI_STR_LEN
];
682 vty
= (struct vty
*)wctx
->vty
;
683 json
= (struct json_object
*)wctx
->json
;
685 zvni
= (zebra_vni_t
*)backet
->data
;
688 vty_out(vty
, "{}\n");
693 /*We are iterating over a new VNI, set the count to 0*/
696 num_macs
= num_valid_macs(zvni
);
701 json_vni
= json_object_new_object();
702 json_mac
= json_object_new_object();
703 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
706 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
708 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
709 zvni
->vni
, num_macs
);
710 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
711 "Intf/Remote VTEP", "VLAN");
713 json_object_int_add(json_vni
, "numMacs", num_macs
);
715 /* assign per-vni to wctx->json object to fill macs
716 * under the vni. Re-assign primary json object to fill
717 * next vni information.
719 wctx
->json
= json_mac
;
720 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
724 json_object_object_add(json_vni
, "macs", json_mac
);
725 json_object_object_add(json
, vni_str
, json_vni
);
729 static void zl3vni_print_nh_hash(struct hash_backet
*backet
, void *ctx
)
731 struct nh_walk_ctx
*wctx
= NULL
;
732 struct vty
*vty
= NULL
;
733 struct json_object
*json_vni
= NULL
;
734 struct json_object
*json_nh
= NULL
;
735 zebra_neigh_t
*n
= NULL
;
736 char buf1
[ETHER_ADDR_STRLEN
];
737 char buf2
[INET6_ADDRSTRLEN
];
739 wctx
= (struct nh_walk_ctx
*)ctx
;
741 json_vni
= wctx
->json
;
743 json_nh
= json_object_new_object();
744 n
= (zebra_neigh_t
*)backet
->data
;
749 vty_out(vty
, "%-15s %-17s\n",
750 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
751 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
753 json_object_string_add(json_nh
, "nexthopIp",
754 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
755 json_object_string_add(
756 json_nh
, "routerMac",
757 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
758 json_object_object_add(json_vni
,
759 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
764 static void zl3vni_print_nh_hash_all_vni(struct hash_backet
*backet
,
767 struct vty
*vty
= NULL
;
768 json_object
*json
= NULL
;
769 json_object
*json_vni
= NULL
;
770 zebra_l3vni_t
*zl3vni
= NULL
;
772 struct nh_walk_ctx wctx
;
773 char vni_str
[VNI_STR_LEN
];
775 vty
= (struct vty
*)args
[0];
776 json
= (struct json_object
*)args
[1];
778 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
781 vty_out(vty
, "{}\n");
785 num_nh
= hashcount(zl3vni
->nh_table
);
790 json_vni
= json_object_new_object();
791 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
795 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
796 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
798 json_object_int_add(json_vni
, "numNextHops", num_nh
);
800 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
802 wctx
.json
= json_vni
;
803 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
805 json_object_object_add(json
, vni_str
, json_vni
);
808 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet
*backet
,
811 struct vty
*vty
= NULL
;
812 json_object
*json
= NULL
;
813 json_object
*json_vni
= NULL
;
814 zebra_l3vni_t
*zl3vni
= NULL
;
816 struct rmac_walk_ctx wctx
;
817 char vni_str
[VNI_STR_LEN
];
819 vty
= (struct vty
*)args
[0];
820 json
= (struct json_object
*)args
[1];
822 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
825 vty_out(vty
, "{}\n");
829 num_rmacs
= hashcount(zl3vni
->rmac_table
);
834 json_vni
= json_object_new_object();
835 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
839 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
840 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
842 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
844 /* assign per-vni to wctx->json object to fill macs
845 * under the vni. Re-assign primary json object to fill
846 * next vni information.
848 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
850 wctx
.json
= json_vni
;
851 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
853 json_object_object_add(json
, vni_str
, json_vni
);
856 static void zl3vni_print_rmac_hash(struct hash_backet
*backet
, void *ctx
)
858 zebra_mac_t
*zrmac
= NULL
;
859 struct rmac_walk_ctx
*wctx
= NULL
;
860 struct vty
*vty
= NULL
;
861 struct json_object
*json
= NULL
;
862 struct json_object
*json_rmac
= NULL
;
863 char buf
[ETHER_ADDR_STRLEN
];
865 wctx
= (struct rmac_walk_ctx
*)ctx
;
869 json_rmac
= json_object_new_object();
870 zrmac
= (zebra_mac_t
*)backet
->data
;
875 vty_out(vty
, "%-17s %-21s\n",
876 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
877 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
879 json_object_string_add(
880 json_rmac
, "routerMac",
881 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
882 json_object_string_add(json_rmac
, "vtepIp",
883 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
884 json_object_object_add(
885 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
890 /* print a specific L3 VNI entry */
891 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
893 char buf
[ETHER_ADDR_STRLEN
];
894 struct vty
*vty
= NULL
;
895 json_object
*json
= NULL
;
896 zebra_vni_t
*zvni
= NULL
;
897 json_object
*json_vni_list
= NULL
;
898 struct listnode
*node
= NULL
, *nnode
= NULL
;
904 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
905 vty_out(vty
, " Type: %s\n", "L3");
906 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
907 vty_out(vty
, " Local Vtep Ip: %s\n",
908 inet_ntoa(zl3vni
->local_vtep_ip
));
909 vty_out(vty
, " Vxlan-Intf: %s\n",
910 zl3vni_vxlan_if_name(zl3vni
));
911 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
912 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
913 vty_out(vty
, " VNI Filter: %s\n",
914 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
915 ? "prefix-routes-only"
917 vty_out(vty
, " Router MAC: %s\n",
918 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
919 vty_out(vty
, " L2 VNIs: ");
920 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
921 vty_out(vty
, "%u ", zvni
->vni
);
924 json_vni_list
= json_object_new_array();
925 json_object_int_add(json
, "vni", zl3vni
->vni
);
926 json_object_string_add(json
, "type", "L3");
927 json_object_string_add(json
, "localVtepIp",
928 inet_ntoa(zl3vni
->local_vtep_ip
));
929 json_object_string_add(json
, "vxlanIntf",
930 zl3vni_vxlan_if_name(zl3vni
));
931 json_object_string_add(json
, "sviIntf",
932 zl3vni_svi_if_name(zl3vni
));
933 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
934 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
935 json_object_string_add(
937 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
938 json_object_string_add(
940 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
941 ? "prefix-routes-only"
943 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
944 json_object_array_add(json_vni_list
,
945 json_object_new_int(zvni
->vni
));
947 json_object_object_add(json
, "l2Vnis", json_vni_list
);
952 * Print a specific VNI entry.
954 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
960 json_object
*json
= NULL
;
961 json_object
*json_vtep_list
= NULL
;
962 json_object
*json_ip_str
= NULL
;
968 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
969 vty_out(vty
, " Type: %s\n", "L2");
970 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
972 json_object_int_add(json
, "vni", zvni
->vni
);
973 json_object_string_add(json
, "type", "L2");
974 json_object_string_add(json
, "vrf",
975 vrf_id_to_name(zvni
->vrf_id
));
978 if (!zvni
->vxlan_if
) { // unexpected
980 vty_out(vty
, " VxLAN interface: unknown\n");
983 num_macs
= num_valid_macs(zvni
);
984 num_neigh
= hashcount(zvni
->neigh_table
);
986 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
987 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
988 vty_out(vty
, " Local VTEP IP: %s\n",
989 inet_ntoa(zvni
->local_vtep_ip
));
991 json_object_string_add(json
, "vxlanInterface",
992 zvni
->vxlan_if
->name
);
993 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
994 json_object_string_add(json
, "vtepIp",
995 inet_ntoa(zvni
->local_vtep_ip
));
996 json_object_string_add(json
, "advertiseGatewayMacip",
997 zvni
->advertise_gw_macip
? "Yes" : "No");
998 json_object_int_add(json
, "numMacs", num_macs
);
999 json_object_int_add(json
, "numArpNd", num_neigh
);
1003 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1006 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1008 json_vtep_list
= json_object_new_array();
1009 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1011 vty_out(vty
, " %s\n",
1012 inet_ntoa(zvtep
->vtep_ip
));
1014 json_ip_str
= json_object_new_string(
1015 inet_ntoa(zvtep
->vtep_ip
));
1016 json_object_array_add(json_vtep_list
,
1021 json_object_object_add(json
, "numRemoteVteps",
1026 " Number of MACs (local and remote) known for this VNI: %u\n",
1029 " Number of ARPs (IPv4 and IPv6, local and remote) "
1030 "known for this VNI: %u\n",
1032 vty_out(vty
, " Advertise-gw-macip: %s\n",
1033 zvni
->advertise_gw_macip
? "Yes" : "No");
1037 /* print a L3 VNI hash entry */
1038 static void zl3vni_print_hash(struct hash_backet
*backet
, void *ctx
[])
1040 struct vty
*vty
= NULL
;
1041 json_object
*json
= NULL
;
1042 json_object
*json_vni
= NULL
;
1043 zebra_l3vni_t
*zl3vni
= NULL
;
1045 vty
= (struct vty
*)ctx
[0];
1046 json
= (json_object
*)ctx
[1];
1048 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1053 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1054 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1055 hashcount(zl3vni
->rmac_table
),
1056 hashcount(zl3vni
->nh_table
), "n/a",
1057 zl3vni_vrf_name(zl3vni
));
1059 char vni_str
[VNI_STR_LEN
];
1061 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1062 json_vni
= json_object_new_object();
1063 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1064 json_object_string_add(json_vni
, "vxlanIf",
1065 zl3vni_vxlan_if_name(zl3vni
));
1066 json_object_int_add(json_vni
, "numMacs",
1067 hashcount(zl3vni
->rmac_table
));
1068 json_object_int_add(json_vni
, "numArpNd",
1069 hashcount(zl3vni
->nh_table
));
1070 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1071 json_object_string_add(json_vni
, "type", "L3");
1072 json_object_string_add(json_vni
, "tenantVrf",
1073 zl3vni_vrf_name(zl3vni
));
1074 json_object_object_add(json
, vni_str
, json_vni
);
1079 * Print a VNI hash entry - called for display of all VNIs.
1081 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1085 zebra_vtep_t
*zvtep
;
1086 uint32_t num_vteps
= 0;
1087 uint32_t num_macs
= 0;
1088 uint32_t num_neigh
= 0;
1089 json_object
*json
= NULL
;
1090 json_object
*json_vni
= NULL
;
1091 json_object
*json_ip_str
= NULL
;
1092 json_object
*json_vtep_list
= NULL
;
1097 zvni
= (zebra_vni_t
*)backet
->data
;
1101 zvtep
= zvni
->vteps
;
1104 zvtep
= zvtep
->next
;
1107 num_macs
= num_valid_macs(zvni
);
1108 num_neigh
= hashcount(zvni
->neigh_table
);
1110 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1112 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1113 num_macs
, num_neigh
, num_vteps
,
1114 vrf_id_to_name(zvni
->vrf_id
));
1116 char vni_str
[VNI_STR_LEN
];
1117 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1118 json_vni
= json_object_new_object();
1119 json_object_int_add(json_vni
, "vni", zvni
->vni
);
1120 json_object_string_add(json_vni
, "type", "L2");
1121 json_object_string_add(json_vni
, "vxlanIf",
1122 zvni
->vxlan_if
? zvni
->vxlan_if
->name
1124 json_object_int_add(json_vni
, "numMacs", num_macs
);
1125 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1126 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
1127 json_object_string_add(json_vni
, "tenantVrf",
1128 vrf_id_to_name(zvni
->vrf_id
));
1130 json_vtep_list
= json_object_new_array();
1131 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1132 json_ip_str
= json_object_new_string(
1133 inet_ntoa(zvtep
->vtep_ip
));
1134 json_object_array_add(json_vtep_list
,
1137 json_object_object_add(json_vni
, "remoteVteps",
1140 json_object_object_add(json
, vni_str
, json_vni
);
1145 * Inform BGP about local MACIP.
1147 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
1148 struct ipaddr
*ip
, uint8_t flags
,
1151 char buf
[ETHER_ADDR_STRLEN
];
1152 char buf2
[INET6_ADDRSTRLEN
];
1154 struct zserv
*client
= NULL
;
1155 struct stream
*s
= NULL
;
1157 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
1158 /* BGP may not be running. */
1162 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
1164 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
1165 stream_putl(s
, vni
);
1166 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
1169 if (IS_IPADDR_V4(ip
))
1170 ipa_len
= IPV4_MAX_BYTELEN
;
1171 else if (IS_IPADDR_V6(ip
))
1172 ipa_len
= IPV6_MAX_BYTELEN
;
1174 stream_putl(s
, ipa_len
); /* IP address length */
1176 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
1178 stream_putl(s
, 0); /* Just MAC. */
1180 stream_putc(s
, flags
); /* sticky mac/gateway mac */
1183 /* Write packet size. */
1184 stream_putw_at(s
, 0, stream_get_endp(s
));
1186 if (IS_ZEBRA_DEBUG_VXLAN
)
1188 "Send MACIP %s flags 0x%x MAC %s IP %s L2-VNI %u to %s",
1189 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
1190 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1191 ipaddr2str(ip
, buf2
, sizeof(buf2
)), vni
,
1192 zebra_route_string(client
->proto
));
1194 if (cmd
== ZEBRA_MACIP_ADD
)
1195 client
->macipadd_cnt
++;
1197 client
->macipdel_cnt
++;
1199 return zebra_server_send_message(client
, s
);
1203 * Make hash key for neighbors.
1205 static unsigned int neigh_hash_keymake(void *p
)
1207 zebra_neigh_t
*n
= p
;
1208 struct ipaddr
*ip
= &n
->ip
;
1210 if (IS_IPADDR_V4(ip
))
1211 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
1213 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
1214 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
1218 * Compare two neighbor hash structures.
1220 static int neigh_cmp(const void *p1
, const void *p2
)
1222 const zebra_neigh_t
*n1
= p1
;
1223 const zebra_neigh_t
*n2
= p2
;
1225 if (n1
== NULL
&& n2
== NULL
)
1228 if (n1
== NULL
|| n2
== NULL
)
1231 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
1235 * Callback to allocate neighbor hash entry.
1237 static void *zvni_neigh_alloc(void *p
)
1239 const zebra_neigh_t
*tmp_n
= p
;
1242 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
1249 * Add neighbor entry.
1251 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
1252 struct ethaddr
*mac
)
1254 zebra_neigh_t tmp_n
;
1255 zebra_neigh_t
*n
= NULL
;
1256 zebra_mac_t
*zmac
= NULL
;
1258 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
1259 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1260 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
1263 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1264 n
->state
= ZEBRA_NEIGH_INACTIVE
;
1266 /* Associate the neigh to mac */
1267 zmac
= zvni_mac_lookup(zvni
, mac
);
1269 listnode_add_sort(zmac
->neigh_list
, n
);
1275 * Delete neighbor entry.
1277 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1279 zebra_neigh_t
*tmp_n
;
1280 zebra_mac_t
*zmac
= NULL
;
1282 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
1284 listnode_delete(zmac
->neigh_list
, n
);
1286 /* Free the VNI hash entry and allocated memory. */
1287 tmp_n
= hash_release(zvni
->neigh_table
, n
);
1289 XFREE(MTYPE_NEIGH
, tmp_n
);
1295 * Free neighbor hash entry (callback)
1297 static int zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
1299 struct neigh_walk_ctx
*wctx
= arg
;
1300 zebra_neigh_t
*n
= backet
->data
;
1302 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1303 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
1304 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
1305 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
1306 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
1307 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
1308 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1309 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
1312 if (wctx
->uninstall
)
1313 zvni_neigh_uninstall(wctx
->zvni
, n
);
1315 return zvni_neigh_del(wctx
->zvni
, n
);
1322 * Delete all neighbor entries from specific VTEP for a particular VNI.
1324 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
1325 struct in_addr
*r_vtep_ip
)
1327 struct neigh_walk_ctx wctx
;
1329 if (!zvni
->neigh_table
)
1332 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1334 wctx
.uninstall
= uninstall
;
1335 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
1336 wctx
.r_vtep_ip
= *r_vtep_ip
;
1338 hash_iterate(zvni
->neigh_table
,
1339 (void (*)(struct hash_backet
*,
1340 void *))zvni_neigh_del_hash_entry
,
1345 * Delete all neighbor entries for this VNI.
1347 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
1350 struct neigh_walk_ctx wctx
;
1352 if (!zvni
->neigh_table
)
1355 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1357 wctx
.uninstall
= uninstall
;
1358 wctx
.upd_client
= upd_client
;
1361 hash_iterate(zvni
->neigh_table
,
1362 (void (*)(struct hash_backet
*,
1363 void *))zvni_neigh_del_hash_entry
,
1368 * Look up neighbor hash entry.
1370 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
1375 memset(&tmp
, 0, sizeof(tmp
));
1376 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
1377 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
1382 /* Process all neigh associated to a mac upon local mac add event */
1383 static void zvni_process_neigh_on_local_mac_add(zebra_vni_t
*zvni
,
1386 zebra_neigh_t
*n
= NULL
;
1387 struct listnode
*node
= NULL
;
1388 char buf
[ETHER_ADDR_STRLEN
];
1389 char buf2
[INET6_ADDRSTRLEN
];
1391 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1392 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1393 /* MAC is learnt locally, program all inactive neigh
1394 * pointing to this mac */
1395 if (IS_ZEBRA_NEIGH_INACTIVE(n
)) {
1396 if (IS_ZEBRA_DEBUG_VXLAN
)
1398 "neigh %s (MAC %s) on L2-VNI %u is now ACTIVE",
1399 ipaddr2str(&n
->ip
, buf2
,
1401 prefix_mac2str(&n
->emac
, buf
,
1405 ZEBRA_NEIGH_SET_ACTIVE(n
);
1406 zvni_neigh_send_add_to_client(
1407 zvni
->vni
, &n
->ip
, &n
->emac
, n
->flags
);
1409 if (IS_ZEBRA_DEBUG_VXLAN
)
1411 "neigh %s (MAC %s) on VNI %u should NOT be ACTIVE",
1412 ipaddr2str(&n
->ip
, buf2
,
1414 prefix_mac2str(&n
->emac
, buf
,
1418 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1419 /* TODO: assume the neigh has moved too ?? */
1424 /* Process all neigh associated to a mac upon local mac del event */
1425 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
1428 zebra_neigh_t
*n
= NULL
;
1429 struct listnode
*node
= NULL
;
1430 char buf
[ETHER_ADDR_STRLEN
];
1431 char buf2
[INET6_ADDRSTRLEN
];
1433 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1434 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1435 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1436 if (IS_ZEBRA_DEBUG_VXLAN
)
1438 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1439 ipaddr2str(&n
->ip
, buf2
,
1441 prefix_mac2str(&n
->emac
, buf
,
1445 ZEBRA_NEIGH_SET_INACTIVE(n
);
1446 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1449 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1450 if (IS_ZEBRA_DEBUG_VXLAN
)
1452 "local MAC %s getting deleted on VNI %u has remote neigh %s",
1453 prefix_mac2str(&n
->emac
, buf
,
1456 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1461 /* process all neigh associated to a mac entry upon remote mac add */
1462 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
1465 zebra_neigh_t
*n
= NULL
;
1466 struct listnode
*node
= NULL
;
1467 char buf
[ETHER_ADDR_STRLEN
];
1468 char buf2
[INET6_ADDRSTRLEN
];
1470 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1471 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1472 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1473 if (IS_ZEBRA_DEBUG_VXLAN
)
1475 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1476 ipaddr2str(&n
->ip
, buf2
,
1478 prefix_mac2str(&n
->emac
, buf
,
1482 ZEBRA_NEIGH_SET_INACTIVE(n
);
1483 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1490 /* process all neigh associated to mac entry upon remote mac del */
1491 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
1494 zebra_neigh_t
*n
= NULL
;
1495 struct listnode
*node
= NULL
;
1496 char buf
[ETHER_ADDR_STRLEN
];
1497 char buf2
[INET6_ADDRSTRLEN
];
1499 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1500 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1501 if (IS_ZEBRA_DEBUG_VXLAN
)
1503 "remote MAC %s getting deleted on VNI %u has local neigh %s",
1504 prefix_mac2str(&n
->emac
, buf
,
1507 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1513 * Inform BGP about local neighbor addition.
1515 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
1516 struct ethaddr
*macaddr
,
1517 uint8_t neigh_flags
)
1521 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
1522 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
1524 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1529 * Inform BGP about local neighbor deletion.
1531 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
1532 struct ethaddr
*macaddr
, uint8_t flags
)
1534 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1539 * Install remote neighbor into the kernel.
1541 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1543 struct zebra_if
*zif
;
1544 struct zebra_l2info_vxlan
*vxl
;
1545 struct interface
*vlan_if
;
1547 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1550 zif
= zvni
->vxlan_if
->info
;
1553 vxl
= &zif
->l2info
.vxl
;
1555 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1559 return kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
);
1563 * Uninstall remote neighbor from the kernel.
1565 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1567 struct zebra_if
*zif
;
1568 struct zebra_l2info_vxlan
*vxl
;
1569 struct interface
*vlan_if
;
1571 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1574 if (!zvni
->vxlan_if
) {
1575 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
1580 zif
= zvni
->vxlan_if
->info
;
1583 vxl
= &zif
->l2info
.vxl
;
1584 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1588 return kernel_del_neigh(vlan_if
, &n
->ip
);
1592 * Install neighbor hash entry - called upon access VLAN change.
1594 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
1597 struct neigh_walk_ctx
*wctx
= ctxt
;
1599 n
= (zebra_neigh_t
*)backet
->data
;
1603 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
1604 zvni_neigh_install(wctx
->zvni
, n
);
1607 /* Get the VRR interface for SVI if any */
1608 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
1610 struct zebra_vrf
*zvrf
= NULL
;
1611 struct interface
*tmp_if
= NULL
;
1612 struct zebra_if
*zif
= NULL
;
1614 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1617 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
1622 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
1625 if (zif
->link
== ifp
)
1632 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1634 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1635 struct connected
*c
= NULL
;
1636 struct ethaddr macaddr
;
1638 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1640 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1643 memset(&ip
, 0, sizeof(struct ipaddr
));
1644 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1647 if (c
->address
->family
== AF_INET
) {
1648 ip
.ipa_type
= IPADDR_V4
;
1649 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1650 sizeof(struct in_addr
));
1651 } else if (c
->address
->family
== AF_INET6
) {
1652 ip
.ipa_type
= IPADDR_V6
;
1653 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1654 sizeof(struct in6_addr
));
1659 zvni_gw_macip_del(ifp
, zvni
, &ip
);
1665 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1667 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1668 struct connected
*c
= NULL
;
1669 struct ethaddr macaddr
;
1671 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1673 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1676 memset(&ip
, 0, sizeof(struct ipaddr
));
1677 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1680 if (c
->address
->family
== AF_INET
) {
1681 ip
.ipa_type
= IPADDR_V4
;
1682 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1683 sizeof(struct in_addr
));
1684 } else if (c
->address
->family
== AF_INET6
) {
1685 ip
.ipa_type
= IPADDR_V6
;
1686 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1687 sizeof(struct in6_addr
));
1692 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
1698 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
1701 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1702 struct connected
*c
= NULL
;
1703 struct ethaddr macaddr
;
1705 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1707 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1710 memcpy(&p
, c
->address
, sizeof(struct prefix
));
1712 /* skip link local address */
1713 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
1718 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1719 ZEBRA_IP_PREFIX_ROUTE_ADD
);
1721 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1722 ZEBRA_IP_PREFIX_ROUTE_DEL
);
1728 * zvni_gw_macip_add_to_client
1730 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
1731 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
1733 char buf
[ETHER_ADDR_STRLEN
];
1734 char buf2
[INET6_ADDRSTRLEN
];
1735 zebra_neigh_t
*n
= NULL
;
1736 zebra_mac_t
*mac
= NULL
;
1737 struct zebra_if
*zif
= NULL
;
1738 struct zebra_l2info_vxlan
*vxl
= NULL
;
1740 zif
= zvni
->vxlan_if
->info
;
1744 vxl
= &zif
->l2info
.vxl
;
1746 mac
= zvni_mac_lookup(zvni
, macaddr
);
1748 mac
= zvni_mac_add(zvni
, macaddr
);
1750 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
1751 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1752 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
1757 /* Set "local" forwarding info. */
1758 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
1759 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
1760 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
1761 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
1762 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
1763 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
1765 n
= zvni_neigh_lookup(zvni
, ip
);
1767 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
1770 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1771 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
1772 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1773 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
1778 /* Set "local" forwarding info. */
1779 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
1780 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
1781 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
1782 n
->ifindex
= ifp
->ifindex
;
1784 /* Only advertise in BGP if the knob is enabled */
1785 if (!advertise_gw_macip_enabled(zvni
))
1788 if (IS_ZEBRA_DEBUG_VXLAN
)
1790 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP",
1791 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1792 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1793 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1795 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, n
->flags
);
1801 * zvni_gw_macip_del_from_client
1803 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
1806 char buf1
[ETHER_ADDR_STRLEN
];
1807 char buf2
[INET6_ADDRSTRLEN
];
1808 zebra_neigh_t
*n
= NULL
;
1809 zebra_mac_t
*mac
= NULL
;
1811 /* If the neigh entry is not present nothing to do*/
1812 n
= zvni_neigh_lookup(zvni
, ip
);
1816 /* mac entry should be present */
1817 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
1819 zlog_err("MAC %s doesnt exists for neigh %s on VNI %u",
1820 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
1821 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1825 /* If the entry is not local nothing to do*/
1826 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
1829 /* only need to delete the entry from bgp if we sent it before */
1830 if (IS_ZEBRA_DEBUG_VXLAN
)
1832 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
1833 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1834 prefix_mac2str(&(n
->emac
), NULL
, ETHER_ADDR_STRLEN
),
1835 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1837 /* Remove neighbor from BGP. */
1838 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
1839 ZEBRA_MACIP_TYPE_GW
);
1841 /* Delete this neighbor entry. */
1842 zvni_neigh_del(zvni
, n
);
1844 /* see if the mac needs to be deleted as well*/
1846 zvni_deref_ip2mac(zvni
, mac
, 0);
1851 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
1854 zebra_vni_t
*zvni
= NULL
;
1855 struct zebra_if
*zif
= NULL
;
1856 struct zebra_l2info_vxlan zl2_info
;
1857 struct interface
*vlan_if
= NULL
;
1858 struct interface
*vrr_if
= NULL
;
1859 struct interface
*ifp
;
1861 /* Add primary SVI MAC*/
1862 zvni
= (zebra_vni_t
*)backet
->data
;
1866 ifp
= zvni
->vxlan_if
;
1871 /* If down or not mapped to a bridge, we're done. */
1872 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1875 zl2_info
= zif
->l2info
.vxl
;
1878 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1882 /* Del primary MAC-IP */
1883 zvni_del_macip_for_intf(vlan_if
, zvni
);
1885 /* Del VRR MAC-IP - if any*/
1886 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1888 zvni_del_macip_for_intf(vrr_if
, zvni
);
1893 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
1896 zebra_vni_t
*zvni
= NULL
;
1897 struct zebra_if
*zif
= NULL
;
1898 struct zebra_l2info_vxlan zl2_info
;
1899 struct interface
*vlan_if
= NULL
;
1900 struct interface
*vrr_if
= NULL
;
1901 struct interface
*ifp
= NULL
;
1903 zvni
= (zebra_vni_t
*)backet
->data
;
1907 ifp
= zvni
->vxlan_if
;
1912 /* If down or not mapped to a bridge, we're done. */
1913 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1915 zl2_info
= zif
->l2info
.vxl
;
1918 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1922 /* Add primary SVI MAC-IP */
1923 zvni_add_macip_for_intf(vlan_if
, zvni
);
1925 /* Add VRR MAC-IP - if any*/
1926 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1928 zvni_add_macip_for_intf(vrr_if
, zvni
);
1933 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
1934 struct interface
*ifp
,
1936 struct ethaddr
*macaddr
)
1938 char buf
[ETHER_ADDR_STRLEN
];
1939 char buf2
[INET6_ADDRSTRLEN
];
1940 zebra_neigh_t
*n
= NULL
;
1941 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
1943 /* create a dummy MAC if the MAC is not already present */
1944 zmac
= zvni_mac_lookup(zvni
, macaddr
);
1946 if (IS_ZEBRA_DEBUG_VXLAN
)
1948 "AUTO MAC %s created for neigh %s on VNI %u",
1949 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1950 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1952 zmac
= zvni_mac_add(zvni
, macaddr
);
1954 zlog_warn("Failed to add MAC %s VNI %u",
1955 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1960 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
1961 memset(&zmac
->flags
, 0, sizeof(uint32_t));
1962 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
1965 /* If same entry already exists, it might be a change or it might be a
1966 * move from remote to local.
1968 n
= zvni_neigh_lookup(zvni
, ip
);
1970 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1971 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
1973 /* Update any params and return - client doesn't
1974 * care about a purely local change.
1976 n
->ifindex
= ifp
->ifindex
;
1980 /* If the MAC has changed,
1981 * need to issue a delete first
1982 * as this means a different MACIP route.
1983 * Also, need to do some unlinking/relinking.
1985 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1987 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
1989 listnode_delete(old_zmac
->neigh_list
, n
);
1990 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
1993 /* Update the forwarding info. */
1994 n
->ifindex
= ifp
->ifindex
;
1995 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
1997 /* Link to new MAC */
1998 listnode_add_sort(zmac
->neigh_list
, n
);
2001 /* Neighbor has moved from remote to local. */
2003 /* If MAC has changed, do the unlink/link */
2004 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2006 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2008 listnode_delete(old_zmac
->neigh_list
, n
);
2009 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
2012 /* Link to new MAC */
2013 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2014 listnode_add_sort(zmac
->neigh_list
, n
);
2017 /* Mark appropriately */
2018 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2019 n
->r_vtep_ip
.s_addr
= 0;
2020 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2021 n
->ifindex
= ifp
->ifindex
;
2024 /* New neighbor - create */
2025 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2028 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2029 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2030 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2031 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2034 /* Set "local" forwarding info. */
2035 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2036 n
->ifindex
= ifp
->ifindex
;
2039 /* Before we program this in BGP, we need to check if MAC is locally
2042 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
2043 if (IS_ZEBRA_DEBUG_VXLAN
)
2045 "Skipping neigh %s add to client as MAC %s is not local on VNI %u",
2046 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2047 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2054 if (IS_ZEBRA_DEBUG_VXLAN
)
2055 zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u",
2056 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2057 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2059 ZEBRA_NEIGH_SET_ACTIVE(n
);
2061 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, 0);
2064 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
2065 struct interface
*ifp
,
2067 struct ethaddr
*macaddr
,
2070 char buf
[ETHER_ADDR_STRLEN
];
2071 char buf2
[INET6_ADDRSTRLEN
];
2072 zebra_neigh_t
*n
= NULL
;
2073 zebra_mac_t
*zmac
= NULL
;
2075 /* If the neighbor is unknown, there is no further action. */
2076 n
= zvni_neigh_lookup(zvni
, ip
);
2080 /* If a remote entry, see if it needs to be refreshed */
2081 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2082 if (state
& NUD_STALE
)
2083 zvni_neigh_install(zvni
, n
);
2085 /* We got a "remote" neighbor notification for an entry
2086 * we think is local. This can happen in a multihoming
2087 * scenario - but only if the MAC is already "remote".
2088 * Just mark our entry as "remote".
2090 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2091 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2093 "Ignore remote neigh %s (MAC %s) on L2-VNI %u "
2094 "- MAC unknown or local",
2095 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
2096 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2101 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2102 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2103 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
2110 * Make hash key for MAC.
2112 static unsigned int mac_hash_keymake(void *p
)
2114 zebra_mac_t
*pmac
= p
;
2115 const void *pnt
= (void *)pmac
->macaddr
.octet
;
2117 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
2121 * Compare two MAC addresses.
2123 static int mac_cmp(const void *p1
, const void *p2
)
2125 const zebra_mac_t
*pmac1
= p1
;
2126 const zebra_mac_t
*pmac2
= p2
;
2128 if (pmac1
== NULL
&& pmac2
== NULL
)
2131 if (pmac1
== NULL
|| pmac2
== NULL
)
2134 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
2139 * Callback to allocate MAC hash entry.
2141 static void *zvni_mac_alloc(void *p
)
2143 const zebra_mac_t
*tmp_mac
= p
;
2146 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2149 return ((void *)mac
);
2155 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
2157 zebra_mac_t tmp_mac
;
2158 zebra_mac_t
*mac
= NULL
;
2160 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
2161 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
2162 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
2165 mac
->neigh_list
= list_new();
2166 mac
->neigh_list
->cmp
= (int (*)(void *, void *))neigh_cmp
;
2174 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2176 zebra_mac_t
*tmp_mac
;
2178 list_delete_and_null(&mac
->neigh_list
);
2180 /* Free the VNI hash entry and allocated memory. */
2181 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
2183 XFREE(MTYPE_MAC
, tmp_mac
);
2189 * Free MAC hash entry (callback)
2191 static int zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2193 struct mac_walk_ctx
*wctx
= arg
;
2194 zebra_mac_t
*mac
= backet
->data
;
2196 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
2197 || ((wctx
->flags
& DEL_REMOTE_MAC
)
2198 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
2199 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
2200 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
2201 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
2202 &wctx
->r_vtep_ip
))) {
2203 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
2204 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
2205 &mac
->macaddr
, mac
->flags
);
2208 if (wctx
->uninstall
)
2209 zvni_mac_uninstall(wctx
->zvni
, mac
, 0);
2211 return zvni_mac_del(wctx
->zvni
, mac
);
2218 * Delete all MAC entries from specific VTEP for a particular VNI.
2220 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2221 struct in_addr
*r_vtep_ip
)
2223 struct mac_walk_ctx wctx
;
2225 if (!zvni
->mac_table
)
2228 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2230 wctx
.uninstall
= uninstall
;
2231 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
2232 wctx
.r_vtep_ip
= *r_vtep_ip
;
2234 hash_iterate(zvni
->mac_table
, (void (*)(struct hash_backet
*,
2235 void *))zvni_mac_del_hash_entry
,
2240 * Delete all MAC entries for this VNI.
2242 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2245 struct mac_walk_ctx wctx
;
2247 if (!zvni
->mac_table
)
2250 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2252 wctx
.uninstall
= uninstall
;
2253 wctx
.upd_client
= upd_client
;
2256 hash_iterate(zvni
->mac_table
, (void (*)(struct hash_backet
*,
2257 void *))zvni_mac_del_hash_entry
,
2262 * Look up MAC hash entry.
2264 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
2269 memset(&tmp
, 0, sizeof(tmp
));
2270 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
2271 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
2277 * Inform BGP about local MAC addition.
2279 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2284 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2285 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2286 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2287 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2289 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2294 * Inform BGP about local MAC deletion.
2296 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2301 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2302 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2303 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2304 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2306 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2311 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2312 * notifications, to see if they are of interest.
2314 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
2315 struct interface
*br_if
, vlanid_t vid
)
2317 struct zebra_ns
*zns
;
2318 struct route_node
*rn
;
2319 struct interface
*tmp_if
= NULL
;
2320 struct zebra_if
*zif
;
2321 struct zebra_l2info_bridge
*br
;
2322 struct zebra_l2info_vxlan
*vxl
= NULL
;
2323 uint8_t bridge_vlan_aware
;
2327 /* Determine if bridge is VLAN-aware or not */
2330 br
= &zif
->l2info
.br
;
2331 bridge_vlan_aware
= br
->vlan_aware
;
2333 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2334 /* TODO: Optimize with a hash. */
2335 zns
= zebra_ns_lookup(NS_DEFAULT
);
2336 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2337 tmp_if
= (struct interface
*)rn
->info
;
2341 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2343 if (!if_is_operative(tmp_if
))
2345 vxl
= &zif
->l2info
.vxl
;
2347 if (zif
->brslave_info
.br_if
!= br_if
)
2350 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2359 zvni
= zvni_lookup(vxl
->vni
);
2364 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2365 * neighbor notifications, to see if they are of interest.
2367 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
2368 struct interface
*br_if
)
2370 struct zebra_ns
*zns
;
2371 struct route_node
*rn
;
2372 struct interface
*tmp_if
= NULL
;
2373 struct zebra_if
*zif
;
2374 struct zebra_l2info_bridge
*br
;
2375 struct zebra_l2info_vxlan
*vxl
= NULL
;
2376 uint8_t bridge_vlan_aware
;
2384 /* Make sure the linked interface is a bridge. */
2385 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
2388 /* Determine if bridge is VLAN-aware or not */
2391 br
= &zif
->l2info
.br
;
2392 bridge_vlan_aware
= br
->vlan_aware
;
2393 if (bridge_vlan_aware
) {
2394 struct zebra_l2info_vlan
*vl
;
2396 if (!IS_ZEBRA_IF_VLAN(ifp
))
2401 vl
= &zif
->l2info
.vl
;
2405 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2406 /* TODO: Optimize with a hash. */
2407 zns
= zebra_ns_lookup(NS_DEFAULT
);
2408 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2409 tmp_if
= (struct interface
*)rn
->info
;
2413 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2415 if (!if_is_operative(tmp_if
))
2417 vxl
= &zif
->l2info
.vxl
;
2419 if (zif
->brslave_info
.br_if
!= br_if
)
2422 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2431 zvni
= zvni_lookup(vxl
->vni
);
2435 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
2437 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
2438 * linked to the bridge
2439 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
2442 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
2444 struct zebra_ns
*zns
;
2445 struct route_node
*rn
;
2446 struct interface
*tmp_if
= NULL
;
2447 struct zebra_if
*zif
;
2448 struct zebra_l2info_bridge
*br
;
2449 struct zebra_l2info_vlan
*vl
;
2450 uint8_t bridge_vlan_aware
;
2453 /* Defensive check, caller expected to invoke only with valid bridge. */
2457 /* Determine if bridge is VLAN-aware or not */
2460 br
= &zif
->l2info
.br
;
2461 bridge_vlan_aware
= br
->vlan_aware
;
2463 /* Check oper status of the SVI. */
2464 if (!bridge_vlan_aware
)
2465 return if_is_operative(br_if
) ? br_if
: NULL
;
2467 /* Identify corresponding VLAN interface. */
2468 /* TODO: Optimize with a hash. */
2469 zns
= zebra_ns_lookup(NS_DEFAULT
);
2470 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2471 tmp_if
= (struct interface
*)rn
->info
;
2472 /* Check oper status of the SVI. */
2473 if (!tmp_if
|| !if_is_operative(tmp_if
))
2476 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
2477 || zif
->link
!= br_if
)
2479 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
2481 if (vl
->vid
== vid
) {
2487 return found
? tmp_if
: NULL
;
2491 * Install remote MAC into the kernel.
2493 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2495 struct zebra_if
*zif
;
2496 struct zebra_l2info_vxlan
*vxl
;
2499 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2502 zif
= zvni
->vxlan_if
->info
;
2505 vxl
= &zif
->l2info
.vxl
;
2507 sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0;
2509 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
2510 mac
->fwd_info
.r_vtep_ip
, sticky
);
2514 * Uninstall remote MAC from the kernel. In the scenario where the MAC
2515 * moves to remote, we have to uninstall any existing local entry first.
2517 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
)
2519 struct zebra_if
*zif
;
2520 struct zebra_l2info_vxlan
*vxl
;
2521 struct in_addr vtep_ip
= {.s_addr
= 0};
2522 struct zebra_ns
*zns
;
2523 struct interface
*ifp
;
2525 if (!local
&& !(mac
->flags
& ZEBRA_MAC_REMOTE
))
2528 if (!zvni
->vxlan_if
) {
2529 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2534 zif
= zvni
->vxlan_if
->info
;
2537 vxl
= &zif
->l2info
.vxl
;
2540 zns
= zebra_ns_lookup(NS_DEFAULT
);
2541 ifp
= if_lookup_by_index_per_ns(zns
,
2542 mac
->fwd_info
.local
.ifindex
);
2543 if (!ifp
) // unexpected
2546 ifp
= zvni
->vxlan_if
;
2547 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
2550 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
,
2555 * Install MAC hash entry - called upon access VLAN change.
2557 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
2560 struct mac_walk_ctx
*wctx
= ctxt
;
2562 mac
= (zebra_mac_t
*)backet
->data
;
2566 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
2567 zvni_mac_install(wctx
->zvni
, mac
);
2571 * Decrement neighbor refcount of MAC; uninstall and free it if
2574 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
2577 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)
2578 || !list_isempty(mac
->neigh_list
))
2582 zvni_mac_uninstall(zvni
, mac
, 0);
2584 zvni_mac_del(zvni
, mac
);
2588 * Read and populate local MACs and neighbors corresponding to this VNI.
2590 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
2592 struct zebra_ns
*zns
;
2593 struct zebra_if
*zif
;
2594 struct interface
*vlan_if
;
2595 struct zebra_l2info_vxlan
*vxl
;
2596 struct interface
*vrr_if
;
2599 vxl
= &zif
->l2info
.vxl
;
2600 zns
= zebra_ns_lookup(NS_DEFAULT
);
2602 if (IS_ZEBRA_DEBUG_VXLAN
)
2604 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2605 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2606 zif
->brslave_info
.bridge_ifindex
);
2608 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
2609 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2612 /* Add SVI MAC-IP */
2613 zvni_add_macip_for_intf(vlan_if
, zvni
);
2615 /* Add VRR MAC-IP - if any*/
2616 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2618 zvni_add_macip_for_intf(vrr_if
, zvni
);
2620 neigh_read_for_vlan(zns
, vlan_if
);
2625 * Hash function for VNI.
2627 static unsigned int vni_hash_keymake(void *p
)
2629 const zebra_vni_t
*zvni
= p
;
2631 return (jhash_1word(zvni
->vni
, 0));
2635 * Compare 2 VNI hash entries.
2637 static int vni_hash_cmp(const void *p1
, const void *p2
)
2639 const zebra_vni_t
*zvni1
= p1
;
2640 const zebra_vni_t
*zvni2
= p2
;
2642 return (zvni1
->vni
== zvni2
->vni
);
2646 * Callback to allocate VNI hash entry.
2648 static void *zvni_alloc(void *p
)
2650 const zebra_vni_t
*tmp_vni
= p
;
2653 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
2654 zvni
->vni
= tmp_vni
->vni
;
2655 return ((void *)zvni
);
2659 * Look up VNI hash entry.
2661 static zebra_vni_t
*zvni_lookup(vni_t vni
)
2663 struct zebra_vrf
*zvrf
;
2664 zebra_vni_t tmp_vni
;
2665 zebra_vni_t
*zvni
= NULL
;
2667 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2669 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
2671 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
2677 * Add VNI hash entry.
2679 static zebra_vni_t
*zvni_add(vni_t vni
)
2681 struct zebra_vrf
*zvrf
;
2682 zebra_vni_t tmp_zvni
;
2683 zebra_vni_t
*zvni
= NULL
;
2685 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2687 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
2689 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
2692 /* Create hash table for MAC */
2694 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
2696 /* Create hash table for neighbors */
2697 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
2698 "Zebra VNI Neighbor Table");
2704 * Delete VNI hash entry.
2706 static int zvni_del(zebra_vni_t
*zvni
)
2708 struct zebra_vrf
*zvrf
;
2709 zebra_vni_t
*tmp_zvni
;
2711 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2714 zvni
->vxlan_if
= NULL
;
2716 /* Free the neighbor hash table. */
2717 hash_free(zvni
->neigh_table
);
2718 zvni
->neigh_table
= NULL
;
2720 /* Free the MAC hash table. */
2721 hash_free(zvni
->mac_table
);
2722 zvni
->mac_table
= NULL
;
2724 /* Free the VNI hash entry and allocated memory. */
2725 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
2727 XFREE(MTYPE_ZVNI
, tmp_zvni
);
2733 * Inform BGP about local VNI addition.
2735 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
2737 struct zserv
*client
;
2740 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
2741 /* BGP may not be running. */
2745 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2747 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
2748 stream_putl(s
, zvni
->vni
);
2749 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
2750 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
2752 /* Write packet size. */
2753 stream_putw_at(s
, 0, stream_get_endp(s
));
2755 if (IS_ZEBRA_DEBUG_VXLAN
)
2756 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
2757 inet_ntoa(zvni
->local_vtep_ip
),
2758 vrf_id_to_name(zvni
->vrf_id
),
2759 zebra_route_string(client
->proto
));
2761 client
->vniadd_cnt
++;
2762 return zebra_server_send_message(client
, s
);
2766 * Inform BGP about local VNI deletion.
2768 static int zvni_send_del_to_client(vni_t vni
)
2770 struct zserv
*client
;
2773 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
2774 /* BGP may not be running. */
2778 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2781 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
2782 stream_putl(s
, vni
);
2784 /* Write packet size. */
2785 stream_putw_at(s
, 0, stream_get_endp(s
));
2787 if (IS_ZEBRA_DEBUG_VXLAN
)
2788 zlog_debug("Send VNI_DEL %u to %s", vni
,
2789 zebra_route_string(client
->proto
));
2791 client
->vnidel_cnt
++;
2792 return zebra_server_send_message(client
, s
);
2796 * Build the VNI hash table by going over the VxLAN interfaces. This
2797 * is called when EVPN (advertise-all-vni) is enabled.
2799 static void zvni_build_hash_table()
2801 struct zebra_ns
*zns
;
2802 struct route_node
*rn
;
2803 struct interface
*ifp
;
2805 /* Walk VxLAN interfaces and create VNI hash. */
2806 zns
= zebra_ns_lookup(NS_DEFAULT
);
2807 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2809 zebra_vni_t
*zvni
= NULL
;
2810 zebra_l3vni_t
*zl3vni
= NULL
;
2811 struct zebra_if
*zif
;
2812 struct zebra_l2info_vxlan
*vxl
;
2814 ifp
= (struct interface
*)rn
->info
;
2818 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2821 vxl
= &zif
->l2info
.vxl
;
2824 /* L3-VNI and L2-VNI are handled seperately */
2825 zl3vni
= zl3vni_lookup(vni
);
2828 if (IS_ZEBRA_DEBUG_VXLAN
)
2830 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
2831 ifp
->name
, ifp
->ifindex
, vni
);
2833 /* associate with vxlan_if */
2834 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
2835 zl3vni
->vxlan_if
= ifp
;
2838 * we need to associate with SVI.
2839 * we can associate with svi-if only after association
2840 * with vxlan-intf is complete
2842 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
2844 if (is_l3vni_oper_up(zl3vni
))
2845 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
2848 struct interface
*vlan_if
= NULL
;
2850 if (IS_ZEBRA_DEBUG_VXLAN
)
2852 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
2853 ifp
->name
, ifp
->ifindex
, vni
,
2854 inet_ntoa(vxl
->vtep_ip
));
2856 /* VNI hash entry is not expected to exist. */
2857 zvni
= zvni_lookup(vni
);
2860 "VNI hash already present for IF %s(%u) L2-VNI %u",
2861 ifp
->name
, ifp
->ifindex
, vni
);
2865 zvni
= zvni_add(vni
);
2868 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
2869 ifp
->name
, ifp
->ifindex
, vni
);
2873 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
2874 zvni
->vxlan_if
= ifp
;
2875 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
2876 zif
->brslave_info
.br_if
);
2878 zvni
->vrf_id
= vlan_if
->vrf_id
;
2879 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
2881 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
2885 /* Inform BGP if intf is up and mapped to bridge. */
2886 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
2887 zvni_send_add_to_client(zvni
);
2893 * See if remote VTEP matches with prefix.
2895 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
2897 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
2901 * Locate remote VTEP in VNI hash table.
2903 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2905 zebra_vtep_t
*zvtep
;
2910 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2911 if (zvni_vtep_match(vtep_ip
, zvtep
))
2919 * Add remote VTEP to VNI hash table.
2921 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2923 zebra_vtep_t
*zvtep
;
2925 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
2927 zlog_err("Failed to alloc VTEP entry, VNI %u", zvni
->vni
);
2931 zvtep
->vtep_ip
= *vtep_ip
;
2934 zvni
->vteps
->prev
= zvtep
;
2935 zvtep
->next
= zvni
->vteps
;
2936 zvni
->vteps
= zvtep
;
2942 * Remove remote VTEP from VNI hash table.
2944 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
2947 zvtep
->next
->prev
= zvtep
->prev
;
2949 zvtep
->prev
->next
= zvtep
->next
;
2951 zvni
->vteps
= zvtep
->next
;
2953 zvtep
->prev
= zvtep
->next
= NULL
;
2954 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
2960 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
2961 * uninstall from kernel if asked to.
2963 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
2965 zebra_vtep_t
*zvtep
, *zvtep_next
;
2970 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
2971 zvtep_next
= zvtep
->next
;
2973 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
2974 zvni_vtep_del(zvni
, zvtep
);
2981 * Install remote VTEP into the kernel.
2983 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2985 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
2989 * Uninstall remote VTEP from the kernel.
2991 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2993 if (!zvni
->vxlan_if
) {
2994 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2999 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3003 * Cleanup VNI/VTEP and update kernel
3005 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
3007 zebra_vni_t
*zvni
= NULL
;
3008 zebra_l3vni_t
*zl3vni
= NULL
;
3009 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
3011 zvni
= (zebra_vni_t
*)backet
->data
;
3015 /* remove from l3-vni list */
3017 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
3019 listnode_delete(zl3vni
->l2vnis
, zvni
);
3021 /* Free up all neighbors and MACs, if any. */
3022 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
3023 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
3025 /* Free up all remote VTEPs, if any. */
3026 zvni_vtep_del_all(zvni
, 1);
3028 /* Delete the hash entry. */
3033 static void zl3vni_cleanup_all(struct hash_backet
*backet
, void *args
)
3035 zebra_l3vni_t
*zl3vni
= NULL
;
3037 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
3041 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
3044 static int is_host_present_in_host_list(struct list
*list
, struct prefix
*host
)
3046 struct listnode
*node
= NULL
;
3047 struct prefix
*p
= NULL
;
3049 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
)) {
3050 if (prefix_same(p
, host
))
3056 static void host_list_add_host(struct list
*list
, struct prefix
*host
)
3058 struct prefix
*p
= NULL
;
3060 p
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct prefix
));
3061 memcpy(p
, host
, sizeof(struct prefix
));
3063 listnode_add_sort(list
, p
);
3066 static void host_list_delete_host(struct list
*list
, struct prefix
*host
)
3068 struct listnode
*node
= NULL
, *nnode
= NULL
, *node_to_del
= NULL
;
3069 struct prefix
*p
= NULL
;
3071 for (ALL_LIST_ELEMENTS(list
, node
, nnode
, p
)) {
3072 if (prefix_same(p
, host
)) {
3073 XFREE(MTYPE_HOST_PREFIX
, p
);
3079 list_delete_node(list
, node_to_del
);
3083 * Look up MAC hash entry.
3085 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
3086 struct ethaddr
*rmac
)
3091 memset(&tmp
, 0, sizeof(tmp
));
3092 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
3093 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
3099 * Callback to allocate RMAC hash entry.
3101 static void *zl3vni_rmac_alloc(void *p
)
3103 const zebra_mac_t
*tmp_rmac
= p
;
3106 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3109 return ((void *)zrmac
);
3113 * Add RMAC entry to l3-vni
3115 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
3117 zebra_mac_t tmp_rmac
;
3118 zebra_mac_t
*zrmac
= NULL
;
3120 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
3121 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
3122 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
3125 zrmac
->host_list
= list_new();
3126 zrmac
->host_list
->cmp
= (int (*)(void *, void *))prefix_cmp
;
3128 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
3129 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
3137 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3139 zebra_mac_t
*tmp_rmac
;
3141 if (zrmac
->host_list
)
3142 list_delete_and_null(&zrmac
->host_list
);
3143 zrmac
->host_list
= NULL
;
3145 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
3147 XFREE(MTYPE_MAC
, tmp_rmac
);
3153 * Install remote RMAC into the kernel.
3155 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3157 struct zebra_if
*zif
= NULL
;
3158 struct zebra_l2info_vxlan
*vxl
= NULL
;
3160 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3161 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3164 zif
= zl3vni
->vxlan_if
->info
;
3168 vxl
= &zif
->l2info
.vxl
;
3170 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3171 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3175 * Uninstall remote RMAC from the kernel.
3177 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3179 char buf
[ETHER_ADDR_STRLEN
];
3180 struct zebra_if
*zif
= NULL
;
3181 struct zebra_l2info_vxlan
*vxl
= NULL
;
3183 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3184 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3187 if (!zl3vni
->vxlan_if
) {
3189 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
3190 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
3191 zl3vni
->vni
, zl3vni
);
3195 zif
= zl3vni
->vxlan_if
->info
;
3199 vxl
= &zif
->l2info
.vxl
;
3201 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3202 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3205 /* handle rmac add */
3206 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
3207 struct ipaddr
*vtep_ip
,
3208 struct prefix
*host_prefix
)
3210 char buf
[ETHER_ADDR_STRLEN
];
3211 char buf1
[INET6_ADDRSTRLEN
];
3212 zebra_mac_t
*zrmac
= NULL
;
3214 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3217 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
3220 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
3221 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3223 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
3226 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
3227 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
3229 /* install rmac in kernel */
3230 zl3vni_rmac_install(zl3vni
, zrmac
);
3233 if (!is_host_present_in_host_list(zrmac
->host_list
, host_prefix
))
3234 host_list_add_host(zrmac
->host_list
, host_prefix
);
3239 /* handle rmac delete */
3240 static int zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
3241 struct prefix
*host_prefix
)
3243 zebra_mac_t
*zrmac
= NULL
;
3245 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3249 host_list_delete_host(zrmac
->host_list
, host_prefix
);
3250 if (list_isempty(zrmac
->host_list
)) {
3252 /* uninstall from kernel */
3253 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3255 /* del the rmac entry */
3256 zl3vni_rmac_del(zl3vni
, zrmac
);
3262 * Look up nh hash entry on a l3-vni.
3264 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3269 memset(&tmp
, 0, sizeof(tmp
));
3270 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
3271 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
3278 * Callback to allocate NH hash entry on L3-VNI.
3280 static void *zl3vni_nh_alloc(void *p
)
3282 const zebra_neigh_t
*tmp_n
= p
;
3285 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
3292 * Add neighbor entry.
3294 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3295 struct ethaddr
*mac
)
3297 zebra_neigh_t tmp_n
;
3298 zebra_neigh_t
*n
= NULL
;
3300 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
3301 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
3302 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
3305 n
->host_list
= list_new();
3306 n
->host_list
->cmp
= (int (*)(void *, void *))prefix_cmp
;
3308 memcpy(&n
->emac
, mac
, ETH_ALEN
);
3309 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3310 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
3316 * Delete neighbor entry.
3318 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3320 zebra_neigh_t
*tmp_n
;
3323 list_delete_and_null(&n
->host_list
);
3324 n
->host_list
= NULL
;
3326 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
3328 XFREE(MTYPE_NEIGH
, tmp_n
);
3334 * Install remote nh as neigh into the kernel.
3336 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3338 if (!is_l3vni_oper_up(zl3vni
))
3341 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3342 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3345 return kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
);
3349 * Uninstall remote nh from the kernel.
3351 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3353 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3354 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3357 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
3360 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
3363 /* add remote vtep as a neigh entry */
3364 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
3365 struct ethaddr
*rmac
,
3366 struct prefix
*host_prefix
)
3368 char buf
[ETHER_ADDR_STRLEN
];
3369 char buf1
[INET6_ADDRSTRLEN
];
3370 zebra_neigh_t
*nh
= NULL
;
3372 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3374 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
3378 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
3379 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
3380 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3385 /* install the nh neigh in kernel */
3386 zl3vni_nh_install(zl3vni
, nh
);
3389 if (!is_host_present_in_host_list(nh
->host_list
, host_prefix
))
3390 host_list_add_host(nh
->host_list
, host_prefix
);
3395 /* handle nh neigh delete */
3396 static int zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
3397 struct prefix
*host_prefix
)
3399 zebra_neigh_t
*nh
= NULL
;
3401 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3405 host_list_delete_host(nh
->host_list
, host_prefix
);
3406 if (list_isempty(nh
->host_list
)) {
3408 /* uninstall from kernel */
3409 zl3vni_nh_uninstall(zl3vni
, nh
);
3411 /* delete the nh entry */
3412 zl3vni_nh_del(zl3vni
, nh
);
3418 /* handle neigh update from kernel - the only thing of interest is to
3419 * readd stale entries.
3421 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3425 zebra_neigh_t
*n
= NULL
;
3427 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3431 /* all next hop neigh are remote and installed by frr.
3432 * If the kernel has aged this entry, re-install.
3434 if (state
& NUD_STALE
)
3435 zl3vni_nh_install(zl3vni
, n
);
3440 /* handle neigh delete from kernel */
3441 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3443 zebra_neigh_t
*n
= NULL
;
3445 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3449 /* all next hop neigh are remote and installed by frr.
3450 * If we get an age out notification for these neigh entries, we have to
3453 zl3vni_nh_install(zl3vni
, n
);
3459 * Hash function for L3 VNI.
3461 static unsigned int l3vni_hash_keymake(void *p
)
3463 const zebra_l3vni_t
*zl3vni
= p
;
3465 return jhash_1word(zl3vni
->vni
, 0);
3469 * Compare 2 L3 VNI hash entries.
3471 static int l3vni_hash_cmp(const void *p1
, const void *p2
)
3473 const zebra_l3vni_t
*zl3vni1
= p1
;
3474 const zebra_l3vni_t
*zl3vni2
= p2
;
3476 return (zl3vni1
->vni
== zl3vni2
->vni
);
3480 * Callback to allocate L3 VNI hash entry.
3482 static void *zl3vni_alloc(void *p
)
3484 zebra_l3vni_t
*zl3vni
= NULL
;
3485 const zebra_l3vni_t
*tmp_l3vni
= p
;
3487 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
3488 zl3vni
->vni
= tmp_l3vni
->vni
;
3489 return ((void *)zl3vni
);
3493 * Look up L3 VNI hash entry.
3495 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
3497 struct zebra_ns
*zns
;
3498 zebra_l3vni_t tmp_l3vni
;
3499 zebra_l3vni_t
*zl3vni
= NULL
;
3501 zns
= zebra_ns_lookup(NS_DEFAULT
);
3503 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
3504 tmp_l3vni
.vni
= vni
;
3505 zl3vni
= hash_lookup(zns
->l3vni_table
, &tmp_l3vni
);
3511 * Add L3 VNI hash entry.
3513 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
3515 zebra_l3vni_t tmp_zl3vni
;
3516 struct zebra_ns
*zns
= NULL
;
3517 zebra_l3vni_t
*zl3vni
= NULL
;
3519 zns
= zebra_ns_lookup(NS_DEFAULT
);
3522 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
3523 tmp_zl3vni
.vni
= vni
;
3525 zl3vni
= hash_get(zns
->l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
3528 zl3vni
->vrf_id
= vrf_id
;
3529 zl3vni
->svi_if
= NULL
;
3530 zl3vni
->vxlan_if
= NULL
;
3531 zl3vni
->l2vnis
= list_new();
3532 zl3vni
->l2vnis
->cmp
= (int (*)(void *, void *))vni_hash_cmp
;
3534 /* Create hash table for remote RMAC */
3535 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
3536 "Zebra L3-VNI RMAC-Table");
3538 /* Create hash table for neighbors */
3539 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3540 "Zebra L3-VNI next-hop table");
3546 * Delete L3 VNI hash entry.
3548 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
3550 struct zebra_ns
*zns
;
3551 zebra_l3vni_t
*tmp_zl3vni
;
3553 zns
= zebra_ns_lookup(NS_DEFAULT
);
3556 /* free the list of l2vnis */
3557 list_delete_and_null(&zl3vni
->l2vnis
);
3558 zl3vni
->l2vnis
= NULL
;
3560 /* Free the rmac table */
3561 hash_free(zl3vni
->rmac_table
);
3562 zl3vni
->rmac_table
= NULL
;
3564 /* Free the nh table */
3565 hash_free(zl3vni
->nh_table
);
3566 zl3vni
->nh_table
= NULL
;
3568 /* Free the VNI hash entry and allocated memory. */
3569 tmp_zl3vni
= hash_release(zns
->l3vni_table
, zl3vni
);
3571 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
3576 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
3578 struct zebra_ns
*zns
= NULL
;
3579 struct route_node
*rn
= NULL
;
3580 struct interface
*ifp
= NULL
;
3582 /* loop through all vxlan-interface */
3583 zns
= zebra_ns_lookup(NS_DEFAULT
);
3584 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3586 struct zebra_if
*zif
= NULL
;
3587 struct zebra_l2info_vxlan
*vxl
= NULL
;
3589 ifp
= (struct interface
*)rn
->info
;
3594 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3597 vxl
= &zif
->l2info
.vxl
;
3598 if (vxl
->vni
== zl3vni
->vni
) {
3599 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3607 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
3609 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
3610 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
3615 if (!zl3vni
->vxlan_if
)
3618 zif
= zl3vni
->vxlan_if
->info
;
3622 vxl
= &zif
->l2info
.vxl
;
3624 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3627 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
3629 struct zebra_vrf
*zvrf
= NULL
;
3631 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
3635 return zl3vni_lookup(zvrf
->l3vni
);
3639 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3640 * neighbor notifications, to see if they are of interest.
3642 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
3643 struct interface
*br_if
)
3647 uint8_t bridge_vlan_aware
= 0;
3648 zebra_l3vni_t
*zl3vni
= NULL
;
3649 struct zebra_ns
*zns
= NULL
;
3650 struct route_node
*rn
= NULL
;
3651 struct zebra_if
*zif
= NULL
;
3652 struct interface
*tmp_if
= NULL
;
3653 struct zebra_l2info_bridge
*br
= NULL
;
3654 struct zebra_l2info_vxlan
*vxl
= NULL
;
3659 /* Make sure the linked interface is a bridge. */
3660 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3663 /* Determine if bridge is VLAN-aware or not */
3666 br
= &zif
->l2info
.br
;
3667 bridge_vlan_aware
= br
->vlan_aware
;
3668 if (bridge_vlan_aware
) {
3669 struct zebra_l2info_vlan
*vl
;
3671 if (!IS_ZEBRA_IF_VLAN(ifp
))
3676 vl
= &zif
->l2info
.vl
;
3680 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3681 /* TODO: Optimize with a hash. */
3682 zns
= zebra_ns_lookup(NS_DEFAULT
);
3683 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3684 tmp_if
= (struct interface
*)rn
->info
;
3688 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3690 if (!if_is_operative(tmp_if
))
3692 vxl
= &zif
->l2info
.vxl
;
3694 if (zif
->brslave_info
.br_if
!= br_if
)
3697 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3706 zl3vni
= zl3vni_lookup(vxl
->vni
);
3711 * Inform BGP about l3-vni.
3713 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
3715 struct stream
*s
= NULL
;
3716 struct zserv
*client
= NULL
;
3717 struct ethaddr rmac
;
3718 char buf
[ETHER_ADDR_STRLEN
];
3720 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
3721 /* BGP may not be running. */
3726 memset(&rmac
, 0, sizeof(struct ethaddr
));
3727 zl3vni_get_rmac(zl3vni
, &rmac
);
3729 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3731 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
3732 stream_putl(s
, zl3vni
->vni
);
3733 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
3734 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
3735 stream_put(s
, &zl3vni
->filter
, sizeof(int));
3737 /* Write packet size. */
3738 stream_putw_at(s
, 0, stream_get_endp(s
));
3740 if (IS_ZEBRA_DEBUG_VXLAN
)
3742 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
3743 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3744 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
3745 inet_ntoa(zl3vni
->local_vtep_ip
),
3746 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
3747 ? "prefix-routes-only"
3749 zebra_route_string(client
->proto
));
3751 client
->l3vniadd_cnt
++;
3752 return zebra_server_send_message(client
, s
);
3756 * Inform BGP about local l3-VNI deletion.
3758 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
3760 struct stream
*s
= NULL
;
3761 struct zserv
*client
= NULL
;
3763 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
3764 /* BGP may not be running. */
3768 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3770 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
3771 stream_putl(s
, zl3vni
->vni
);
3773 /* Write packet size. */
3774 stream_putw_at(s
, 0, stream_get_endp(s
));
3776 if (IS_ZEBRA_DEBUG_VXLAN
)
3777 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
3778 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3779 zebra_route_string(client
->proto
));
3781 client
->l3vnidel_cnt
++;
3782 return zebra_server_send_message(client
, s
);
3785 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
3790 /* send l3vni add to BGP */
3791 zl3vni_send_add_to_client(zl3vni
);
3794 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
3799 /* send l3-vni del to BGP*/
3800 zl3vni_send_del_to_client(zl3vni
);
3803 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
, void *ctxt
)
3805 zebra_vni_t
*zvni
= (zebra_vni_t
*)backet
->data
;
3806 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
3808 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
3809 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3813 * handle transition of vni from l2 to l3 and vice versa
3815 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
3818 zebra_vni_t
*zvni
= NULL
;
3820 /* There is a possibility that VNI notification was already received
3821 * from kernel and we programmed it as L2-VNI
3822 * In such a case we need to delete this L2-VNI first, so
3823 * that it can be reprogrammed as L3-VNI in the system. It is also
3824 * possible that the vrf-vni mapping is removed from FRR while the vxlan
3825 * interface is still present in kernel. In this case to keep it
3826 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
3829 /* Locate hash entry */
3830 zvni
= zvni_lookup(vni
);
3834 if (IS_ZEBRA_DEBUG_VXLAN
)
3835 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
3837 /* Delete VNI from BGP. */
3838 zvni_send_del_to_client(zvni
->vni
);
3840 /* Free up all neighbors and MAC, if any. */
3841 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
3842 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
3844 /* Free up all remote VTEPs, if any. */
3845 zvni_vtep_del_all(zvni
, 0);
3847 /* Delete the hash entry. */
3848 if (zvni_del(zvni
)) {
3849 zlog_err("Failed to del VNI hash %p, VNI %u", zvni
,
3854 /* TODO_MITESH: This needs to be thought through. We don't have
3855 * enough information at this point to reprogram the vni as
3856 * l2-vni. One way is to store the required info in l3-vni and
3857 * used it solely for this purpose
3864 /* delete and uninstall rmac hash entry */
3865 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
, void *ctx
)
3867 zebra_mac_t
*zrmac
= NULL
;
3868 zebra_l3vni_t
*zl3vni
= NULL
;
3870 zrmac
= (zebra_mac_t
*)backet
->data
;
3871 zl3vni
= (zebra_l3vni_t
*)ctx
;
3872 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3873 zl3vni_rmac_del(zl3vni
, zrmac
);
3876 /* delete and uninstall nh hash entry */
3877 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
, void *ctx
)
3879 zebra_neigh_t
*n
= NULL
;
3880 zebra_l3vni_t
*zl3vni
= NULL
;
3882 n
= (zebra_neigh_t
*)backet
->data
;
3883 zl3vni
= (zebra_l3vni_t
*)ctx
;
3884 zl3vni_nh_uninstall(zl3vni
, n
);
3885 zl3vni_nh_del(zl3vni
, n
);
3888 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
3891 struct zserv
*client
= NULL
;
3892 struct stream
*s
= NULL
;
3893 char buf
[PREFIX_STRLEN
];
3895 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
3896 /* BGP may not be running. */
3900 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3902 zclient_create_header(s
, cmd
, vrf_id
);
3903 stream_put(s
, p
, sizeof(struct prefix
));
3905 /* Write packet size. */
3906 stream_putw_at(s
, 0, stream_get_endp(s
));
3908 if (IS_ZEBRA_DEBUG_VXLAN
)
3909 zlog_debug("Send ip prefix %s %s on vrf %s",
3910 prefix2str(p
, buf
, sizeof(buf
)),
3911 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
3912 vrf_id_to_name(vrf_id
));
3914 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
3915 client
->prefixadd_cnt
++;
3917 client
->prefixdel_cnt
++;
3919 return zebra_server_send_message(client
, s
);
3922 /* re-add remote rmac if needed */
3923 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
3924 struct ethaddr
*rmac
)
3926 char buf
[ETHER_ADDR_STRLEN
];
3927 zebra_mac_t
*zrmac
= NULL
;
3929 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3933 if (IS_ZEBRA_DEBUG_VXLAN
)
3934 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
3935 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
3937 zl3vni_rmac_install(zl3vni
, zrmac
);
3941 /* Public functions */
3943 int is_l3vni_for_prefix_routes_only(vni_t vni
)
3945 zebra_l3vni_t
*zl3vni
= NULL
;
3947 zl3vni
= zl3vni_lookup(vni
);
3951 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
3954 /* handle evpn route in vrf table */
3955 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
3956 struct ipaddr
*vtep_ip
,
3957 struct prefix
*host_prefix
)
3959 zebra_l3vni_t
*zl3vni
= NULL
;
3961 zl3vni
= zl3vni_from_vrf(vrf_id
);
3962 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
3965 /* add the next hop neighbor */
3966 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
3969 zl3vni_remote_rmac_add(zl3vni
, rmac
, vtep_ip
, host_prefix
);
3972 /* handle evpn vrf route delete */
3973 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
3974 struct ipaddr
*vtep_ip
,
3975 struct prefix
*host_prefix
)
3977 zebra_l3vni_t
*zl3vni
= NULL
;
3979 zl3vni
= zl3vni_from_vrf(vrf_id
);
3983 /* delete the next hop entry */
3984 zl3vni_remote_nh_del(zl3vni
, vtep_ip
, host_prefix
);
3986 /* delete the rmac entry */
3987 zl3vni_remote_rmac_del(zl3vni
, rmac
, host_prefix
);
3990 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
3991 struct ethaddr
*rmac
,
3994 zebra_l3vni_t
*zl3vni
= NULL
;
3995 zebra_mac_t
*zrmac
= NULL
;
3996 json_object
*json
= NULL
;
3998 if (!is_evpn_enabled()) {
4000 vty_out(vty
, "{}\n");
4005 json
= json_object_new_object();
4007 zl3vni
= zl3vni_lookup(l3vni
);
4010 vty_out(vty
, "{}\n");
4012 vty_out(vty
, "%% L3-VNI %u doesnt exist\n", l3vni
);
4016 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4019 vty_out(vty
, "{}\n");
4022 "%% Requested RMAC doesnt exist in L3-VNI %u",
4027 zl3vni_print_rmac(zrmac
, vty
, json
);
4030 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4031 json
, JSON_C_TO_STRING_PRETTY
));
4032 json_object_free(json
);
4036 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
,
4039 zebra_l3vni_t
*zl3vni
;
4041 struct rmac_walk_ctx wctx
;
4042 json_object
*json
= NULL
;
4044 if (!is_evpn_enabled())
4047 zl3vni
= zl3vni_lookup(l3vni
);
4050 vty_out(vty
, "{}\n");
4052 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4055 num_rmacs
= hashcount(zl3vni
->rmac_table
);
4060 json
= json_object_new_object();
4062 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
4066 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
4068 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
4070 json_object_int_add(json
, "numRmacs", num_rmacs
);
4072 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
4075 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4076 json
, JSON_C_TO_STRING_PRETTY
));
4077 json_object_free(json
);
4081 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, uint8_t use_json
)
4083 struct zebra_ns
*zns
= NULL
;
4084 json_object
*json
= NULL
;
4087 if (!is_evpn_enabled()) {
4089 vty_out(vty
, "{}\n");
4093 zns
= zebra_ns_lookup(NS_DEFAULT
);
4096 vty_out(vty
, "{}\n");
4101 json
= json_object_new_object();
4105 hash_iterate(zns
->l3vni_table
,
4106 (void (*)(struct hash_backet
*,
4107 void *))zl3vni_print_rmac_hash_all_vni
,
4111 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4112 json
, JSON_C_TO_STRING_PRETTY
));
4113 json_object_free(json
);
4117 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
4118 struct ipaddr
*ip
, uint8_t use_json
)
4120 zebra_l3vni_t
*zl3vni
= NULL
;
4121 zebra_neigh_t
*n
= NULL
;
4122 json_object
*json
= NULL
;
4124 if (!is_evpn_enabled()) {
4126 vty_out(vty
, "{}\n");
4131 json
= json_object_new_object();
4133 zl3vni
= zl3vni_lookup(l3vni
);
4136 vty_out(vty
, "{}\n");
4138 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4142 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4145 vty_out(vty
, "{}\n");
4148 "%% Requested next-hop not present for L3-VNI %u",
4153 zl3vni_print_nh(n
, vty
, json
);
4156 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4157 json
, JSON_C_TO_STRING_PRETTY
));
4158 json_object_free(json
);
4162 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, uint8_t use_json
)
4165 struct nh_walk_ctx wctx
;
4166 json_object
*json
= NULL
;
4167 zebra_l3vni_t
*zl3vni
= NULL
;
4169 if (!is_evpn_enabled())
4172 zl3vni
= zl3vni_lookup(l3vni
);
4175 vty_out(vty
, "{}\n");
4177 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4181 num_nh
= hashcount(zl3vni
->nh_table
);
4186 json
= json_object_new_object();
4191 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
4193 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
4195 json_object_int_add(json
, "numNextHops", num_nh
);
4197 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
4200 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4201 json
, JSON_C_TO_STRING_PRETTY
));
4202 json_object_free(json
);
4206 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, uint8_t use_json
)
4208 struct zebra_ns
*zns
= NULL
;
4209 json_object
*json
= NULL
;
4212 if (!is_evpn_enabled()) {
4214 vty_out(vty
, "{}\n");
4218 zns
= zebra_ns_lookup(NS_DEFAULT
);
4223 json
= json_object_new_object();
4227 hash_iterate(zns
->l3vni_table
,
4228 (void (*)(struct hash_backet
*,
4229 void *))zl3vni_print_nh_hash_all_vni
,
4233 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4234 json
, JSON_C_TO_STRING_PRETTY
));
4235 json_object_free(json
);
4241 * Display L3 VNI information (VTY command handler).
4243 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, uint8_t use_json
)
4246 json_object
*json
= NULL
;
4247 zebra_l3vni_t
*zl3vni
= NULL
;
4249 if (!is_evpn_enabled()) {
4251 vty_out(vty
, "{}\n");
4255 zl3vni
= zl3vni_lookup(vni
);
4258 vty_out(vty
, "{}\n");
4260 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4265 json
= json_object_new_object();
4269 zl3vni_print(zl3vni
, (void *)args
);
4272 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4273 json
, JSON_C_TO_STRING_PRETTY
));
4274 json_object_free(json
);
4278 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4279 json_object
*json_vrfs
)
4281 char buf
[ETHER_ADDR_STRLEN
];
4282 zebra_l3vni_t
*zl3vni
= NULL
;
4284 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4289 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
4290 zvrf_name(zvrf
), zl3vni
->vni
,
4291 zl3vni_vxlan_if_name(zl3vni
),
4292 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
4293 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4295 json_object
*json_vrf
= NULL
;
4296 json_vrf
= json_object_new_object();
4297 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
4298 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
4299 json_object_string_add(json_vrf
, "vxlanIntf",
4300 zl3vni_vxlan_if_name(zl3vni
));
4301 json_object_string_add(json_vrf
, "sviIntf",
4302 zl3vni_svi_if_name(zl3vni
));
4303 json_object_string_add(json_vrf
, "state",
4304 zl3vni_state2str(zl3vni
));
4305 json_object_string_add(
4306 json_vrf
, "routerMac",
4307 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4308 json_object_array_add(json_vrfs
, json_vrf
);
4313 * Display Neighbors for a VNI (VTY command handler).
4315 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4316 vni_t vni
, uint8_t use_json
)
4320 struct neigh_walk_ctx wctx
;
4321 json_object
*json
= NULL
;
4323 if (!is_evpn_enabled())
4325 zvni
= zvni_lookup(vni
);
4328 vty_out(vty
, "{}\n");
4330 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4333 num_neigh
= hashcount(zvni
->neigh_table
);
4338 json
= json_object_new_object();
4340 /* Since we have IPv6 addresses to deal with which can vary widely in
4341 * size, we try to be a bit more elegant in display by first computing
4342 * the maximum width.
4344 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4347 wctx
.addr_width
= 15;
4349 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4353 "Number of ARPs (local and remote) known for this VNI: %u\n",
4355 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
4356 "Type", "MAC", "Remote VTEP");
4358 json_object_int_add(json
, "numArpNd", num_neigh
);
4360 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4362 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4363 json
, JSON_C_TO_STRING_PRETTY
));
4364 json_object_free(json
);
4369 * Display neighbors across all VNIs (VTY command handler).
4371 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4374 json_object
*json
= NULL
;
4377 if (!is_evpn_enabled())
4381 json
= json_object_new_object();
4385 hash_iterate(zvrf
->vni_table
,
4386 (void (*)(struct hash_backet
*,
4387 void *))zvni_print_neigh_hash_all_vni
,
4390 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4391 json
, JSON_C_TO_STRING_PRETTY
));
4392 json_object_free(json
);
4397 * Display specific neighbor for a VNI, if present (VTY command handler).
4399 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
4400 struct zebra_vrf
*zvrf
, vni_t vni
,
4401 struct ipaddr
*ip
, uint8_t use_json
)
4405 json_object
*json
= NULL
;
4407 if (!is_evpn_enabled())
4409 zvni
= zvni_lookup(vni
);
4412 vty_out(vty
, "{}\n");
4414 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4417 n
= zvni_neigh_lookup(zvni
, ip
);
4421 "%% Requested neighbor does not exist in VNI %u\n",
4426 json
= json_object_new_object();
4428 zvni_print_neigh(n
, vty
, json
);
4431 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4432 json
, JSON_C_TO_STRING_PRETTY
));
4433 json_object_free(json
);
4438 * Display neighbors for a VNI from specific VTEP (VTY command handler).
4439 * By definition, these are remote neighbors.
4441 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4442 vni_t vni
, struct in_addr vtep_ip
,
4447 struct neigh_walk_ctx wctx
;
4448 json_object
*json
= NULL
;
4450 if (!is_evpn_enabled())
4452 zvni
= zvni_lookup(vni
);
4455 vty_out(vty
, "{}\n");
4457 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4460 num_neigh
= hashcount(zvni
->neigh_table
);
4464 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4467 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
4468 wctx
.r_vtep_ip
= vtep_ip
;
4470 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4473 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4474 json
, JSON_C_TO_STRING_PRETTY
));
4475 json_object_free(json
);
4480 * Display MACs for a VNI (VTY command handler).
4482 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4483 vni_t vni
, uint8_t use_json
)
4487 struct mac_walk_ctx wctx
;
4488 json_object
*json
= NULL
;
4489 json_object
*json_mac
= NULL
;
4491 if (!is_evpn_enabled())
4493 zvni
= zvni_lookup(vni
);
4496 vty_out(vty
, "{}\n");
4498 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4501 num_macs
= num_valid_macs(zvni
);
4506 json
= json_object_new_object();
4507 json_mac
= json_object_new_object();
4510 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4513 wctx
.json
= json_mac
;
4517 "Number of MACs (local and remote) known for this VNI: %u\n",
4519 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
4520 "Intf/Remote VTEP", "VLAN");
4522 json_object_int_add(json
, "numMacs", num_macs
);
4524 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4527 json_object_object_add(json
, "macs", json_mac
);
4528 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4529 json
, JSON_C_TO_STRING_PRETTY
));
4530 json_object_free(json
);
4535 * Display MACs for all VNIs (VTY command handler).
4537 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4540 struct mac_walk_ctx wctx
;
4541 json_object
*json
= NULL
;
4543 if (!is_evpn_enabled()) {
4545 vty_out(vty
, "{}\n");
4549 json
= json_object_new_object();
4551 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4554 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4557 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4558 json
, JSON_C_TO_STRING_PRETTY
));
4559 json_object_free(json
);
4564 * Display MACs for all VNIs (VTY command handler).
4566 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
4567 struct zebra_vrf
*zvrf
,
4568 struct in_addr vtep_ip
,
4571 struct mac_walk_ctx wctx
;
4572 json_object
*json
= NULL
;
4574 if (!is_evpn_enabled())
4578 json
= json_object_new_object();
4580 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4582 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4583 wctx
.r_vtep_ip
= vtep_ip
;
4585 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4588 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4589 json
, JSON_C_TO_STRING_PRETTY
));
4590 json_object_free(json
);
4595 * Display specific MAC for a VNI, if present (VTY command handler).
4597 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4598 vni_t vni
, struct ethaddr
*macaddr
)
4603 if (!is_evpn_enabled())
4605 zvni
= zvni_lookup(vni
);
4607 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4610 mac
= zvni_mac_lookup(zvni
, macaddr
);
4612 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
4617 zvni_print_mac(mac
, vty
);
4621 * Display MACs for a VNI from specific VTEP (VTY command handler).
4623 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4624 vni_t vni
, struct in_addr vtep_ip
,
4629 struct mac_walk_ctx wctx
;
4630 json_object
*json
= NULL
;
4631 json_object
*json_mac
= NULL
;
4633 if (!is_evpn_enabled())
4635 zvni
= zvni_lookup(vni
);
4638 vty_out(vty
, "{}\n");
4640 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4643 num_macs
= num_valid_macs(zvni
);
4648 json
= json_object_new_object();
4649 json_mac
= json_object_new_object();
4652 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4655 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4656 wctx
.r_vtep_ip
= vtep_ip
;
4657 wctx
.json
= json_mac
;
4658 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4661 json_object_int_add(json
, "numMacs", wctx
.count
);
4663 json_object_object_add(json
, "macs", json_mac
);
4664 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4665 json
, JSON_C_TO_STRING_PRETTY
));
4666 json_object_free(json
);
4672 * Display VNI information (VTY command handler).
4674 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
4677 json_object
*json
= NULL
;
4679 zebra_l3vni_t
*zl3vni
= NULL
;
4680 zebra_vni_t
*zvni
= NULL
;
4682 if (!is_evpn_enabled())
4686 json
= json_object_new_object();
4690 zl3vni
= zl3vni_lookup(vni
);
4692 zl3vni_print(zl3vni
, (void *)args
);
4694 zvni
= zvni_lookup(vni
);
4697 vty_out(vty
, "{}\n");
4699 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4703 zvni_print(zvni
, (void *)args
);
4707 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4708 json
, JSON_C_TO_STRING_PRETTY
));
4709 json_object_free(json
);
4713 /* Display all global details for EVPN */
4714 void zebra_vxlan_print_evpn(struct vty
*vty
, uint8_t uj
)
4719 json_object
*json
= NULL
;
4720 struct zebra_ns
*zns
= NULL
;
4721 struct zebra_vrf
*zvrf
= NULL
;
4723 if (!is_evpn_enabled())
4726 zns
= zebra_ns_lookup(NS_DEFAULT
);
4730 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
4734 num_l3vnis
= hashcount(zns
->l3vni_table
);
4735 num_l2vnis
= hashcount(zvrf
->vni_table
);
4736 num_vnis
= num_l2vnis
+ num_l3vnis
;
4739 json
= json_object_new_object();
4740 json_object_string_add(json
, "advertiseGatewayMacip",
4741 zvrf
->advertise_gw_macip
? "Yes" : "No");
4742 json_object_int_add(json
, "numVnis", num_vnis
);
4743 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4744 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4746 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
4747 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
4748 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
4749 zvrf
->advertise_gw_macip
? "Yes" : "No");
4753 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4754 json
, JSON_C_TO_STRING_PRETTY
));
4755 json_object_free(json
);
4760 * Display VNI hash table (VTY command handler).
4762 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4765 json_object
*json
= NULL
;
4766 struct zebra_ns
*zns
= NULL
;
4769 if (!is_evpn_enabled())
4772 zns
= zebra_ns_lookup(NS_DEFAULT
);
4778 json
= json_object_new_object();
4780 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
4781 "Type", "VxLAN IF", "# MACs", "# ARPs",
4782 "# Remote VTEPs", "Tenant VRF");
4787 /* Display all L2-VNIs */
4788 hash_iterate(zvrf
->vni_table
,
4789 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
4792 /* Display all L3-VNIs */
4793 hash_iterate(zns
->l3vni_table
,
4794 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
4798 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4799 json
, JSON_C_TO_STRING_PRETTY
));
4800 json_object_free(json
);
4805 * Handle neighbor delete notification from the kernel (on a VLAN device
4806 * / L3 interface). This may result in either the neighbor getting deleted
4807 * from our database or being re-added to the kernel (if it is a valid
4810 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
4811 struct interface
*link_if
,
4814 char buf
[INET6_ADDRSTRLEN
];
4815 char buf2
[ETHER_ADDR_STRLEN
];
4816 zebra_neigh_t
*n
= NULL
;
4817 zebra_vni_t
*zvni
= NULL
;
4818 zebra_mac_t
*zmac
= NULL
;
4819 zebra_l3vni_t
*zl3vni
= NULL
;
4821 /* check if this is a remote neigh entry corresponding to remote
4824 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4826 return zl3vni_local_nh_del(zl3vni
, ip
);
4828 /* We are only interested in neighbors on an SVI that resides on top
4829 * of a VxLAN bridge.
4831 zvni
= zvni_from_svi(ifp
, link_if
);
4835 if (!zvni
->vxlan_if
) {
4837 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
4842 if (IS_ZEBRA_DEBUG_VXLAN
)
4843 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
4844 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
4845 ifp
->ifindex
, zvni
->vni
);
4847 /* If entry doesn't exist, nothing to do. */
4848 n
= zvni_neigh_lookup(zvni
, ip
);
4852 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
4854 if (IS_ZEBRA_DEBUG_VXLAN
)
4856 "Trying to del a neigh %s without a mac %s on VNI %u",
4857 ipaddr2str(ip
, buf
, sizeof(buf
)),
4858 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
4864 /* If it is a remote entry, the kernel has aged this out or someone has
4865 * deleted it, it needs to be re-installed as Quagga is the owner.
4867 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
4868 zvni_neigh_install(zvni
, n
);
4872 /* Remove neighbor from BGP. */
4873 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
4874 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0);
4876 /* Delete this neighbor entry. */
4877 zvni_neigh_del(zvni
, n
);
4879 /* see if the AUTO mac needs to be deleted */
4880 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
4881 && !listcount(zmac
->neigh_list
))
4882 zvni_mac_del(zvni
, zmac
);
4888 * Handle neighbor add or update notification from the kernel (on a VLAN
4889 * device / L3 interface). This is typically for a local neighbor but can
4890 * also be for a remote neighbor (e.g., ageout notification). It could
4891 * also be a "move" scenario.
4893 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
4894 struct interface
*link_if
,
4896 struct ethaddr
*macaddr
,
4898 uint8_t ext_learned
)
4900 char buf
[ETHER_ADDR_STRLEN
];
4901 char buf2
[INET6_ADDRSTRLEN
];
4902 zebra_vni_t
*zvni
= NULL
;
4903 zebra_l3vni_t
*zl3vni
= NULL
;
4905 /* check if this is a remote neigh entry corresponding to remote
4908 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4910 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
4912 /* We are only interested in neighbors on an SVI that resides on top
4913 * of a VxLAN bridge.
4915 zvni
= zvni_from_svi(ifp
, link_if
);
4919 if (IS_ZEBRA_DEBUG_VXLAN
)
4921 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u",
4922 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
4923 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
4924 ifp
->ifindex
, state
, ext_learned
? "ext-learned " : "",
4927 /* Is this about a local neighbor or a remote one? */
4929 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
);
4931 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
4936 * Handle message from client to delete a remote MACIP for a VNI.
4938 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
4942 struct ethaddr macaddr
;
4944 struct in_addr vtep_ip
;
4948 unsigned short l
= 0, ipa_len
;
4949 char buf
[ETHER_ADDR_STRLEN
];
4950 char buf1
[INET6_ADDRSTRLEN
];
4951 struct interface
*ifp
= NULL
;
4952 struct zebra_if
*zif
= NULL
;
4954 memset(&macaddr
, 0, sizeof(struct ethaddr
));
4955 memset(&ip
, 0, sizeof(struct ipaddr
));
4956 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
4960 while (l
< hdr
->length
) {
4961 /* Obtain each remote MACIP and process. */
4962 /* Message contains VNI, followed by MAC followed by IP (if any)
4963 * followed by remote VTEP IP.
4967 memset(&ip
, 0, sizeof(ip
));
4968 STREAM_GETL(s
, vni
);
4969 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
4970 STREAM_GETL(s
, ipa_len
);
4972 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
4974 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
4976 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
4977 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
4978 l
+= IPV4_MAX_BYTELEN
;
4980 if (IS_ZEBRA_DEBUG_VXLAN
)
4982 "Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
4983 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
4984 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
4986 zebra_route_string(client
->proto
));
4988 /* Locate VNI hash entry - expected to exist. */
4989 zvni
= zvni_lookup(vni
);
4991 if (IS_ZEBRA_DEBUG_VXLAN
)
4993 "Failed to locate VNI hash upon remote MACIP DEL, "
4998 ifp
= zvni
->vxlan_if
;
5001 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
5007 /* If down or not mapped to a bridge, we're done. */
5008 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5011 /* The remote VTEP specified is normally expected to exist, but
5013 * possible that the peer may delete the VTEP before deleting
5015 * referring to the VTEP, in which case the handler (see
5017 * would have already deleted the MACs.
5019 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5022 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5024 n
= zvni_neigh_lookup(zvni
, &ip
);
5027 zlog_err("Failed to locate MAC %s for neigh %s VNI %u",
5028 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5029 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5033 /* If the remote mac or neighbor doesn't exist there is nothing
5035 * to do. Otherwise, uninstall the entry and then remove it.
5040 /* Ignore the delete if this mac is a gateway mac-ip */
5041 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5042 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5044 "%u: Ignore Del for MAC %s neigh %s on VNI %u as it is configured as a default gateway",
5046 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5047 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5051 /* Uninstall remote neighbor or MAC. */
5053 /* When the MAC changes for an IP, it is possible the
5055 * update the new MAC before trying to delete the "old"
5057 * (as these are two different MACIP routes). Do the
5059 * if the MAC matches.
5061 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5062 && (memcmp(n
->emac
.octet
, macaddr
.octet
, ETH_ALEN
)
5064 zvni_neigh_uninstall(zvni
, n
);
5065 zvni_neigh_del(zvni
, n
);
5066 zvni_deref_ip2mac(zvni
, mac
, 1);
5069 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5070 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5072 if (list_isempty(mac
->neigh_list
)) {
5073 zvni_mac_uninstall(zvni
, mac
, 0);
5074 zvni_mac_del(zvni
, mac
);
5076 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5086 * Handle message from client to add a remote MACIP for a VNI. This
5087 * could be just the add of a MAC address or the add of a neighbor
5090 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
5094 struct ethaddr macaddr
;
5096 struct in_addr vtep_ip
;
5098 zebra_vtep_t
*zvtep
;
5099 zebra_mac_t
*mac
, *old_mac
;
5101 unsigned short l
= 0, ipa_len
;
5102 int update_mac
= 0, update_neigh
= 0;
5103 char buf
[ETHER_ADDR_STRLEN
];
5104 char buf1
[INET6_ADDRSTRLEN
];
5107 struct interface
*ifp
= NULL
;
5108 struct zebra_if
*zif
= NULL
;
5110 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5111 memset(&ip
, 0, sizeof(struct ipaddr
));
5112 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5114 if (!EVPN_ENABLED(zvrf
)) {
5116 "%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
5117 __PRETTY_FUNCTION__
);
5123 while (l
< hdr
->length
) {
5124 /* Obtain each remote MACIP and process. */
5125 /* Message contains VNI, followed by MAC followed by IP (if any)
5126 * followed by remote VTEP IP.
5128 update_mac
= update_neigh
= 0;
5131 memset(&ip
, 0, sizeof(ip
));
5132 STREAM_GETL(s
, vni
);
5133 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5134 STREAM_GETL(s
, ipa_len
);
5136 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5138 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5140 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5141 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5142 l
+= IPV4_MAX_BYTELEN
;
5144 /* Get flags - sticky mac and/or gateway mac */
5145 flags
= stream_getc(s
);
5146 sticky
= CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5149 if (IS_ZEBRA_DEBUG_VXLAN
)
5151 "Recv MACIP Add MAC %s IP %s VNI %u Remote VTEP %s with flags 0x%x from %s",
5152 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5153 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5154 inet_ntoa(vtep_ip
), flags
,
5155 zebra_route_string(client
->proto
));
5157 /* Locate VNI hash entry - expected to exist. */
5158 zvni
= zvni_lookup(vni
);
5161 "Failed to locate VNI hash upon remote MACIP ADD, VNI %u",
5165 ifp
= zvni
->vxlan_if
;
5168 "VNI %u hash %p doesn't have intf upon remote MACIP add",
5174 /* If down or not mapped to a bridge, we're done. */
5175 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5178 /* The remote VTEP specified should normally exist, but it is
5180 * that when peering comes up, peer may advertise MACIP routes
5182 * advertising type-3 routes.
5184 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5186 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5188 "Failed to add remote VTEP, VNI %u zvni %p",
5193 zvni_vtep_install(zvni
, &vtep_ip
);
5196 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5198 /* Ignore the update if the mac is already present
5200 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)
5201 && CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5202 if (IS_ZEBRA_DEBUG_VXLAN
)
5204 "%u:Ignore MAC %s IP %s on VNI %u as MAC is already configured as gateway mac",
5206 prefix_mac2str(&macaddr
, buf
,
5208 ipaddr2str(&ip
, buf1
, sizeof(buf1
)),
5213 /* check if the remote MAC is unknown or has a change.
5214 * If so, that needs to be updated first. Note that client could
5215 * install MAC and MACIP separately or just install the latter.
5217 if (!mac
|| !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5218 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0)
5220 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
))
5225 mac
= zvni_mac_add(zvni
, &macaddr
);
5228 "Failed to add MAC %s VNI %u Remote VTEP %s",
5229 prefix_mac2str(&macaddr
, buf
,
5231 vni
, inet_ntoa(vtep_ip
));
5235 /* Is this MAC created for a MACIP? */
5237 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5240 /* Set "auto" and "remote" forwarding info. */
5241 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5242 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5243 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5244 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5247 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5249 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5251 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5253 /* Install the entry. */
5254 zvni_mac_install(zvni
, mac
);
5257 /* If there is no IP, continue - after clearing AUTO flag of
5260 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5264 /* Check if the remote neighbor itself is unknown or has a
5266 * If so, create or update and then install the entry.
5268 n
= zvni_neigh_lookup(zvni
, &ip
);
5269 if (!n
|| !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5270 || (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
)) != 0)
5271 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
))
5276 n
= zvni_neigh_add(zvni
, &ip
, &macaddr
);
5279 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5280 ipaddr2str(&ip
, buf1
,
5282 prefix_mac2str(&macaddr
, buf
,
5284 vni
, inet_ntoa(vtep_ip
));
5288 } else if (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
))
5290 /* MAC change, update neigh list for old and new
5292 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5294 listnode_delete(old_mac
->neigh_list
, n
);
5295 zvni_deref_ip2mac(zvni
, old_mac
, 1);
5297 listnode_add_sort(mac
->neigh_list
, n
);
5298 memcpy(&n
->emac
, &macaddr
, ETH_ALEN
);
5301 /* Set "remote" forwarding info. */
5302 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5303 /* TODO: Handle MAC change. */
5304 n
->r_vtep_ip
= vtep_ip
;
5305 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5307 /* Install the entry. */
5308 zvni_neigh_install(zvni
, n
);
5317 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5318 * us, this must involve a multihoming scenario. Treat this as implicit delete
5319 * of any prior local MAC.
5321 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
5322 struct interface
*br_if
,
5323 struct ethaddr
*macaddr
, vlanid_t vid
)
5325 struct zebra_if
*zif
;
5326 struct zebra_l2info_vxlan
*vxl
;
5330 char buf
[ETHER_ADDR_STRLEN
];
5334 vxl
= &zif
->l2info
.vxl
;
5337 /* Check if EVPN is enabled. */
5338 if (!is_evpn_enabled())
5341 /* Locate hash entry; it is expected to exist. */
5342 zvni
= zvni_lookup(vni
);
5346 /* If entry doesn't exist, nothing to do. */
5347 mac
= zvni_mac_lookup(zvni
, macaddr
);
5351 /* Is it a local entry? */
5352 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5355 if (IS_ZEBRA_DEBUG_VXLAN
)
5357 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5358 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5361 /* Remove MAC from BGP. */
5362 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5365 * If there are no neigh associated with the mac delete the mac
5366 * else mark it as AUTO for forward reference
5368 if (!listcount(mac
->neigh_list
)) {
5369 zvni_mac_del(zvni
, mac
);
5371 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5372 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5379 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5380 * This can happen because the remote MAC entries are also added as "dynamic",
5381 * so the kernel can ageout the entry.
5383 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
5384 struct interface
*br_if
,
5385 struct ethaddr
*macaddr
, vlanid_t vid
)
5387 struct zebra_if
*zif
= NULL
;
5388 struct zebra_l2info_vxlan
*vxl
= NULL
;
5390 zebra_vni_t
*zvni
= NULL
;
5391 zebra_l3vni_t
*zl3vni
= NULL
;
5392 zebra_mac_t
*mac
= NULL
;
5393 char buf
[ETHER_ADDR_STRLEN
];
5397 vxl
= &zif
->l2info
.vxl
;
5400 /* Check if EVPN is enabled. */
5401 if (!is_evpn_enabled())
5404 /* check if this is a remote RMAC and readd simillar to remote macs */
5405 zl3vni
= zl3vni_lookup(vni
);
5407 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
5409 /* Locate hash entry; it is expected to exist. */
5410 zvni
= zvni_lookup(vni
);
5414 /* If entry doesn't exist, nothing to do. */
5415 mac
= zvni_mac_lookup(zvni
, macaddr
);
5419 /* Is it a remote entry? */
5420 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
5423 if (IS_ZEBRA_DEBUG_VXLAN
)
5424 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
5425 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5428 zvni_mac_install(zvni
, mac
);
5433 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
5435 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
5436 struct ethaddr
*macaddr
, vlanid_t vid
)
5440 char buf
[ETHER_ADDR_STRLEN
];
5442 /* We are interested in MACs only on ports or (port, VLAN) that
5445 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5448 if (!zvni
->vxlan_if
) {
5449 zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL",
5454 if (IS_ZEBRA_DEBUG_VXLAN
)
5455 zlog_debug("Del MAC %s intf %s(%u) VID %u -> VNI %u",
5456 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5457 ifp
->ifindex
, vid
, zvni
->vni
);
5459 /* If entry doesn't exist, nothing to do. */
5460 mac
= zvni_mac_lookup(zvni
, macaddr
);
5464 /* Is it a local entry? */
5465 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5468 /* Remove MAC from BGP. */
5469 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5471 /* Update all the neigh entries associated with this mac */
5472 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
5475 * If there are no neigh associated with the mac delete the mac
5476 * else mark it as AUTO for forward reference
5478 if (!listcount(mac
->neigh_list
)) {
5479 zvni_mac_del(zvni
, mac
);
5481 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5482 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5489 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
5491 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
5492 struct interface
*br_if
,
5493 struct ethaddr
*macaddr
, vlanid_t vid
,
5498 char buf
[ETHER_ADDR_STRLEN
];
5502 /* We are interested in MACs only on ports or (port, VLAN) that
5505 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5507 if (IS_ZEBRA_DEBUG_VXLAN
)
5509 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5510 sticky
? "sticky " : "",
5511 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5512 ifp
->name
, ifp
->ifindex
, vid
);
5516 if (!zvni
->vxlan_if
) {
5517 zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD",
5522 if (IS_ZEBRA_DEBUG_VXLAN
)
5523 zlog_debug("Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
5524 sticky
? "sticky " : "",
5525 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5526 ifp
->ifindex
, vid
, zvni
->vni
);
5528 /* If same entry already exists, nothing to do. */
5529 mac
= zvni_mac_lookup(zvni
, macaddr
);
5531 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5532 mac_sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5538 * return if nothing has changed.
5539 * inform bgp if sticky flag has changed
5540 * update locally and do not inform bgp if local
5541 * parameters like interface has changed
5543 if (mac_sticky
== sticky
5544 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
5545 && mac
->fwd_info
.local
.vid
== vid
) {
5546 if (IS_ZEBRA_DEBUG_VXLAN
)
5548 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
5549 "entry exists and has not changed ",
5550 sticky
? "sticky " : "",
5551 prefix_mac2str(macaddr
, buf
,
5553 ifp
->name
, ifp
->ifindex
, vid
,
5556 } else if (mac_sticky
!= sticky
) {
5559 add
= 0; /* This is an update of local
5562 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5564 * If we have already learned the MAC as a remote sticky
5566 * this is a operator error and we must log a warning
5568 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
5570 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
5571 prefix_mac2str(macaddr
, buf
,
5573 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
5581 mac
= zvni_mac_add(zvni
, macaddr
);
5583 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
5584 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5585 ifp
->name
, ifp
->ifindex
, vid
);
5590 /* Set "local" forwarding info. */
5591 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5592 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5593 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5594 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5595 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
5596 mac
->fwd_info
.local
.vid
= vid
;
5599 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5601 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5603 /* Inform BGP if required. */
5605 zvni_process_neigh_on_local_mac_add(zvni
, mac
);
5606 return zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
5614 * Handle message from client to delete a remote VTEP for a VNI.
5616 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
5619 unsigned short l
= 0;
5621 struct in_addr vtep_ip
;
5623 zebra_vtep_t
*zvtep
;
5624 struct interface
*ifp
;
5625 struct zebra_if
*zif
;
5627 if (!is_evpn_enabled()) {
5629 "%s: EVPN is not enabled yet we have received a vtep del command",
5630 __PRETTY_FUNCTION__
);
5634 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5635 zlog_err("Recv MACIP DEL for non-default VRF %u",
5642 while (l
< hdr
->length
) {
5643 /* Obtain each remote VTEP and process. */
5644 STREAM_GETL(s
, vni
);
5646 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5647 l
+= IPV4_MAX_BYTELEN
;
5649 if (IS_ZEBRA_DEBUG_VXLAN
)
5650 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
5651 inet_ntoa(vtep_ip
), vni
,
5652 zebra_route_string(client
->proto
));
5654 /* Locate VNI hash entry - expected to exist. */
5655 zvni
= zvni_lookup(vni
);
5657 if (IS_ZEBRA_DEBUG_VXLAN
)
5659 "Failed to locate VNI hash upon remote VTEP DEL, "
5665 ifp
= zvni
->vxlan_if
;
5668 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
5674 /* If down or not mapped to a bridge, we're done. */
5675 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5678 /* If the remote VTEP does not exist, there's nothing more to
5680 * Otherwise, uninstall any remote MACs pointing to this VTEP
5682 * then, the VTEP entry itself and remove it.
5684 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5688 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
5689 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
5690 zvni_vtep_uninstall(zvni
, &vtep_ip
);
5691 zvni_vtep_del(zvni
, zvtep
);
5699 * Handle message from client to add a remote VTEP for a VNI.
5701 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
5704 unsigned short l
= 0;
5706 struct in_addr vtep_ip
;
5708 struct interface
*ifp
;
5709 struct zebra_if
*zif
;
5711 if (!is_evpn_enabled()) {
5713 "%s: EVPN not enabled yet we received a vtep_add zapi call",
5714 __PRETTY_FUNCTION__
);
5718 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5719 zlog_err("Recv MACIP ADD for non-default VRF %u",
5726 while (l
< hdr
->length
) {
5727 /* Obtain each remote VTEP and process. */
5728 STREAM_GETL(s
, vni
);
5730 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5731 l
+= IPV4_MAX_BYTELEN
;
5733 if (IS_ZEBRA_DEBUG_VXLAN
)
5734 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
5735 inet_ntoa(vtep_ip
), vni
,
5736 zebra_route_string(client
->proto
));
5738 /* Locate VNI hash entry - expected to exist. */
5739 zvni
= zvni_lookup(vni
);
5742 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
5747 ifp
= zvni
->vxlan_if
;
5750 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
5757 /* If down or not mapped to a bridge, we're done. */
5758 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5761 /* If the remote VTEP already exists,
5762 there's nothing more to do. */
5763 if (zvni_vtep_find(zvni
, &vtep_ip
))
5766 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5767 zlog_err("Failed to add remote VTEP, VNI %u zvni %p",
5772 zvni_vtep_install(zvni
, &vtep_ip
);
5780 * Add/Del gateway macip to evpn
5782 * 1. SVI interface on a vlan aware bridge
5783 * 2. SVI interface on a vlan unaware bridge
5784 * 3. vrr interface (MACVLAN) associated to a SVI
5785 * We advertise macip routes for an interface if it is associated to VxLan vlan
5787 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
5791 struct ethaddr macaddr
;
5792 zebra_vni_t
*zvni
= NULL
;
5794 memset(&ip
, 0, sizeof(struct ipaddr
));
5795 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5797 /* Check if EVPN is enabled. */
5798 if (!is_evpn_enabled())
5801 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
5802 struct interface
*svi_if
=
5803 NULL
; /* SVI corresponding to the MACVLAN */
5804 struct zebra_if
*ifp_zif
=
5805 NULL
; /* Zebra daemon specific info for MACVLAN */
5806 struct zebra_if
*svi_if_zif
=
5807 NULL
; /* Zebra daemon specific info for SVI*/
5809 ifp_zif
= ifp
->info
;
5814 * for a MACVLAN interface the link represents the svi_if
5816 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
5817 ifp_zif
->link_ifindex
);
5819 zlog_err("MACVLAN %s(%u) without link information",
5820 ifp
->name
, ifp
->ifindex
);
5824 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
5826 * If it is a vlan aware bridge then the link gives the
5827 * bridge information
5829 struct interface
*svi_if_link
= NULL
;
5831 svi_if_zif
= svi_if
->info
;
5833 svi_if_link
= if_lookup_by_index_per_ns(
5834 zebra_ns_lookup(NS_DEFAULT
),
5835 svi_if_zif
->link_ifindex
);
5836 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
5838 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
5840 * If it is a vlan unaware bridge then svi is the bridge
5843 zvni
= zvni_from_svi(svi_if
, svi_if
);
5845 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
5846 struct zebra_if
*svi_if_zif
=
5847 NULL
; /* Zebra daemon specific info for SVI */
5848 struct interface
*svi_if_link
=
5849 NULL
; /* link info for the SVI = bridge info */
5851 svi_if_zif
= ifp
->info
;
5853 svi_if_link
= if_lookup_by_index_per_ns(
5854 zebra_ns_lookup(NS_DEFAULT
),
5855 svi_if_zif
->link_ifindex
);
5857 zvni
= zvni_from_svi(ifp
, svi_if_link
);
5859 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
5860 zvni
= zvni_from_svi(ifp
, ifp
);
5866 if (!zvni
->vxlan_if
) {
5867 zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
5873 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
5875 if (p
->family
== AF_INET
) {
5876 ip
.ipa_type
= IPADDR_V4
;
5877 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
5878 sizeof(struct in_addr
));
5879 } else if (p
->family
== AF_INET6
) {
5880 ip
.ipa_type
= IPADDR_V6
;
5881 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
5882 sizeof(struct in6_addr
));
5887 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
5889 zvni_gw_macip_del(ifp
, zvni
, &ip
);
5895 * Handle SVI interface going down.
5896 * SVI can be associated to either L3-VNI or L2-VNI.
5897 * For L2-VNI: At this point, this is a NOP since
5898 * the kernel deletes the neighbor entries on this SVI (if any).
5899 * We only need to update the vrf corresponding to zvni.
5900 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
5903 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
5905 zebra_l3vni_t
*zl3vni
= NULL
;
5907 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5910 /* process l3-vni down */
5911 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
5913 /* remove association with svi-if */
5914 zl3vni
->svi_if
= NULL
;
5916 zebra_vni_t
*zvni
= NULL
;
5918 /* since we dont have svi corresponding to zvni, we associate it
5919 * to default vrf. Note: the corresponding neigh entries on the
5920 * SVI would have already been deleted */
5921 zvni
= zvni_from_svi(ifp
, link_if
);
5923 zvni
->vrf_id
= VRF_DEFAULT
;
5925 /* update the tenant vrf in BGP */
5926 zvni_send_add_to_client(zvni
);
5933 * Handle SVI interface coming up.
5934 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
5936 * For L2-VNI: we need to install any remote neighbors entried (used for
5938 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
5940 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
5942 zebra_vni_t
*zvni
= NULL
;
5943 zebra_l3vni_t
*zl3vni
= NULL
;
5945 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5948 /* associate with svi */
5949 zl3vni
->svi_if
= ifp
;
5951 /* process oper-up */
5952 if (is_l3vni_oper_up(zl3vni
))
5953 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
5956 /* process SVI up for l2-vni */
5957 struct neigh_walk_ctx n_wctx
;
5959 zvni
= zvni_from_svi(ifp
, link_if
);
5963 if (!zvni
->vxlan_if
) {
5964 zlog_err("VNI %u hash %p doesn't have intf upon SVI up",
5969 if (IS_ZEBRA_DEBUG_VXLAN
)
5971 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
5972 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
5973 vrf_id_to_name(ifp
->vrf_id
));
5975 /* update the vrf information for l2-vni and inform bgp */
5976 zvni
->vrf_id
= ifp
->vrf_id
;
5977 zvni_send_add_to_client(zvni
);
5979 /* Install any remote neighbors for this VNI. */
5980 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
5982 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
5990 * Handle VxLAN interface down
5992 int zebra_vxlan_if_down(struct interface
*ifp
)
5995 struct zebra_if
*zif
= NULL
;
5996 struct zebra_l2info_vxlan
*vxl
= NULL
;
5997 zebra_l3vni_t
*zl3vni
= NULL
;
6000 /* Check if EVPN is enabled. */
6001 if (!is_evpn_enabled())
6006 vxl
= &zif
->l2info
.vxl
;
6009 zl3vni
= zl3vni_lookup(vni
);
6011 /* process-if-down for l3-vni */
6012 if (IS_ZEBRA_DEBUG_VXLAN
)
6013 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
6016 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6018 /* process if-down for l2-vni */
6019 if (IS_ZEBRA_DEBUG_VXLAN
)
6020 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
6023 /* Locate hash entry; it is expected to exist. */
6024 zvni
= zvni_lookup(vni
);
6027 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
6028 ifp
->name
, ifp
->ifindex
, vni
);
6032 assert(zvni
->vxlan_if
== ifp
);
6034 /* Delete this VNI from BGP. */
6035 zvni_send_del_to_client(zvni
->vni
);
6037 /* Free up all neighbors and MACs, if any. */
6038 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6039 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6041 /* Free up all remote VTEPs, if any. */
6042 zvni_vtep_del_all(zvni
, 1);
6048 * Handle VxLAN interface up - update BGP if required.
6050 int zebra_vxlan_if_up(struct interface
*ifp
)
6053 struct zebra_if
*zif
= NULL
;
6054 struct zebra_l2info_vxlan
*vxl
= NULL
;
6055 zebra_vni_t
*zvni
= NULL
;
6056 zebra_l3vni_t
*zl3vni
= NULL
;
6058 /* Check if EVPN is enabled. */
6059 if (!is_evpn_enabled())
6064 vxl
= &zif
->l2info
.vxl
;
6067 zl3vni
= zl3vni_lookup(vni
);
6070 if (IS_ZEBRA_DEBUG_VXLAN
)
6071 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
6074 /* we need to associate with SVI, if any, we can associate with
6075 * svi-if only after association with vxlan-intf is complete
6077 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6079 if (is_l3vni_oper_up(zl3vni
))
6080 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6082 /* Handle L2-VNI add */
6083 struct interface
*vlan_if
= NULL
;
6085 if (IS_ZEBRA_DEBUG_VXLAN
)
6086 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
6089 /* Locate hash entry; it is expected to exist. */
6090 zvni
= zvni_lookup(vni
);
6093 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
6094 ifp
->name
, ifp
->ifindex
, vni
);
6098 assert(zvni
->vxlan_if
== ifp
);
6099 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6100 zif
->brslave_info
.br_if
);
6102 zvni
->vrf_id
= vlan_if
->vrf_id
;
6103 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6105 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6108 /* If part of a bridge, inform BGP about this VNI. */
6109 /* Also, read and populate local MACs and neighbors. */
6110 if (zif
->brslave_info
.br_if
) {
6111 zvni_send_add_to_client(zvni
);
6112 zvni_read_mac_neigh(zvni
, ifp
);
6120 * Handle VxLAN interface delete. Locate and remove entry in hash table
6121 * and update BGP, if required.
6123 int zebra_vxlan_if_del(struct interface
*ifp
)
6126 struct zebra_if
*zif
= NULL
;
6127 struct zebra_l2info_vxlan
*vxl
= NULL
;
6128 zebra_vni_t
*zvni
= NULL
;
6129 zebra_l3vni_t
*zl3vni
= NULL
;
6131 /* Check if EVPN is enabled. */
6132 if (!is_evpn_enabled())
6137 vxl
= &zif
->l2info
.vxl
;
6140 zl3vni
= zl3vni_lookup(vni
);
6143 if (IS_ZEBRA_DEBUG_VXLAN
)
6144 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
6147 /* process oper-down for l3-vni */
6148 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6150 /* remove the association with vxlan_if */
6151 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
6152 zl3vni
->vxlan_if
= NULL
;
6155 /* process if-del for l2-vni*/
6156 if (IS_ZEBRA_DEBUG_VXLAN
)
6157 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
6160 /* Locate hash entry; it is expected to exist. */
6161 zvni
= zvni_lookup(vni
);
6164 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6165 ifp
->name
, ifp
->ifindex
, vni
);
6169 /* remove from l3-vni list */
6170 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
6172 listnode_delete(zl3vni
->l2vnis
, zvni
);
6174 /* Delete VNI from BGP. */
6175 zvni_send_del_to_client(zvni
->vni
);
6177 /* Free up all neighbors and MAC, if any. */
6178 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
6179 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
6181 /* Free up all remote VTEPs, if any. */
6182 zvni_vtep_del_all(zvni
, 0);
6184 /* Delete the hash entry. */
6185 if (zvni_del(zvni
)) {
6186 zlog_err("Failed to del VNI hash %p, IF %s(%u) VNI %u",
6187 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
6195 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6197 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
6200 struct zebra_if
*zif
= NULL
;
6201 struct zebra_l2info_vxlan
*vxl
= NULL
;
6202 zebra_vni_t
*zvni
= NULL
;
6203 zebra_l3vni_t
*zl3vni
= NULL
;
6205 /* Check if EVPN is enabled. */
6206 if (!is_evpn_enabled())
6211 vxl
= &zif
->l2info
.vxl
;
6214 zl3vni
= zl3vni_lookup(vni
);
6217 if (IS_ZEBRA_DEBUG_VXLAN
)
6219 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6220 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6221 inet_ntoa(vxl
->vtep_ip
),
6222 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6224 /* Removed from bridge? Cleanup and return */
6225 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6226 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6227 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6231 /* access-vlan change - process oper down, associate with new
6232 * svi_if and then process oper up again
6234 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6235 if (if_is_operative(ifp
)) {
6236 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6237 zl3vni
->svi_if
= NULL
;
6238 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6239 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6240 if (is_l3vni_oper_up(zl3vni
))
6241 zebra_vxlan_process_l3vni_oper_up(
6247 * local-ip change - process oper down, associate with new
6248 * local-ip and then process oper up again
6250 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
6251 if (if_is_operative(ifp
)) {
6252 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6253 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6254 if (is_l3vni_oper_up(zl3vni
))
6255 zebra_vxlan_process_l3vni_oper_up(
6260 /* Update local tunnel IP. */
6261 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6263 /* if we have a valid new master, process l3-vni oper up */
6264 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
6265 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
6266 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6270 /* Update VNI hash. */
6271 zvni
= zvni_lookup(vni
);
6274 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6275 ifp
->name
, ifp
->ifindex
, vni
);
6279 if (IS_ZEBRA_DEBUG_VXLAN
)
6281 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6282 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6283 inet_ntoa(vxl
->vtep_ip
),
6284 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6286 /* Removed from bridge? Cleanup and return */
6287 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6288 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6289 /* Delete from client, remove all remote VTEPs */
6290 /* Also, free up all MACs and neighbors. */
6291 zvni_send_del_to_client(zvni
->vni
);
6292 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6293 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6294 zvni_vtep_del_all(zvni
, 1);
6298 /* Handle other changes. */
6299 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6300 /* Remove all existing local neigh and MACs for this VNI
6301 * (including from BGP)
6303 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6304 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6307 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6308 zvni
->vxlan_if
= ifp
;
6310 /* Take further actions needed.
6311 * Note that if we are here, there is a change of interest.
6313 /* If down or not mapped to a bridge, we're done. */
6314 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6317 /* Inform BGP, if there is a change of interest. */
6319 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
6320 zvni_send_add_to_client(zvni
);
6322 /* If there is a valid new master or a VLAN mapping change,
6323 * read and populate local MACs and neighbors.
6324 * Also, reinstall any remote MACs and neighbors
6325 * for this VNI (based on new VLAN).
6327 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6328 zvni_read_mac_neigh(zvni
, ifp
);
6329 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6330 struct mac_walk_ctx m_wctx
;
6331 struct neigh_walk_ctx n_wctx
;
6333 zvni_read_mac_neigh(zvni
, ifp
);
6335 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6337 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
6340 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6342 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6351 * Handle VxLAN interface add.
6353 int zebra_vxlan_if_add(struct interface
*ifp
)
6356 struct zebra_if
*zif
= NULL
;
6357 struct zebra_l2info_vxlan
*vxl
= NULL
;
6358 zebra_vni_t
*zvni
= NULL
;
6359 zebra_l3vni_t
*zl3vni
= NULL
;
6361 /* Check if EVPN is enabled. */
6362 if (!is_evpn_enabled())
6367 vxl
= &zif
->l2info
.vxl
;
6370 zl3vni
= zl3vni_lookup(vni
);
6373 /* process if-add for l3-vni*/
6374 if (IS_ZEBRA_DEBUG_VXLAN
)
6376 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6377 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6378 inet_ntoa(vxl
->vtep_ip
),
6379 zif
->brslave_info
.bridge_ifindex
);
6381 /* associate with vxlan_if */
6382 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6383 zl3vni
->vxlan_if
= ifp
;
6385 /* Associate with SVI, if any. We can associate with svi-if only
6386 * after association with vxlan_if is complete */
6387 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6389 if (is_l3vni_oper_up(zl3vni
))
6390 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6393 /* process if-add for l2-vni */
6394 struct interface
*vlan_if
= NULL
;
6396 /* Create or update VNI hash. */
6397 zvni
= zvni_lookup(vni
);
6399 zvni
= zvni_add(vni
);
6402 "Failed to add VNI hash, IF %s(%u) VNI %u",
6403 ifp
->name
, ifp
->ifindex
, vni
);
6408 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6409 zvni
->vxlan_if
= ifp
;
6410 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6411 zif
->brslave_info
.br_if
);
6413 zvni
->vrf_id
= vlan_if
->vrf_id
;
6414 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6416 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6419 if (IS_ZEBRA_DEBUG_VXLAN
)
6421 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6423 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
6425 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6426 inet_ntoa(vxl
->vtep_ip
),
6427 zif
->brslave_info
.bridge_ifindex
);
6429 /* If down or not mapped to a bridge, we're done. */
6430 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6434 zvni_send_add_to_client(zvni
);
6436 /* Read and populate local MACs and neighbors */
6437 zvni_read_mac_neigh(zvni
, ifp
);
6443 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
6444 char *err
, int err_str_sz
, int filter
,
6447 zebra_l3vni_t
*zl3vni
= NULL
;
6448 struct zebra_vrf
*zvrf_default
= NULL
;
6450 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
6454 if (IS_ZEBRA_DEBUG_VXLAN
)
6455 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
6456 add
? "ADD" : "DEL");
6460 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6462 /* check if the vni is already present under zvrf */
6464 snprintf(err
, err_str_sz
,
6465 "VNI is already configured under the vrf");
6469 /* check if this VNI is already present in the system */
6470 zl3vni
= zl3vni_lookup(vni
);
6472 snprintf(err
, err_str_sz
,
6473 "VNI is already configured as L3-VNI");
6477 /* add the L3-VNI to the global table */
6478 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
6480 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
6484 /* associate the vrf with vni */
6487 /* set the filter in l3vni to denote if we are using l3vni only
6491 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
6493 /* associate with vxlan-intf;
6494 * we need to associate with the vxlan-intf first
6496 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
6498 /* associate with corresponding SVI interface, we can associate
6499 * with svi-if only after vxlan interface association is
6502 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6504 /* formulate l2vni list */
6505 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
6508 if (is_l3vni_oper_up(zl3vni
))
6509 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6512 zl3vni
= zl3vni_lookup(vni
);
6514 snprintf(err
, err_str_sz
, "VNI doesn't exist");
6518 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6520 /* delete and uninstall all rmacs */
6521 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
6524 /* delete and uninstall all next-hops */
6525 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
6531 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6536 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
6538 zebra_l3vni_t
*zl3vni
= NULL
;
6541 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6545 zl3vni
->vrf_id
= zvrf_id(zvrf
);
6546 if (is_l3vni_oper_up(zl3vni
))
6547 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6551 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
6553 zebra_l3vni_t
*zl3vni
= NULL
;
6556 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6560 zl3vni
->vrf_id
= VRF_UNKNOWN
;
6561 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6565 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
6567 zebra_l3vni_t
*zl3vni
= NULL
;
6571 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6577 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
6583 * Handle message from client to enable/disable advertisement of g/w macip
6586 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
6591 zebra_vni_t
*zvni
= NULL
;
6592 struct interface
*ifp
= NULL
;
6593 struct zebra_if
*zif
= NULL
;
6594 struct zebra_l2info_vxlan zl2_info
;
6595 struct interface
*vlan_if
= NULL
;
6597 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6598 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6604 advertise
= stream_getc(s
);
6605 vni
= stream_get3(s
);
6607 zvni
= zvni_lookup(vni
);
6611 if (zvni
->advertise_subnet
== advertise
)
6614 if (IS_ZEBRA_DEBUG_VXLAN
)
6615 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
6616 advertise
? "enabled" : "disabled", vni
,
6617 zvni
->advertise_subnet
? "enabled" : "disabled");
6620 zvni
->advertise_subnet
= advertise
;
6622 ifp
= zvni
->vxlan_if
;
6628 /* If down or not mapped to a bridge, we're done. */
6629 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6632 zl2_info
= zif
->l2info
.vxl
;
6635 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
6639 if (zvni
->advertise_subnet
)
6640 zvni_advertise_subnet(zvni
, vlan_if
, 1);
6642 zvni_advertise_subnet(zvni
, vlan_if
, 0);
6646 * Handle message from client to enable/disable advertisement of g/w macip
6649 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
6654 zebra_vni_t
*zvni
= NULL
;
6655 struct interface
*ifp
= NULL
;
6657 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6658 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6664 STREAM_GETC(s
, advertise
);
6665 STREAM_GET(&vni
, s
, 3);
6668 if (IS_ZEBRA_DEBUG_VXLAN
)
6669 zlog_debug("EVPN gateway macip Adv %s, currently %s",
6670 advertise
? "enabled" : "disabled",
6671 advertise_gw_macip_enabled(NULL
)
6675 if (zvrf
->advertise_gw_macip
== advertise
)
6678 zvrf
->advertise_gw_macip
= advertise
;
6680 if (advertise_gw_macip_enabled(zvni
))
6681 hash_iterate(zvrf
->vni_table
,
6682 zvni_gw_macip_add_for_vni_hash
, NULL
);
6684 hash_iterate(zvrf
->vni_table
,
6685 zvni_gw_macip_del_for_vni_hash
, NULL
);
6688 struct zebra_if
*zif
= NULL
;
6689 struct zebra_l2info_vxlan zl2_info
;
6690 struct interface
*vlan_if
= NULL
;
6691 struct interface
*vrr_if
= NULL
;
6693 zvni
= zvni_lookup(vni
);
6697 if (IS_ZEBRA_DEBUG_VXLAN
)
6699 "EVPN gateway macip Adv %s on VNI %d , currently %s",
6700 advertise
? "enabled" : "disabled", vni
,
6701 advertise_gw_macip_enabled(zvni
) ? "enabled"
6704 if (zvni
->advertise_gw_macip
== advertise
)
6707 zvni
->advertise_gw_macip
= advertise
;
6709 ifp
= zvni
->vxlan_if
;
6715 /* If down or not mapped to a bridge, we're done. */
6716 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6719 zl2_info
= zif
->l2info
.vxl
;
6721 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
6722 zif
->brslave_info
.br_if
);
6726 if (advertise_gw_macip_enabled(zvni
)) {
6727 /* Add primary SVI MAC-IP */
6728 zvni_add_macip_for_intf(vlan_if
, zvni
);
6730 /* Add VRR MAC-IP - if any*/
6731 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6733 zvni_add_macip_for_intf(vrr_if
, zvni
);
6735 /* Del primary MAC-IP */
6736 zvni_del_macip_for_intf(vlan_if
, zvni
);
6738 /* Del VRR MAC-IP - if any*/
6739 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6741 zvni_del_macip_for_intf(vrr_if
, zvni
);
6751 * Handle message from client to learn (or stop learning) about VNIs and MACs.
6752 * When enabled, the VNI hash table will be built and MAC FDB table read;
6753 * when disabled, the entries should be deleted and remote VTEPs and MACs
6754 * uninstalled from the kernel.
6756 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
6758 struct stream
*s
= NULL
;
6760 struct zebra_ns
*zns
= NULL
;
6762 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6763 zlog_err("EVPN VNI Adv for non-default VRF %u", zvrf_id(zvrf
));
6768 STREAM_GETC(s
, advertise
);
6770 if (IS_ZEBRA_DEBUG_VXLAN
)
6771 zlog_debug("EVPN VNI Adv %s, currently %s",
6772 advertise
? "enabled" : "disabled",
6773 is_evpn_enabled() ? "enabled" : "disabled");
6775 if (zvrf
->advertise_all_vni
== advertise
)
6778 zvrf
->advertise_all_vni
= advertise
;
6779 if (is_evpn_enabled()) {
6780 /* Build VNI hash table and inform BGP. */
6781 zvni_build_hash_table();
6783 /* Add all SVI (L3 GW) MACs to BGP*/
6784 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
6787 /* Read the MAC FDB */
6788 macfdb_read(zvrf
->zns
);
6790 /* Read neighbors */
6791 neigh_read(zvrf
->zns
);
6793 /* Cleanup VTEPs for all VNIs - uninstall from
6794 * kernel and free entries.
6796 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6798 /* cleanup all l3vnis */
6799 zns
= zebra_ns_lookup(NS_DEFAULT
);
6803 hash_iterate(zns
->l3vni_table
, zl3vni_cleanup_all
, NULL
);
6811 * Allocate VNI hash table for this VRF and do other initialization.
6812 * NOTE: Currently supported only for default VRF.
6814 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
6818 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
6819 "Zebra VRF VNI Table");
6822 /* Cleanup VNI info, but don't free the table. */
6823 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
6827 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6830 /* Close all VNI handling */
6831 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
6835 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6836 hash_free(zvrf
->vni_table
);
6839 /* init the l3vni table */
6840 void zebra_vxlan_ns_init(struct zebra_ns
*zns
)
6842 zns
->l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
6843 "Zebra VRF L3 VNI table");
6846 /* free l3vni table */
6847 void zebra_vxlan_ns_disable(struct zebra_ns
*zns
)
6849 hash_free(zns
->l3vni_table
);
6852 /* get the l3vni svi ifindex */
6853 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
6855 zebra_l3vni_t
*zl3vni
= NULL
;
6857 zl3vni
= zl3vni_from_vrf(vrf_id
);
6858 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
6861 return zl3vni
->svi_if
->ifindex
;