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
,
64 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
65 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
);
66 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
68 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
70 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
72 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
);
73 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
);
74 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
);
75 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
76 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[]);
78 static int zvni_macip_send_msg_to_client(vni_t vni
,
79 struct ethaddr
*macaddr
,
80 struct ipaddr
*ip
, u_char flags
,
82 static unsigned int neigh_hash_keymake(void *p
);
83 static int neigh_cmp(const void *p1
, const void *p2
);
84 static void *zvni_neigh_alloc(void *p
);
85 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
87 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
88 static int zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
);
89 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
90 struct in_addr
*r_vtep_ip
);
91 static void zvni_neigh_del_all(zebra_vni_t
*zvni
,
92 int uninstall
, int upd_client
, u_int32_t flags
);
93 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
);
94 static int zvni_neigh_send_add_to_client(vni_t vni
,
96 struct ethaddr
*macaddr
, u_char flags
);
97 static int zvni_neigh_send_del_to_client(vni_t vni
,
99 struct ethaddr
*macaddr
, u_char flags
);
100 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
101 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
102 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
103 struct interface
*br_if
);
104 static struct interface
*zvni_map_to_svi(vlanid_t vid
,
105 struct interface
*br_if
);
107 /* l3-vni next-hop neigh related APIs */
108 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
110 static void *zl3vni_nh_alloc(void *p
);
111 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
112 struct ipaddr
*vtep_ip
,
113 struct ethaddr
*rmac
);
114 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
115 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
116 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
118 /* l3-vni rmac related APIs */
119 static void zl3vni_print_rmac_hash(struct hash_backet
*, void *);
120 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
121 struct ethaddr
*rmac
);
122 static void *zl3vni_rmac_alloc(void *p
);
123 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
124 struct ethaddr
*rmac
);
125 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
126 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
127 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
,
130 /* l3-vni related APIs*/
131 static int is_vni_l3(vni_t
);
132 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
);
133 static void *zl3vni_alloc(void *p
);
134 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
135 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
136 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t
);
137 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
);
138 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
);
139 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
140 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
142 static unsigned int mac_hash_keymake(void *p
);
143 static int mac_cmp(const void *p1
, const void *p2
);
144 static void *zvni_mac_alloc(void *p
);
145 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
146 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
147 static int zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
);
148 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
149 struct in_addr
*r_vtep_ip
);
150 static void zvni_mac_del_all(zebra_vni_t
*zvni
,
151 int uninstall
, int upd_client
, u_int32_t flags
);
152 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
153 static int zvni_mac_send_add_to_client(vni_t vni
,
154 struct ethaddr
*macaddr
, u_char flags
);
155 static int zvni_mac_send_del_to_client(vni_t vni
,
156 struct ethaddr
*macaddr
, u_char flags
);
157 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
158 struct interface
*br_if
, vlanid_t vid
);
159 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
160 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
);
161 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
);
163 static unsigned int vni_hash_keymake(void *p
);
164 static int vni_hash_cmp(const void *p1
, const void *p2
);
165 static void *zvni_alloc(void *p
);
166 static zebra_vni_t
*zvni_lookup(vni_t vni
);
167 static zebra_vni_t
*zvni_add(vni_t vni
);
168 static int zvni_del(zebra_vni_t
*zvni
);
169 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
170 static int zvni_send_del_to_client(vni_t vni
);
171 static void zvni_build_hash_table();
172 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
173 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
174 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
175 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
176 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
177 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
178 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
179 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
180 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
181 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
182 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
183 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
185 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
186 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
187 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
190 /* Private functions */
193 * Return number of valid MACs in a VNI's MAC hash table - all
194 * remote MACs and non-internal (auto) local MACs count.
196 static u_int32_t
num_valid_macs(zebra_vni_t
*zvni
)
199 u_int32_t num_macs
= 0;
201 struct hash_backet
*hb
;
204 hash
= zvni
->mac_table
;
207 for (i
= 0; i
< hash
->size
; i
++) {
208 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
209 mac
= (zebra_mac_t
*)hb
->data
;
210 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
211 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
219 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
221 struct zebra_vrf
*zvrf
;
223 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
224 if (zvrf
&& zvrf
->advertise_gw_macip
)
227 if (zvni
&& zvni
->advertise_gw_macip
)
234 * Helper function to determine maximum width of neighbor IP address for
235 * display - just because we're dealing with IPv6 addresses that can
238 static void zvni_find_neigh_addr_width(struct hash_backet
*backet
, void *ctxt
)
241 char buf
[INET6_ADDRSTRLEN
];
242 struct neigh_walk_ctx
*wctx
= ctxt
;
245 n
= (zebra_neigh_t
*)backet
->data
;
249 ipaddr2str(&n
->ip
, buf
, sizeof(buf
)), width
= strlen(buf
);
250 if (width
> wctx
->addr_width
)
251 wctx
->addr_width
= width
;
255 * Print a specific neighbor entry.
257 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
260 char buf1
[ETHER_ADDR_STRLEN
];
261 char buf2
[INET6_ADDRSTRLEN
];
263 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
264 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
265 vty
= (struct vty
*)ctxt
;
267 vty_out(vty
, "IP: %s\n",
268 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
269 vty_out(vty
, " MAC: %s",
270 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
272 json_object_string_add(json
, "ip", buf2
);
273 json_object_string_add(json
, "mac", buf1
);
275 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
277 vty_out(vty
, " Remote VTEP: %s",
278 inet_ntoa(n
->r_vtep_ip
));
280 json_object_string_add(json
, "remoteVtep",
281 inet_ntoa(n
->r_vtep_ip
));
283 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
286 vty_out(vty
, " State: %s",
287 IS_ZEBRA_NEIGH_ACTIVE(n
) ? "Active"
291 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
293 vty_out(vty
, " Default-gateway");
295 json_object_boolean_true_add(json
, "defaultGateway");
302 * Print neighbor hash entry - called for display of all neighbors.
304 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
307 json_object
*json_vni
= NULL
, *json_row
= NULL
;
309 char buf1
[ETHER_ADDR_STRLEN
];
310 char buf2
[INET6_ADDRSTRLEN
];
311 struct neigh_walk_ctx
*wctx
= ctxt
;
314 json_vni
= wctx
->json
;
315 n
= (zebra_neigh_t
*)backet
->data
;
320 json_row
= json_object_new_object();
322 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
323 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
324 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)
325 && !(wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)) {
326 if (json_vni
== NULL
) {
327 vty_out(vty
, "%*s %-6s %-17s\n", -wctx
->addr_width
,
328 buf2
, "local", buf1
);
330 json_object_string_add(json_row
, "type", "local");
331 json_object_string_add(json_row
, "mac", buf1
);
335 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) {
336 if (IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
)) {
337 if (json_vni
== NULL
) {
338 if (wctx
->count
== 0)
340 "%*s %-6s %-17s %-21s\n",
343 "MAC", "Remote VTEP");
344 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
345 -wctx
->addr_width
, buf2
,
347 inet_ntoa(n
->r_vtep_ip
));
349 json_object_string_add(json_row
, "type",
351 json_object_string_add(json_row
, "mac",
353 json_object_string_add(
354 json_row
, "remoteVtep",
355 inet_ntoa(n
->r_vtep_ip
));
360 if (json_vni
== NULL
) {
361 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
362 -wctx
->addr_width
, buf2
, "remote", buf1
,
363 inet_ntoa(n
->r_vtep_ip
));
365 json_object_string_add(json_row
, "type",
367 json_object_string_add(json_row
, "mac", buf1
);
368 json_object_string_add(json_row
, "remoteVtep",
369 inet_ntoa(n
->r_vtep_ip
));
376 json_object_object_add(json_vni
, buf2
, json_row
);
380 * Print neighbors for all VNI.
382 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
386 json_object
*json
= NULL
, *json_vni
= NULL
;
389 struct neigh_walk_ctx wctx
;
390 char vni_str
[VNI_STR_LEN
];
392 vty
= (struct vty
*)args
[0];
393 json
= (json_object
*)args
[1];
395 zvni
= (zebra_vni_t
*)backet
->data
;
398 vty_out(vty
, "{}\n");
401 num_neigh
= hashcount(zvni
->neigh_table
);
404 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
405 zvni
->vni
, num_neigh
);
407 json_vni
= json_object_new_object();
408 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
409 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
413 json_object_object_add(json
, vni_str
, json_vni
);
417 /* Since we have IPv6 addresses to deal with which can vary widely in
418 * size, we try to be a bit more elegant in display by first computing
421 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
424 wctx
.addr_width
= 15;
425 wctx
.json
= json_vni
;
426 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
429 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
430 "Type", "MAC", "Remote VTEP");
431 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
434 json_object_object_add(json
, vni_str
, json_vni
);
437 /* print a specific next hop for an l3vni */
438 static void zl3vni_print_nh(zebra_neigh_t
*n
,
442 char buf1
[ETHER_ADDR_STRLEN
];
443 char buf2
[INET6_ADDRSTRLEN
];
444 struct listnode
*node
= NULL
;
445 struct prefix
*p
= NULL
;
446 json_object
*json_hosts
= NULL
;
449 vty_out(vty
, "Ip: %s\n",
450 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
451 vty_out(vty
, " RMAC: %s\n",
452 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
453 vty_out(vty
, " Refcount: %d\n", listcount(n
->host_list
));
454 vty_out(vty
, " Prefixes:\n");
455 for (ALL_LIST_ELEMENTS_RO(n
->host_list
, node
, p
))
456 vty_out(vty
, " %s\n",
457 prefix2str(p
, buf2
, sizeof(buf2
)));
459 json_hosts
= json_object_new_array();
460 json_object_string_add(json
, "ip",
461 ipaddr2str(&(n
->ip
), buf2
,
463 json_object_string_add(json
, "routerMac",
464 prefix_mac2str(&n
->emac
, buf2
,
466 json_object_int_add(json
, "refCount", listcount(n
->host_list
));
467 for (ALL_LIST_ELEMENTS_RO(n
->host_list
, node
, p
))
468 json_object_array_add(json_hosts
,
469 json_object_new_string(
472 json_object_object_add(json
, "prefixList", json_hosts
);
476 /* Print a specific RMAC entry */
477 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
,
481 char buf1
[ETHER_ADDR_STRLEN
];
482 char buf2
[PREFIX_STRLEN
];
483 struct listnode
*node
= NULL
;
484 struct prefix
*p
= NULL
;
485 json_object
*json_hosts
= NULL
;
488 vty_out(vty
, "MAC: %s\n",
489 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
490 vty_out(vty
, " Remote VTEP: %s\n",
491 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
492 vty_out(vty
, " Refcount: %d\n", listcount(zrmac
->host_list
));
493 vty_out(vty
, " Prefixes:\n");
494 for (ALL_LIST_ELEMENTS_RO(zrmac
->host_list
, node
, p
))
495 vty_out(vty
, " %s\n",
496 prefix2str(p
, buf2
, sizeof(buf2
)));
498 json_hosts
= json_object_new_array();
499 json_object_string_add(json
, "routerMac",
500 prefix_mac2str(&zrmac
->macaddr
,
503 json_object_string_add(json
, "vtepIp",
504 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
505 json_object_int_add(json
, "refCount",
506 listcount(zrmac
->host_list
));
507 for (ALL_LIST_ELEMENTS_RO(zrmac
->host_list
, node
, p
))
508 json_object_array_add(json_hosts
,
509 json_object_new_string(
512 json_object_object_add(json
, "prefixList", json_hosts
);
517 * Print a specific MAC entry.
519 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
)
522 zebra_neigh_t
*n
= NULL
;
523 struct listnode
*node
= NULL
;
525 char buf2
[INET6_ADDRSTRLEN
];
527 vty
= (struct vty
*)ctxt
;
528 vty_out(vty
, "MAC: %s",
529 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
)));
530 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
531 struct zebra_ns
*zns
;
532 struct interface
*ifp
;
535 ifindex
= mac
->fwd_info
.local
.ifindex
;
536 zns
= zebra_ns_lookup(NS_DEFAULT
);
537 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
538 if (!ifp
) // unexpected
540 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
541 if (mac
->fwd_info
.local
.vid
)
542 vty_out(vty
, " VLAN: %u", mac
->fwd_info
.local
.vid
);
543 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
544 vty_out(vty
, " Remote VTEP: %s",
545 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
546 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
547 vty_out(vty
, " Auto Mac ");
550 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
551 vty_out(vty
, " Sticky Mac ");
553 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
554 vty_out(vty
, " Default-gateway Mac ");
557 /* print all the associated neigh */
558 vty_out(vty
, " Neighbors:\n");
559 if (!listcount(mac
->neigh_list
))
560 vty_out(vty
, " No Neighbors\n");
562 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
563 vty_out(vty
, " %s %s\n",
564 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
565 CHECK_FLAG(n
->flags
, ZEBRA_MAC_LOCAL
)
566 ? (IS_ZEBRA_NEIGH_ACTIVE(n
)
577 * Print MAC hash entry - called for display of all MACs.
579 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
582 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
585 struct mac_walk_ctx
*wctx
= ctxt
;
588 json_mac_hdr
= wctx
->json
;
589 mac
= (zebra_mac_t
*)backet
->data
;
593 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
596 json_mac
= json_object_new_object();
598 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
599 && !(wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)) {
600 struct zebra_ns
*zns
;
602 struct interface
*ifp
;
605 zns
= zebra_ns_lookup(NS_DEFAULT
);
606 ifindex
= mac
->fwd_info
.local
.ifindex
;
607 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
608 if (!ifp
) // unexpected
610 vid
= mac
->fwd_info
.local
.vid
;
611 if (json_mac_hdr
== NULL
)
612 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
615 json_object_string_add(json_mac
, "type", "local");
616 json_object_string_add(json_mac
, "intf", ifp
->name
);
619 if (json_mac_hdr
== NULL
)
620 vty_out(vty
, " %-5u", vid
);
622 json_object_int_add(json_mac
, "vlan", vid
);
624 if (json_mac_hdr
== NULL
)
627 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
629 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
630 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) {
631 if (IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
633 if (wctx
->count
== 0) {
634 if (json_mac_hdr
== NULL
) {
635 vty_out(vty
, "\nVNI %u\n\n",
638 "%-17s %-6s %-21s %-5s\n",
644 if (json_mac_hdr
== NULL
)
645 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
647 inet_ntoa(mac
->fwd_info
650 json_object_string_add(json_mac
, "type",
652 json_object_string_add(
653 json_mac
, "remoteVtep",
654 inet_ntoa(mac
->fwd_info
656 json_object_object_add(json_mac_hdr
,
662 if (json_mac_hdr
== NULL
)
663 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
665 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
667 json_object_string_add(json_mac
, "type",
669 json_object_string_add(
670 json_mac
, "remoteVtep",
671 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
672 json_object_object_add(json_mac_hdr
, buf1
,
681 * Print MACs for all VNI.
683 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
686 json_object
*json
= NULL
, *json_vni
= NULL
;
687 json_object
*json_mac
= NULL
;
690 struct mac_walk_ctx
*wctx
= ctxt
;
691 char vni_str
[VNI_STR_LEN
];
693 vty
= (struct vty
*)wctx
->vty
;
694 json
= (struct json_object
*)wctx
->json
;
696 zvni
= (zebra_vni_t
*)backet
->data
;
699 vty_out(vty
, "{}\n");
704 /*We are iterating over a new VNI, set the count to 0*/
707 num_macs
= num_valid_macs(zvni
);
712 json_vni
= json_object_new_object();
713 json_mac
= json_object_new_object();
714 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
717 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
719 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
720 zvni
->vni
, num_macs
);
721 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
722 "Intf/Remote VTEP", "VLAN");
724 json_object_int_add(json_vni
, "numMacs", num_macs
);
726 /* assign per-vni to wctx->json object to fill macs
727 * under the vni. Re-assign primary json object to fill
728 * next vni information.
730 wctx
->json
= json_mac
;
731 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
735 json_object_object_add(json_vni
, "macs", json_mac
);
736 json_object_object_add(json
, vni_str
, json_vni
);
740 static void zl3vni_print_nh_hash(struct hash_backet
*backet
,
743 struct nh_walk_ctx
*wctx
= NULL
;
744 struct vty
*vty
= NULL
;
745 struct json_object
*json_vni
= NULL
;
746 struct json_object
*json_nh
= NULL
;
747 zebra_neigh_t
*n
= NULL
;
748 char buf1
[ETHER_ADDR_STRLEN
];
749 char buf2
[INET6_ADDRSTRLEN
];
751 wctx
= (struct nh_walk_ctx
*)ctx
;
753 json_vni
= wctx
->json
;
755 json_nh
= json_object_new_object();
756 n
= (zebra_neigh_t
*)backet
->data
;
761 vty_out(vty
, "%-15s %-17s\n",
762 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
763 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
765 json_object_string_add(json_nh
, "nexthopIp",
766 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
767 json_object_string_add(json_nh
, "routerMac",
768 prefix_mac2str(&n
->emac
, buf1
,
770 json_object_object_add(json_vni
,
771 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
776 static void zl3vni_print_nh_hash_all_vni(struct hash_backet
*backet
,
779 struct vty
*vty
= NULL
;
780 json_object
*json
= NULL
;
781 json_object
*json_vni
= NULL
;
782 zebra_l3vni_t
*zl3vni
= NULL
;
784 struct nh_walk_ctx wctx
;
785 char vni_str
[VNI_STR_LEN
];
787 vty
= (struct vty
*)args
[0];
788 json
= (struct json_object
*)args
[1];
790 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
793 vty_out(vty
, "{}\n");
797 num_nh
= hashcount(zl3vni
->nh_table
);
802 json_vni
= json_object_new_object();
803 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
807 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n",
808 zl3vni
->vni
, num_nh
);
809 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
811 json_object_int_add(json_vni
, "numNextHops", num_nh
);
813 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
815 wctx
.json
= json_vni
;
816 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
818 json_object_object_add(json
, vni_str
, json_vni
);
821 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet
*backet
,
824 struct vty
*vty
= NULL
;
825 json_object
*json
= NULL
;
826 json_object
*json_vni
= NULL
;
827 zebra_l3vni_t
*zl3vni
= NULL
;
829 struct rmac_walk_ctx wctx
;
830 char vni_str
[VNI_STR_LEN
];
832 vty
= (struct vty
*)args
[0];
833 json
= (struct json_object
*)args
[1];
835 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
838 vty_out(vty
, "{}\n");
842 num_rmacs
= hashcount(zl3vni
->rmac_table
);
847 json_vni
= json_object_new_object();
848 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
852 vty_out(vty
, "\nVNI %u #RMACs %u\n\n",
853 zl3vni
->vni
, num_rmacs
);
854 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
856 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
858 /* assign per-vni to wctx->json object to fill macs
859 * under the vni. Re-assign primary json object to fill
860 * next vni information.
862 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
864 wctx
.json
= json_vni
;
865 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
867 json_object_object_add(json
, vni_str
, json_vni
);
870 static void zl3vni_print_rmac_hash(struct hash_backet
*backet
,
873 zebra_mac_t
*zrmac
= NULL
;
874 struct rmac_walk_ctx
*wctx
= NULL
;
875 struct vty
*vty
= NULL
;
876 struct json_object
*json
= NULL
;
877 struct json_object
*json_rmac
= NULL
;
878 char buf
[ETHER_ADDR_STRLEN
];
880 wctx
= (struct rmac_walk_ctx
*)ctx
;
884 json_rmac
= json_object_new_object();
885 zrmac
= (zebra_mac_t
*)backet
->data
;
890 vty_out(vty
, "%-17s %-21s\n",
891 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
892 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
894 json_object_string_add(json_rmac
, "routerMac",
895 prefix_mac2str(&zrmac
->macaddr
, buf
,
897 json_object_string_add(json_rmac
, "vtepIp",
898 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
899 json_object_object_add(json
,
900 prefix_mac2str(&zrmac
->macaddr
, buf
,
906 /* print a specific L3 VNI entry */
907 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
909 char buf
[ETHER_ADDR_STRLEN
];
910 struct vty
*vty
= NULL
;
911 json_object
*json
= NULL
;
912 zebra_vni_t
*zvni
= NULL
;
913 json_object
*json_vni_list
= NULL
;
914 struct listnode
*node
= NULL
, *nnode
= NULL
;
920 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
921 vty_out(vty
, " Type: %s\n", "L3");
922 vty_out(vty
, " Tenant VRF: %s\n",
923 zl3vni_vrf_name(zl3vni
));
924 vty_out(vty
, " Local Vtep Ip: %s\n",
925 inet_ntoa(zl3vni
->local_vtep_ip
));
926 vty_out(vty
, " Vxlan-Intf: %s\n",
927 zl3vni_vxlan_if_name(zl3vni
));
928 vty_out(vty
, " SVI-If: %s\n",
929 zl3vni_svi_if_name(zl3vni
));
930 vty_out(vty
, " State: %s\n",
931 zl3vni_state2str(zl3vni
));
932 vty_out(vty
, " Router MAC: %s\n",
933 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
934 vty_out(vty
, " L2 VNIs: ");
935 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
936 vty_out(vty
, "%u ", zvni
->vni
);
939 json_vni_list
= json_object_new_array();
940 json_object_int_add(json
, "vni", zl3vni
->vni
);
941 json_object_string_add(json
, "type", "L3");
942 json_object_string_add(json
, "localVtepIp",
943 inet_ntoa(zl3vni
->local_vtep_ip
));
944 json_object_string_add(json
, "vxlanIntf",
945 zl3vni_vxlan_if_name(zl3vni
));
946 json_object_string_add(json
, "sviIntf",
947 zl3vni_svi_if_name(zl3vni
));
948 json_object_string_add(json
, "state",
949 zl3vni_state2str(zl3vni
));
950 json_object_string_add(json
, "vrf",
951 zl3vni_vrf_name(zl3vni
));
952 json_object_string_add(json
, "routerMac",
953 zl3vni_rmac2str(zl3vni
, buf
,
955 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
956 json_object_array_add(json_vni_list
,
957 json_object_new_int(zvni
->vni
));
959 json_object_object_add(json
, "l2Vnis", json_vni_list
);
964 * Print a specific VNI entry.
966 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
972 json_object
*json
= NULL
;
973 json_object
*json_vtep_list
= NULL
;
974 json_object
*json_ip_str
= NULL
;
980 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
981 vty_out(vty
, " Type: %s\n", "L2");
982 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
984 json_object_int_add(json
, "vni", zvni
->vni
);
985 json_object_string_add(json
, "type", "L2");
986 json_object_string_add(json
, "vrf",
987 vrf_id_to_name(zvni
->vrf_id
));
990 if (!zvni
->vxlan_if
) { // unexpected
992 vty_out(vty
, " VxLAN interface: unknown\n");
995 num_macs
= num_valid_macs(zvni
);
996 num_neigh
= hashcount(zvni
->neigh_table
);
998 vty_out(vty
, " VxLAN interface: %s\n",
999 zvni
->vxlan_if
->name
);
1000 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1001 vty_out(vty
," Local VTEP IP: %s\n",
1002 inet_ntoa(zvni
->local_vtep_ip
));
1004 json_object_string_add(json
, "vxlanInterface",
1005 zvni
->vxlan_if
->name
);
1006 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1007 json_object_string_add(json
, "vtepIp",
1008 inet_ntoa(zvni
->local_vtep_ip
));
1009 json_object_string_add(json
, "advertiseGatewayMacip",
1010 zvni
->advertise_gw_macip
? "Yes" : "No");
1011 json_object_int_add(json
, "numMacs", num_macs
);
1012 json_object_int_add(json
, "numArpNd", num_neigh
);
1016 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1019 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1021 json_vtep_list
= json_object_new_array();
1022 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1024 vty_out(vty
, " %s\n",
1025 inet_ntoa(zvtep
->vtep_ip
));
1027 json_ip_str
= json_object_new_string(
1028 inet_ntoa(zvtep
->vtep_ip
));
1029 json_object_array_add(json_vtep_list
,
1034 json_object_object_add(json
, "numRemoteVteps",
1039 " Number of MACs (local and remote) known for this VNI: %u\n",
1042 " Number of ARPs (IPv4 and IPv6, local and remote) "
1043 "known for this VNI: %u\n",
1045 vty_out(vty
, " Advertise-gw-macip: %s\n",
1046 zvni
->advertise_gw_macip
? "Yes" : "No");
1050 /* print a L3 VNI hash entry */
1051 static void zl3vni_print_hash(struct hash_backet
*backet
,
1054 struct vty
*vty
= NULL
;
1055 json_object
*json
= NULL
;
1056 json_object
*json_vni
= NULL
;
1057 zebra_l3vni_t
*zl3vni
= NULL
;
1059 vty
= (struct vty
*)ctx
[0];
1060 json
= (json_object
*)ctx
[1];
1062 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1068 "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1070 zl3vni_vxlan_if_name(zl3vni
),
1071 hashcount(zl3vni
->rmac_table
),
1072 hashcount(zl3vni
->nh_table
),
1074 zl3vni_vrf_name(zl3vni
));
1076 char vni_str
[VNI_STR_LEN
];
1078 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1079 json_vni
= json_object_new_object();
1080 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1081 json_object_string_add(json_vni
, "vxlanIf",
1082 zl3vni_vxlan_if_name(zl3vni
));
1083 json_object_int_add(json_vni
, "numMacs",
1084 hashcount(zl3vni
->rmac_table
));
1085 json_object_int_add(json_vni
, "numArpNd",
1086 hashcount(zl3vni
->nh_table
));
1087 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1088 json_object_string_add(json_vni
, "type", "L3");
1089 json_object_string_add(json_vni
, "tenantVrf",
1090 zl3vni_vrf_name(zl3vni
));
1091 json_object_object_add(json
, vni_str
, json_vni
);
1097 * Print a VNI hash entry - called for display of all VNIs.
1099 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1103 zebra_vtep_t
*zvtep
;
1104 u_int32_t num_vteps
= 0;
1105 u_int32_t num_macs
= 0;
1106 u_int32_t num_neigh
= 0;
1107 json_object
*json
= NULL
;
1108 json_object
*json_vni
= NULL
;
1109 json_object
*json_ip_str
= NULL
;
1110 json_object
*json_vtep_list
= NULL
;
1115 zvni
= (zebra_vni_t
*)backet
->data
;
1119 zvtep
= zvni
->vteps
;
1122 zvtep
= zvtep
->next
;
1125 num_macs
= num_valid_macs(zvni
);
1126 num_neigh
= hashcount(zvni
->neigh_table
);
1129 "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1131 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1132 num_macs
, num_neigh
, num_vteps
,
1133 vrf_id_to_name(zvni
->vrf_id
));
1135 char vni_str
[VNI_STR_LEN
];
1136 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1137 json_vni
= json_object_new_object();
1138 json_object_int_add(json_vni
, "vni", zvni
->vni
);
1139 json_object_string_add(json_vni
, "type", "L2");
1140 json_object_string_add(json_vni
, "vxlanIf",
1141 zvni
->vxlan_if
? zvni
->vxlan_if
->name
1143 json_object_int_add(json_vni
, "numMacs", num_macs
);
1144 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1145 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
1146 json_object_string_add(json_vni
, "tenantVrf",
1147 vrf_id_to_name(zvni
->vrf_id
));
1149 json_vtep_list
= json_object_new_array();
1150 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1151 json_ip_str
= json_object_new_string(
1152 inet_ntoa(zvtep
->vtep_ip
));
1153 json_object_array_add(json_vtep_list
,
1156 json_object_object_add(json_vni
, "remoteVteps",
1159 json_object_object_add(json
, vni_str
, json_vni
);
1164 * Inform BGP about local MACIP.
1166 static int zvni_macip_send_msg_to_client(vni_t vni
,
1167 struct ethaddr
*macaddr
,
1168 struct ipaddr
*ip
, u_char flags
,
1171 char buf
[ETHER_ADDR_STRLEN
];
1172 char buf2
[INET6_ADDRSTRLEN
];
1174 struct zserv
*client
= NULL
;
1175 struct stream
*s
= NULL
;
1177 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
1178 /* BGP may not be running. */
1185 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
1186 stream_putl(s
, vni
);
1187 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
1190 if (IS_IPADDR_V4(ip
))
1191 ipa_len
= IPV4_MAX_BYTELEN
;
1192 else if (IS_IPADDR_V6(ip
))
1193 ipa_len
= IPV6_MAX_BYTELEN
;
1195 stream_putl(s
, ipa_len
); /* IP address length */
1197 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
1199 stream_putl(s
, 0); /* Just MAC. */
1201 stream_putc(s
, flags
); /* sticky mac/gateway mac */
1204 /* Write packet size. */
1205 stream_putw_at(s
, 0, stream_get_endp(s
));
1207 if (IS_ZEBRA_DEBUG_VXLAN
)
1209 "Send MACIP %s flags 0x%x MAC %s IP %s L2-VNI %u to %s",
1210 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del",
1211 flags
, prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1212 ipaddr2str(ip
, buf2
, sizeof(buf2
)), vni
,
1213 zebra_route_string(client
->proto
));
1215 if (cmd
== ZEBRA_MACIP_ADD
)
1216 client
->macipadd_cnt
++;
1218 client
->macipdel_cnt
++;
1220 return zebra_server_send_message(client
);
1224 * Make hash key for neighbors.
1226 static unsigned int neigh_hash_keymake(void *p
)
1228 zebra_neigh_t
*n
= p
;
1229 struct ipaddr
*ip
= &n
->ip
;
1231 if (IS_IPADDR_V4(ip
))
1232 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
1234 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
1235 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
1239 * Compare two neighbor hash structures.
1241 static int neigh_cmp(const void *p1
, const void *p2
)
1243 const zebra_neigh_t
*n1
= p1
;
1244 const zebra_neigh_t
*n2
= p2
;
1246 if (n1
== NULL
&& n2
== NULL
)
1249 if (n1
== NULL
|| n2
== NULL
)
1252 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
1256 * Callback to allocate neighbor hash entry.
1258 static void *zvni_neigh_alloc(void *p
)
1260 const zebra_neigh_t
*tmp_n
= p
;
1263 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
1270 * Add neighbor entry.
1272 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
1273 struct ethaddr
*mac
)
1275 zebra_neigh_t tmp_n
;
1276 zebra_neigh_t
*n
= NULL
;
1277 zebra_mac_t
*zmac
= NULL
;
1279 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
1280 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1281 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
1284 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1285 n
->state
= ZEBRA_NEIGH_INACTIVE
;
1287 /* Associate the neigh to mac */
1288 zmac
= zvni_mac_lookup(zvni
, mac
);
1290 listnode_add_sort(zmac
->neigh_list
, n
);
1296 * Delete neighbor entry.
1298 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1300 zebra_neigh_t
*tmp_n
;
1301 zebra_mac_t
*zmac
= NULL
;
1303 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
1305 listnode_delete(zmac
->neigh_list
, n
);
1307 /* Free the VNI hash entry and allocated memory. */
1308 tmp_n
= hash_release(zvni
->neigh_table
, n
);
1310 XFREE(MTYPE_NEIGH
, tmp_n
);
1316 * Free neighbor hash entry (callback)
1318 static int zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
1320 struct neigh_walk_ctx
*wctx
= arg
;
1321 zebra_neigh_t
*n
= backet
->data
;
1323 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1324 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
1325 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
1326 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
1327 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
1328 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
1329 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1330 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
1333 if (wctx
->uninstall
)
1334 zvni_neigh_uninstall(wctx
->zvni
, n
);
1336 return zvni_neigh_del(wctx
->zvni
, n
);
1343 * Delete all neighbor entries from specific VTEP for a particular VNI.
1345 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
1346 struct in_addr
*r_vtep_ip
)
1348 struct neigh_walk_ctx wctx
;
1350 if (!zvni
->neigh_table
)
1353 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1355 wctx
.uninstall
= uninstall
;
1356 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
1357 wctx
.r_vtep_ip
= *r_vtep_ip
;
1359 hash_iterate(zvni
->neigh_table
,
1360 (void (*)(struct hash_backet
*,
1361 void *))zvni_neigh_del_hash_entry
,
1366 * Delete all neighbor entries for this VNI.
1368 static void zvni_neigh_del_all(zebra_vni_t
*zvni
,
1369 int uninstall
, int upd_client
, u_int32_t flags
)
1371 struct neigh_walk_ctx wctx
;
1373 if (!zvni
->neigh_table
)
1376 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1378 wctx
.uninstall
= uninstall
;
1379 wctx
.upd_client
= upd_client
;
1382 hash_iterate(zvni
->neigh_table
,
1383 (void (*)(struct hash_backet
*,
1384 void *))zvni_neigh_del_hash_entry
,
1389 * Look up neighbor hash entry.
1391 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
1396 memset(&tmp
, 0, sizeof(tmp
));
1397 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
1398 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
1403 /* Process all neigh associated to a mac upon local mac add event */
1404 static void zvni_process_neigh_on_local_mac_add(zebra_vni_t
*zvni
,
1407 zebra_neigh_t
*n
= NULL
;
1408 struct listnode
*node
= NULL
;
1409 char buf
[ETHER_ADDR_STRLEN
];
1410 char buf2
[INET6_ADDRSTRLEN
];
1412 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1413 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1414 /* MAC is learnt locally, program all inactive neigh
1415 * pointing to this mac */
1416 if (IS_ZEBRA_NEIGH_INACTIVE(n
)) {
1417 if (IS_ZEBRA_DEBUG_VXLAN
)
1419 "neigh %s (MAC %s) on L2-VNI %u is now ACTIVE",
1420 ipaddr2str(&n
->ip
, buf2
,
1422 prefix_mac2str(&n
->emac
, buf
,
1426 ZEBRA_NEIGH_SET_ACTIVE(n
);
1427 zvni_neigh_send_add_to_client(
1428 zvni
->vni
, &n
->ip
, &n
->emac
, n
->flags
);
1430 if (IS_ZEBRA_DEBUG_VXLAN
)
1432 "neigh %s (MAC %s) on VNI %u should NOT be ACTIVE",
1433 ipaddr2str(&n
->ip
, buf2
,
1435 prefix_mac2str(&n
->emac
, buf
,
1439 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1440 /* TODO: assume the neigh has moved too ?? */
1445 /* Process all neigh associated to a mac upon local mac del event */
1446 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
1449 zebra_neigh_t
*n
= NULL
;
1450 struct listnode
*node
= NULL
;
1451 char buf
[ETHER_ADDR_STRLEN
];
1452 char buf2
[INET6_ADDRSTRLEN
];
1454 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1455 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1456 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1457 if (IS_ZEBRA_DEBUG_VXLAN
)
1459 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1460 ipaddr2str(&n
->ip
, buf2
,
1462 prefix_mac2str(&n
->emac
, buf
,
1466 ZEBRA_NEIGH_SET_INACTIVE(n
);
1467 zvni_neigh_send_del_to_client(
1468 zvni
->vni
, &n
->ip
, &n
->emac
, 0);
1470 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1471 if (IS_ZEBRA_DEBUG_VXLAN
)
1473 "local MAC %s getting deleted on VNI %u has remote neigh %s",
1474 prefix_mac2str(&n
->emac
, buf
,
1477 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1482 /* process all neigh associated to a mac entry upon remote mac add */
1483 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
1486 zebra_neigh_t
*n
= NULL
;
1487 struct listnode
*node
= NULL
;
1488 char buf
[ETHER_ADDR_STRLEN
];
1489 char buf2
[INET6_ADDRSTRLEN
];
1491 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1492 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1493 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1494 if (IS_ZEBRA_DEBUG_VXLAN
)
1496 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1497 ipaddr2str(&n
->ip
, buf2
,
1499 prefix_mac2str(&n
->emac
, buf
,
1503 ZEBRA_NEIGH_SET_INACTIVE(n
);
1504 zvni_neigh_send_del_to_client(
1505 zvni
->vni
, &n
->ip
, &n
->emac
, 0);
1511 /* process all neigh associated to mac entry upon remote mac del */
1512 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
1515 zebra_neigh_t
*n
= NULL
;
1516 struct listnode
*node
= NULL
;
1517 char buf
[ETHER_ADDR_STRLEN
];
1518 char buf2
[INET6_ADDRSTRLEN
];
1520 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1521 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1522 if (IS_ZEBRA_DEBUG_VXLAN
)
1524 "remote MAC %s getting deleted on VNI %u has local neigh %s",
1525 prefix_mac2str(&n
->emac
, buf
,
1528 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1534 * Inform BGP about local neighbor addition.
1536 static int zvni_neigh_send_add_to_client(vni_t vni
,
1538 struct ethaddr
*macaddr
,
1543 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
1544 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
1546 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1551 * Inform BGP about local neighbor deletion.
1553 static int zvni_neigh_send_del_to_client(vni_t vni
,
1555 struct ethaddr
*macaddr
, u_char flags
)
1557 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1562 * Install remote neighbor into the kernel.
1564 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1566 struct zebra_if
*zif
;
1567 struct zebra_l2info_vxlan
*vxl
;
1568 struct interface
*vlan_if
;
1570 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1573 zif
= zvni
->vxlan_if
->info
;
1576 vxl
= &zif
->l2info
.vxl
;
1578 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1582 return kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
);
1586 * Uninstall remote neighbor from the kernel.
1588 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1590 struct zebra_if
*zif
;
1591 struct zebra_l2info_vxlan
*vxl
;
1592 struct interface
*vlan_if
;
1594 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1597 if (!zvni
->vxlan_if
) {
1598 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
1603 zif
= zvni
->vxlan_if
->info
;
1606 vxl
= &zif
->l2info
.vxl
;
1607 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1611 return kernel_del_neigh(vlan_if
, &n
->ip
);
1615 * Install neighbor hash entry - called upon access VLAN change.
1617 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
1620 struct neigh_walk_ctx
*wctx
= ctxt
;
1622 n
= (zebra_neigh_t
*)backet
->data
;
1626 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
1627 zvni_neigh_install(wctx
->zvni
, n
);
1630 /* Get the VRR interface for SVI if any */
1631 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
1633 struct zebra_vrf
*zvrf
= NULL
;
1634 struct interface
*tmp_if
= NULL
;
1635 struct zebra_if
*zif
= NULL
;
1637 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1640 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
1645 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
1648 if (zif
->link
== ifp
)
1655 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1657 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1658 struct connected
*c
= NULL
;
1659 struct ethaddr macaddr
;
1661 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1663 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1666 memset(&ip
, 0, sizeof(struct ipaddr
));
1667 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1670 if (c
->address
->family
== AF_INET
) {
1671 ip
.ipa_type
= IPADDR_V4
;
1672 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1673 sizeof(struct in_addr
));
1674 } else if (c
->address
->family
== AF_INET6
) {
1675 ip
.ipa_type
= IPADDR_V6
;
1676 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1677 sizeof(struct in6_addr
));
1682 zvni_gw_macip_del(ifp
, zvni
, &ip
);
1688 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1690 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1691 struct connected
*c
= NULL
;
1692 struct ethaddr macaddr
;
1694 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1696 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1699 memset(&ip
, 0, sizeof(struct ipaddr
));
1700 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1703 if (c
->address
->family
== AF_INET
) {
1704 ip
.ipa_type
= IPADDR_V4
;
1705 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1706 sizeof(struct in_addr
));
1707 } else if (c
->address
->family
== AF_INET6
) {
1708 ip
.ipa_type
= IPADDR_V6
;
1709 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1710 sizeof(struct in6_addr
));
1715 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
1721 static int zvni_advertise_subnet(zebra_vni_t
*zvni
,
1722 struct interface
*ifp
,
1725 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1726 struct connected
*c
= NULL
;
1727 struct ethaddr macaddr
;
1729 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1731 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1734 memcpy(&p
, c
->address
, sizeof(struct prefix
));
1736 /* skip link local address */
1737 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
1742 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1743 ZEBRA_IP_PREFIX_ROUTE_ADD
);
1745 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1746 ZEBRA_IP_PREFIX_ROUTE_DEL
);
1752 * zvni_gw_macip_add_to_client
1754 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
1755 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
1757 char buf
[ETHER_ADDR_STRLEN
];
1758 char buf2
[INET6_ADDRSTRLEN
];
1759 zebra_neigh_t
*n
= NULL
;
1760 zebra_mac_t
*mac
= NULL
;
1761 struct zebra_if
*zif
= NULL
;
1762 struct zebra_l2info_vxlan
*vxl
= NULL
;
1764 zif
= zvni
->vxlan_if
->info
;
1768 vxl
= &zif
->l2info
.vxl
;
1770 mac
= zvni_mac_lookup(zvni
, macaddr
);
1772 mac
= zvni_mac_add(zvni
, macaddr
);
1774 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
1775 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1776 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
1781 /* Set "local" forwarding info. */
1782 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
1783 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
1784 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
1785 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
1786 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
1787 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
1789 n
= zvni_neigh_lookup(zvni
, ip
);
1791 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
1794 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1795 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
1796 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1797 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
1802 /* Set "local" forwarding info. */
1803 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
1804 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
1805 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
1806 n
->ifindex
= ifp
->ifindex
;
1808 /* Only advertise in BGP if the knob is enabled */
1809 if (!advertise_gw_macip_enabled(zvni
))
1812 if (IS_ZEBRA_DEBUG_VXLAN
)
1814 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP",
1815 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1816 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1817 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1819 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
1826 * zvni_gw_macip_del_from_client
1828 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
1831 char buf1
[ETHER_ADDR_STRLEN
];
1832 char buf2
[INET6_ADDRSTRLEN
];
1833 zebra_neigh_t
*n
= NULL
;
1834 zebra_mac_t
*mac
= NULL
;
1836 /* If the neigh entry is not present nothing to do*/
1837 n
= zvni_neigh_lookup(zvni
, ip
);
1841 /* mac entry should be present */
1842 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
1844 zlog_err("MAC %s doesnt exists for neigh %s on VNI %u",
1845 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
1846 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1850 /* If the entry is not local nothing to do*/
1851 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
1854 /* only need to delete the entry from bgp if we sent it before */
1855 if (advertise_gw_macip_enabled(zvni
)) {
1856 if (IS_ZEBRA_DEBUG_VXLAN
)
1857 zlog_debug("%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
1858 ifp
->vrf_id
, ifp
->name
,
1859 ifp
->ifindex
, zvni
->vni
,
1860 prefix_mac2str(&(n
->emac
),
1863 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1865 /* Remove neighbor from BGP. */
1866 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
1867 ZEBRA_MACIP_TYPE_GW
);
1870 /* Delete this neighbor entry. */
1871 zvni_neigh_del(zvni
, n
);
1873 /* see if the mac needs to be deleted as well*/
1875 zvni_deref_ip2mac(zvni
, mac
, 0);
1880 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
1883 zebra_vni_t
*zvni
= NULL
;
1884 struct zebra_if
*zif
= NULL
;
1885 struct zebra_l2info_vxlan zl2_info
;
1886 struct interface
*vlan_if
= NULL
;
1887 struct interface
*vrr_if
= NULL
;
1888 struct interface
*ifp
;
1890 /* Add primary SVI MAC*/
1891 zvni
= (zebra_vni_t
*)backet
->data
;
1895 ifp
= zvni
->vxlan_if
;
1900 /* If down or not mapped to a bridge, we're done. */
1901 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1904 zl2_info
= zif
->l2info
.vxl
;
1906 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1910 /* Del primary MAC-IP */
1911 zvni_del_macip_for_intf(vlan_if
, zvni
);
1913 /* Del VRR MAC-IP - if any*/
1914 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1916 zvni_del_macip_for_intf(vrr_if
, zvni
);
1921 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
1924 zebra_vni_t
*zvni
= NULL
;
1925 struct zebra_if
*zif
= NULL
;
1926 struct zebra_l2info_vxlan zl2_info
;
1927 struct interface
*vlan_if
= NULL
;
1928 struct interface
*vrr_if
= NULL
;
1929 struct interface
*ifp
= NULL
;
1931 zvni
= (zebra_vni_t
*)backet
->data
;
1935 ifp
= zvni
->vxlan_if
;
1940 /* If down or not mapped to a bridge, we're done. */
1941 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1943 zl2_info
= zif
->l2info
.vxl
;
1945 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
1946 zif
->brslave_info
.br_if
);
1950 /* Add primary SVI MAC-IP */
1951 zvni_add_macip_for_intf(vlan_if
, zvni
);
1953 /* Add VRR MAC-IP - if any*/
1954 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1956 zvni_add_macip_for_intf(vrr_if
, zvni
);
1962 * Make hash key for MAC.
1964 static unsigned int mac_hash_keymake(void *p
)
1966 zebra_mac_t
*pmac
= p
;
1967 const void *pnt
= (void *)pmac
->macaddr
.octet
;
1969 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
1973 * Compare two MAC addresses.
1975 static int mac_cmp(const void *p1
, const void *p2
)
1977 const zebra_mac_t
*pmac1
= p1
;
1978 const zebra_mac_t
*pmac2
= p2
;
1980 if (pmac1
== NULL
&& pmac2
== NULL
)
1983 if (pmac1
== NULL
|| pmac2
== NULL
)
1986 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
,
1992 * Callback to allocate MAC hash entry.
1994 static void *zvni_mac_alloc(void *p
)
1996 const zebra_mac_t
*tmp_mac
= p
;
1999 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2002 return ((void *)mac
);
2008 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
2010 zebra_mac_t tmp_mac
;
2011 zebra_mac_t
*mac
= NULL
;
2013 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
2014 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
2015 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
2018 mac
->neigh_list
= list_new();
2019 mac
->neigh_list
->cmp
= (int (*)(void *, void *))neigh_cmp
;
2027 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2029 zebra_mac_t
*tmp_mac
;
2031 list_delete_and_null(&mac
->neigh_list
);
2033 /* Free the VNI hash entry and allocated memory. */
2034 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
2036 XFREE(MTYPE_MAC
, tmp_mac
);
2042 * Free MAC hash entry (callback)
2044 static int zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2046 struct mac_walk_ctx
*wctx
= arg
;
2047 zebra_mac_t
*mac
= backet
->data
;
2049 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
2050 || ((wctx
->flags
& DEL_REMOTE_MAC
)
2051 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
2052 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
2053 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
2054 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
2055 &wctx
->r_vtep_ip
))) {
2056 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
2057 zvni_mac_send_del_to_client(
2058 wctx
->zvni
->vni
, &mac
->macaddr
,
2062 if (wctx
->uninstall
)
2063 zvni_mac_uninstall(wctx
->zvni
, mac
, 0);
2065 return zvni_mac_del(wctx
->zvni
, mac
);
2072 * Delete all MAC entries from specific VTEP for a particular VNI.
2074 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2075 struct in_addr
*r_vtep_ip
)
2077 struct mac_walk_ctx wctx
;
2079 if (!zvni
->mac_table
)
2082 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2084 wctx
.uninstall
= uninstall
;
2085 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
2086 wctx
.r_vtep_ip
= *r_vtep_ip
;
2088 hash_iterate(zvni
->mac_table
, (void (*)(struct hash_backet
*,
2089 void *))zvni_mac_del_hash_entry
,
2094 * Delete all MAC entries for this VNI.
2096 static void zvni_mac_del_all(zebra_vni_t
*zvni
,
2097 int uninstall
, int upd_client
, u_int32_t flags
)
2099 struct mac_walk_ctx wctx
;
2101 if (!zvni
->mac_table
)
2104 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2106 wctx
.uninstall
= uninstall
;
2107 wctx
.upd_client
= upd_client
;
2110 hash_iterate(zvni
->mac_table
, (void (*)(struct hash_backet
*,
2111 void *))zvni_mac_del_hash_entry
,
2116 * Look up MAC hash entry.
2118 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
2123 memset(&tmp
, 0, sizeof(tmp
));
2124 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
2125 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
2131 * Inform BGP about local MAC addition.
2133 static int zvni_mac_send_add_to_client(vni_t vni
,
2134 struct ethaddr
*macaddr
,
2139 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2140 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2141 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2142 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2144 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2149 * Inform BGP about local MAC deletion.
2151 static int zvni_mac_send_del_to_client(vni_t vni
,
2152 struct ethaddr
*macaddr
,
2157 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2158 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2159 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2160 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2162 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2167 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2168 * notifications, to see if they are of interest.
2170 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
2171 struct interface
*br_if
, vlanid_t vid
)
2173 struct zebra_ns
*zns
;
2174 struct route_node
*rn
;
2175 struct interface
*tmp_if
= NULL
;
2176 struct zebra_if
*zif
;
2177 struct zebra_l2info_bridge
*br
;
2178 struct zebra_l2info_vxlan
*vxl
= NULL
;
2179 u_char bridge_vlan_aware
;
2183 /* Determine if bridge is VLAN-aware or not */
2186 br
= &zif
->l2info
.br
;
2187 bridge_vlan_aware
= br
->vlan_aware
;
2189 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2190 /* TODO: Optimize with a hash. */
2191 zns
= zebra_ns_lookup(NS_DEFAULT
);
2192 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2193 tmp_if
= (struct interface
*)rn
->info
;
2197 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2199 if (!if_is_operative(tmp_if
))
2201 vxl
= &zif
->l2info
.vxl
;
2203 if (zif
->brslave_info
.br_if
!= br_if
)
2206 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2215 zvni
= zvni_lookup(vxl
->vni
);
2220 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2221 * neighbor notifications, to see if they are of interest.
2223 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
2224 struct interface
*br_if
)
2226 struct zebra_ns
*zns
;
2227 struct route_node
*rn
;
2228 struct interface
*tmp_if
= NULL
;
2229 struct zebra_if
*zif
;
2230 struct zebra_l2info_bridge
*br
;
2231 struct zebra_l2info_vxlan
*vxl
= NULL
;
2232 u_char bridge_vlan_aware
;
2240 /* Make sure the linked interface is a bridge. */
2241 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
2244 /* Determine if bridge is VLAN-aware or not */
2247 br
= &zif
->l2info
.br
;
2248 bridge_vlan_aware
= br
->vlan_aware
;
2249 if (bridge_vlan_aware
) {
2250 struct zebra_l2info_vlan
*vl
;
2252 if (!IS_ZEBRA_IF_VLAN(ifp
))
2257 vl
= &zif
->l2info
.vl
;
2261 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2262 /* TODO: Optimize with a hash. */
2263 zns
= zebra_ns_lookup(NS_DEFAULT
);
2264 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2265 tmp_if
= (struct interface
*)rn
->info
;
2269 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2271 if (!if_is_operative(tmp_if
))
2273 vxl
= &zif
->l2info
.vxl
;
2275 if (zif
->brslave_info
.br_if
!= br_if
)
2278 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2287 zvni
= zvni_lookup(vxl
->vni
);
2291 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
2293 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
2294 * linked to the bridge
2295 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
2298 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
2300 struct zebra_ns
*zns
;
2301 struct route_node
*rn
;
2302 struct interface
*tmp_if
= NULL
;
2303 struct zebra_if
*zif
;
2304 struct zebra_l2info_bridge
*br
;
2305 struct zebra_l2info_vlan
*vl
;
2306 u_char bridge_vlan_aware
;
2309 /* Defensive check, caller expected to invoke only with valid bridge. */
2313 /* Determine if bridge is VLAN-aware or not */
2316 br
= &zif
->l2info
.br
;
2317 bridge_vlan_aware
= br
->vlan_aware
;
2319 /* Check oper status of the SVI. */
2320 if (!bridge_vlan_aware
)
2321 return if_is_operative(br_if
) ? br_if
: NULL
;
2323 /* Identify corresponding VLAN interface. */
2324 /* TODO: Optimize with a hash. */
2325 zns
= zebra_ns_lookup(NS_DEFAULT
);
2326 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2327 tmp_if
= (struct interface
*)rn
->info
;
2328 /* Check oper status of the SVI. */
2329 if (!tmp_if
|| !if_is_operative(tmp_if
))
2332 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
2333 || zif
->link
!= br_if
)
2335 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
2337 if (vl
->vid
== vid
) {
2343 return found
? tmp_if
: NULL
;
2347 * Install remote MAC into the kernel.
2349 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2351 struct zebra_if
*zif
;
2352 struct zebra_l2info_vxlan
*vxl
;
2355 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2358 zif
= zvni
->vxlan_if
->info
;
2361 vxl
= &zif
->l2info
.vxl
;
2363 sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0;
2365 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
2366 mac
->fwd_info
.r_vtep_ip
, sticky
);
2370 * Uninstall remote MAC from the kernel. In the scenario where the MAC
2371 * moves to remote, we have to uninstall any existing local entry first.
2373 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
)
2375 struct zebra_if
*zif
;
2376 struct zebra_l2info_vxlan
*vxl
;
2377 struct in_addr vtep_ip
= {.s_addr
= 0};
2378 struct zebra_ns
*zns
;
2379 struct interface
*ifp
;
2381 if (!local
&& !(mac
->flags
& ZEBRA_MAC_REMOTE
))
2384 if (!zvni
->vxlan_if
) {
2385 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2390 zif
= zvni
->vxlan_if
->info
;
2393 vxl
= &zif
->l2info
.vxl
;
2396 zns
= zebra_ns_lookup(NS_DEFAULT
);
2397 ifp
= if_lookup_by_index_per_ns(zns
,
2398 mac
->fwd_info
.local
.ifindex
);
2399 if (!ifp
) // unexpected
2402 ifp
= zvni
->vxlan_if
;
2403 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
2406 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
,
2411 * Install MAC hash entry - called upon access VLAN change.
2413 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
2416 struct mac_walk_ctx
*wctx
= ctxt
;
2418 mac
= (zebra_mac_t
*)backet
->data
;
2422 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
2423 zvni_mac_install(wctx
->zvni
, mac
);
2427 * Decrement neighbor refcount of MAC; uninstall and free it if
2430 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
2433 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)
2434 || !list_isempty(mac
->neigh_list
))
2438 zvni_mac_uninstall(zvni
, mac
, 0);
2440 zvni_mac_del(zvni
, mac
);
2444 * Read and populate local MACs and neighbors corresponding to this VNI.
2446 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
,
2447 struct interface
*ifp
)
2449 struct zebra_ns
*zns
;
2450 struct zebra_if
*zif
;
2451 struct interface
*vlan_if
;
2452 struct zebra_l2info_vxlan
*vxl
;
2453 struct interface
*vrr_if
;
2456 vxl
= &zif
->l2info
.vxl
;
2457 zns
= zebra_ns_lookup(NS_DEFAULT
);
2459 if (IS_ZEBRA_DEBUG_VXLAN
)
2461 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2462 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2463 zif
->brslave_info
.bridge_ifindex
);
2465 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
2466 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2469 /* Add SVI MAC-IP */
2470 zvni_add_macip_for_intf(vlan_if
, zvni
);
2472 /* Add VRR MAC-IP - if any*/
2473 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2475 zvni_add_macip_for_intf(vrr_if
, zvni
);
2477 neigh_read_for_vlan(zns
, vlan_if
);
2482 * Hash function for VNI.
2484 static unsigned int vni_hash_keymake(void *p
)
2486 const zebra_vni_t
*zvni
= p
;
2488 return (jhash_1word(zvni
->vni
, 0));
2492 * Compare 2 VNI hash entries.
2494 static int vni_hash_cmp(const void *p1
, const void *p2
)
2496 const zebra_vni_t
*zvni1
= p1
;
2497 const zebra_vni_t
*zvni2
= p2
;
2499 return (zvni1
->vni
== zvni2
->vni
);
2503 * Callback to allocate VNI hash entry.
2505 static void *zvni_alloc(void *p
)
2507 const zebra_vni_t
*tmp_vni
= p
;
2510 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
2511 zvni
->vni
= tmp_vni
->vni
;
2512 return ((void *)zvni
);
2516 * Look up VNI hash entry.
2518 static zebra_vni_t
*zvni_lookup(vni_t vni
)
2520 struct zebra_vrf
*zvrf
;
2521 zebra_vni_t tmp_vni
;
2522 zebra_vni_t
*zvni
= NULL
;
2524 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2526 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
2528 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
2534 * Add VNI hash entry.
2536 static zebra_vni_t
*zvni_add(vni_t vni
)
2538 struct zebra_vrf
*zvrf
;
2539 zebra_vni_t tmp_zvni
;
2540 zebra_vni_t
*zvni
= NULL
;
2542 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2544 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
2546 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
2549 /* Create hash table for MAC */
2551 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
2553 /* Create hash table for neighbors */
2554 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
2555 "Zebra VNI Neighbor Table");
2561 * Delete VNI hash entry.
2563 static int zvni_del(zebra_vni_t
*zvni
)
2565 struct zebra_vrf
*zvrf
;
2566 zebra_vni_t
*tmp_zvni
;
2568 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2571 zvni
->vxlan_if
= NULL
;
2573 /* Free the neighbor hash table. */
2574 hash_free(zvni
->neigh_table
);
2575 zvni
->neigh_table
= NULL
;
2577 /* Free the MAC hash table. */
2578 hash_free(zvni
->mac_table
);
2579 zvni
->mac_table
= NULL
;
2581 /* Free the VNI hash entry and allocated memory. */
2582 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
2584 XFREE(MTYPE_ZVNI
, tmp_zvni
);
2590 * Inform BGP about local VNI addition.
2592 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
2594 struct zserv
*client
;
2597 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
2598 /* BGP may not be running. */
2605 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
2606 stream_putl(s
, zvni
->vni
);
2607 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
2608 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
2610 /* Write packet size. */
2611 stream_putw_at(s
, 0, stream_get_endp(s
));
2613 if (IS_ZEBRA_DEBUG_VXLAN
)
2614 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s",
2615 zvni
->vni
, inet_ntoa(zvni
->local_vtep_ip
),
2616 vrf_id_to_name(zvni
->vrf_id
),
2617 zebra_route_string(client
->proto
));
2619 client
->vniadd_cnt
++;
2620 return zebra_server_send_message(client
);
2624 * Inform BGP about local VNI deletion.
2626 static int zvni_send_del_to_client(vni_t vni
)
2628 struct zserv
*client
;
2631 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
2632 /* BGP may not be running. */
2639 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
2640 stream_putl(s
, vni
);
2642 /* Write packet size. */
2643 stream_putw_at(s
, 0, stream_get_endp(s
));
2645 if (IS_ZEBRA_DEBUG_VXLAN
)
2646 zlog_debug("Send VNI_DEL %u to %s", vni
,
2647 zebra_route_string(client
->proto
));
2649 client
->vnidel_cnt
++;
2650 return zebra_server_send_message(client
);
2654 * Build the VNI hash table by going over the VxLAN interfaces. This
2655 * is called when EVPN (advertise-all-vni) is enabled.
2657 static void zvni_build_hash_table()
2659 struct zebra_ns
*zns
;
2660 struct route_node
*rn
;
2661 struct interface
*ifp
;
2663 /* Walk VxLAN interfaces and create VNI hash. */
2664 zns
= zebra_ns_lookup(NS_DEFAULT
);
2665 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2667 struct zebra_if
*zif
;
2668 struct zebra_l2info_vxlan
*vxl
;
2670 ifp
= (struct interface
*)rn
->info
;
2674 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2677 vxl
= &zif
->l2info
.vxl
;
2680 if (is_vni_l3(vni
)) {
2681 zebra_l3vni_t
*zl3vni
= NULL
;
2683 if (IS_ZEBRA_DEBUG_VXLAN
)
2684 zlog_debug("create L3-VNI hash for Intf %s(%u) L3-VNI %u",
2685 ifp
->name
, ifp
->ifindex
, vni
);
2687 zl3vni
= zl3vni_lookup(vni
);
2690 "Failed to locate L3-VNI hash at UP, IF %s(%u) VNI %u",
2691 ifp
->name
, ifp
->ifindex
, vni
);
2695 /* associate with vxlan_if */
2696 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
2697 zl3vni
->vxlan_if
= ifp
;
2700 * we need to associate with SVI.
2701 * we can associate with svi-if only after association
2702 * with vxlan-intf is complete
2704 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
2706 if (is_l3vni_oper_up(zl3vni
))
2707 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
2710 zebra_vni_t
*zvni
= NULL
;
2711 zebra_l3vni_t
*zl3vni
= NULL
;
2712 struct interface
*vlan_if
= NULL
;
2714 if (IS_ZEBRA_DEBUG_VXLAN
)
2716 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
2717 ifp
->name
, ifp
->ifindex
, vni
,
2718 inet_ntoa(vxl
->vtep_ip
));
2720 /* VNI hash entry is not expected to exist. */
2721 zvni
= zvni_lookup(vni
);
2724 "VNI hash already present for IF %s(%u) L2-VNI %u",
2725 ifp
->name
, ifp
->ifindex
, vni
);
2729 zvni
= zvni_add(vni
);
2732 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
2733 ifp
->name
, ifp
->ifindex
, vni
);
2737 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
2738 zvni
->vxlan_if
= ifp
;
2739 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
2740 zif
->brslave_info
.br_if
);
2742 zvni
->vrf_id
= vlan_if
->vrf_id
;
2743 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
2745 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
2749 /* Inform BGP if intf is up and mapped to bridge. */
2750 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
2751 zvni_send_add_to_client(zvni
);
2757 * See if remote VTEP matches with prefix.
2759 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
2761 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
2765 * Locate remote VTEP in VNI hash table.
2767 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2769 zebra_vtep_t
*zvtep
;
2774 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2775 if (zvni_vtep_match(vtep_ip
, zvtep
))
2783 * Add remote VTEP to VNI hash table.
2785 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2787 zebra_vtep_t
*zvtep
;
2789 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
2791 zlog_err("Failed to alloc VTEP entry, VNI %u", zvni
->vni
);
2795 zvtep
->vtep_ip
= *vtep_ip
;
2798 zvni
->vteps
->prev
= zvtep
;
2799 zvtep
->next
= zvni
->vteps
;
2800 zvni
->vteps
= zvtep
;
2806 * Remove remote VTEP from VNI hash table.
2808 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
2811 zvtep
->next
->prev
= zvtep
->prev
;
2813 zvtep
->prev
->next
= zvtep
->next
;
2815 zvni
->vteps
= zvtep
->next
;
2817 zvtep
->prev
= zvtep
->next
= NULL
;
2818 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
2824 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
2825 * uninstall from kernel if asked to.
2827 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
2829 zebra_vtep_t
*zvtep
, *zvtep_next
;
2834 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
2835 zvtep_next
= zvtep
->next
;
2837 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
2838 zvni_vtep_del(zvni
, zvtep
);
2845 * Install remote VTEP into the kernel.
2847 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2849 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
2853 * Uninstall remote VTEP from the kernel.
2855 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2857 if (!zvni
->vxlan_if
) {
2858 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2863 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
2867 * Cleanup VNI/VTEP and update kernel
2869 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
2871 zebra_vni_t
*zvni
= NULL
;
2872 zebra_l3vni_t
*zl3vni
= NULL
;
2873 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
2875 zvni
= (zebra_vni_t
*)backet
->data
;
2879 /* remove from l3-vni list */
2881 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
2883 listnode_delete(zl3vni
->l2vnis
, zvni
);
2885 /* Free up all neighbors and MACs, if any. */
2886 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
2887 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
2889 /* Free up all remote VTEPs, if any. */
2890 zvni_vtep_del_all(zvni
, 1);
2892 /* Delete the hash entry. */
2897 static void zl3vni_cleanup_all(struct hash_backet
*backet
,
2900 zebra_l3vni_t
*zl3vni
= NULL
;
2902 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
2906 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
2909 static int is_host_present_in_host_list(struct list
*list
,
2910 struct prefix
*host
)
2912 struct listnode
*node
= NULL
;
2913 struct prefix
*p
= NULL
;
2915 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
)) {
2916 if (prefix_same(p
, host
))
2922 static void host_list_add_host(struct list
*list
,
2923 struct prefix
*host
)
2925 struct prefix
*p
= NULL
;
2927 p
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct prefix
));
2928 memcpy(p
, host
, sizeof(struct prefix
));
2930 listnode_add_sort(list
, p
);
2933 static void host_list_delete_host(struct list
*list
,
2934 struct prefix
*host
)
2936 struct listnode
*node
= NULL
, *nnode
= NULL
, *node_to_del
= NULL
;
2937 struct prefix
*p
= NULL
;
2939 for (ALL_LIST_ELEMENTS(list
, node
, nnode
, p
)) {
2940 if (prefix_same(p
, host
)) {
2941 XFREE(MTYPE_HOST_PREFIX
, p
);
2947 list_delete_node(list
, node_to_del
);
2951 * Look up MAC hash entry.
2953 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
2954 struct ethaddr
*rmac
)
2959 memset(&tmp
, 0, sizeof(tmp
));
2960 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
2961 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
2967 * Callback to allocate RMAC hash entry.
2969 static void *zl3vni_rmac_alloc(void *p
)
2971 const zebra_mac_t
*tmp_rmac
= p
;
2974 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2977 return ((void *)zrmac
);
2981 * Add RMAC entry to l3-vni
2983 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
2984 struct ethaddr
*rmac
)
2986 zebra_mac_t tmp_rmac
;
2987 zebra_mac_t
*zrmac
= NULL
;
2989 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
2990 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
2991 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
2994 zrmac
->host_list
= list_new();
2995 zrmac
->host_list
->cmp
= (int (*)(void *, void *))prefix_cmp
;
2997 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
2998 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
3006 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
,
3009 zebra_mac_t
*tmp_rmac
;
3011 if (zrmac
->host_list
)
3012 list_delete_and_null(&zrmac
->host_list
);
3013 zrmac
->host_list
= NULL
;
3015 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
3017 XFREE(MTYPE_MAC
, tmp_rmac
);
3023 * Install remote RMAC into the kernel.
3025 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
,
3028 struct zebra_if
*zif
= NULL
;
3029 struct zebra_l2info_vxlan
*vxl
= NULL
;
3031 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
)) ||
3032 !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3035 zif
= zl3vni
->vxlan_if
->info
;
3039 vxl
= &zif
->l2info
.vxl
;
3041 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3043 zrmac
->fwd_info
.r_vtep_ip
, 0);
3047 * Uninstall remote RMAC from the kernel.
3049 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
,
3052 char buf
[ETHER_ADDR_STRLEN
];
3053 struct zebra_if
*zif
= NULL
;
3054 struct zebra_l2info_vxlan
*vxl
= NULL
;
3056 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
)) ||
3057 !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3060 if (!zl3vni
->vxlan_if
) {
3062 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
3063 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
3064 zl3vni
->vni
, zl3vni
);
3068 zif
= zl3vni
->vxlan_if
->info
;
3072 vxl
= &zif
->l2info
.vxl
;
3074 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3075 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3078 /* handle rmac add */
3079 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
,
3080 struct ethaddr
*rmac
,
3081 struct ipaddr
*vtep_ip
,
3082 struct prefix
*host_prefix
)
3084 char buf
[ETHER_ADDR_STRLEN
];
3085 char buf1
[INET6_ADDRSTRLEN
];
3086 zebra_mac_t
*zrmac
= NULL
;
3088 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3091 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
3094 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
3095 prefix_mac2str(rmac
, buf
,
3097 zl3vni
->vni
, ipaddr2str(vtep_ip
, buf1
,
3101 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
3102 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
3104 /* install rmac in kernel */
3105 zl3vni_rmac_install(zl3vni
, zrmac
);
3108 if (!is_host_present_in_host_list(zrmac
->host_list
, host_prefix
))
3109 host_list_add_host(zrmac
->host_list
, host_prefix
);
3114 /* handle rmac delete */
3115 static int zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
,
3116 struct ethaddr
*rmac
,
3117 struct prefix
*host_prefix
)
3119 zebra_mac_t
*zrmac
= NULL
;
3121 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3125 host_list_delete_host(zrmac
->host_list
, host_prefix
);
3126 if (list_isempty(zrmac
->host_list
)) {
3128 /* uninstall from kernel */
3129 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3131 /* del the rmac entry */
3132 zl3vni_rmac_del(zl3vni
, zrmac
);
3138 * Look up nh hash entry on a l3-vni.
3140 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
3146 memset(&tmp
, 0, sizeof(tmp
));
3147 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
3148 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
3155 * Callback to allocate NH hash entry on L3-VNI.
3157 static void *zl3vni_nh_alloc(void *p
)
3159 const zebra_neigh_t
*tmp_n
= p
;
3162 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
3169 * Add neighbor entry.
3171 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
3173 struct ethaddr
*mac
)
3175 zebra_neigh_t tmp_n
;
3176 zebra_neigh_t
*n
= NULL
;
3178 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
3179 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
3180 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
3183 n
->host_list
= list_new();
3184 n
->host_list
->cmp
= (int (*)(void *, void *))prefix_cmp
;
3186 memcpy(&n
->emac
, mac
, ETH_ALEN
);
3187 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3188 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
3194 * Delete neighbor entry.
3196 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
,
3199 zebra_neigh_t
*tmp_n
;
3202 list_delete_and_null(&n
->host_list
);
3203 n
->host_list
= NULL
;
3205 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
3207 XFREE(MTYPE_NEIGH
, tmp_n
);
3213 * Install remote nh as neigh into the kernel.
3215 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
,
3218 if (!is_l3vni_oper_up(zl3vni
))
3221 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
) ||
3222 !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3225 return kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
);
3229 * Uninstall remote nh from the kernel.
3231 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
,
3234 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
) ||
3235 !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3238 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
3241 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
3244 /* add remote vtep as a neigh entry */
3245 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
,
3246 struct ipaddr
*vtep_ip
,
3247 struct ethaddr
*rmac
,
3248 struct prefix
*host_prefix
)
3250 char buf
[ETHER_ADDR_STRLEN
];
3251 char buf1
[INET6_ADDRSTRLEN
];
3252 zebra_neigh_t
*nh
= NULL
;
3254 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3256 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
3260 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
3261 ipaddr2str(vtep_ip
, buf1
,
3263 prefix_mac2str(rmac
, buf
,
3269 /* install the nh neigh in kernel */
3270 zl3vni_nh_install(zl3vni
, nh
);
3273 if (!is_host_present_in_host_list(nh
->host_list
, host_prefix
))
3274 host_list_add_host(nh
->host_list
, host_prefix
);
3279 /* handle nh neigh delete */
3280 static int zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
,
3281 struct ipaddr
*vtep_ip
,
3282 struct prefix
*host_prefix
)
3284 zebra_neigh_t
*nh
= NULL
;
3286 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3290 host_list_delete_host(nh
->host_list
, host_prefix
);
3291 if (list_isempty(nh
->host_list
)) {
3293 /* uninstall from kernel */
3294 zl3vni_nh_uninstall(zl3vni
, nh
);
3296 /* delete the nh entry */
3297 zl3vni_nh_del(zl3vni
, nh
);
3303 /* handle neigh update from kernel - the only thing of interest is to
3304 * readd stale entries.
3306 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
,
3307 struct ipaddr
*ip
, u_int16_t state
)
3310 zebra_neigh_t
*n
= NULL
;
3312 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3316 /* all next hop neigh are remote and installed by frr.
3317 * If the kernel has aged this entry, re-install.
3319 if (state
& NUD_STALE
)
3320 zl3vni_nh_install(zl3vni
, n
);
3325 /* handle neigh delete from kernel */
3326 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
,
3329 zebra_neigh_t
*n
= NULL
;
3331 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3335 /* all next hop neigh are remote and installed by frr.
3336 * If we get an age out notification for these neigh entries, we have to
3339 zl3vni_nh_install(zl3vni
, n
);
3345 * Hash function for L3 VNI.
3347 static unsigned int l3vni_hash_keymake(void *p
)
3349 const zebra_l3vni_t
*zl3vni
= p
;
3351 return jhash_1word(zl3vni
->vni
, 0);
3355 * Compare 2 L3 VNI hash entries.
3357 static int l3vni_hash_cmp(const void *p1
, const void *p2
)
3359 const zebra_l3vni_t
*zl3vni1
= p1
;
3360 const zebra_l3vni_t
*zl3vni2
= p2
;
3362 return (zl3vni1
->vni
== zl3vni2
->vni
);
3366 * Callback to allocate L3 VNI hash entry.
3368 static void *zl3vni_alloc(void *p
)
3370 zebra_l3vni_t
*zl3vni
= NULL
;
3371 const zebra_l3vni_t
*tmp_l3vni
= p
;
3373 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
3374 zl3vni
->vni
= tmp_l3vni
->vni
;
3375 return ((void *)zl3vni
);
3379 * Look up L3 VNI hash entry.
3381 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
3383 struct zebra_ns
*zns
;
3384 zebra_l3vni_t tmp_l3vni
;
3385 zebra_l3vni_t
*zl3vni
= NULL
;
3387 zns
= zebra_ns_lookup(NS_DEFAULT
);
3389 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
3390 tmp_l3vni
.vni
= vni
;
3391 zl3vni
= hash_lookup(zns
->l3vni_table
, &tmp_l3vni
);
3397 * Add L3 VNI hash entry.
3399 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
3401 zebra_l3vni_t tmp_zl3vni
;
3402 struct zebra_ns
*zns
= NULL
;
3403 zebra_l3vni_t
*zl3vni
= NULL
;
3405 zns
= zebra_ns_lookup(NS_DEFAULT
);
3408 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
3409 tmp_zl3vni
.vni
= vni
;
3411 zl3vni
= hash_get(zns
->l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
3414 zl3vni
->vrf_id
= vrf_id
;
3415 zl3vni
->svi_if
= NULL
;
3416 zl3vni
->vxlan_if
= NULL
;
3417 zl3vni
->l2vnis
= list_new();
3418 zl3vni
->l2vnis
->cmp
= (int (*)(void *, void *))vni_hash_cmp
;
3420 /* Create hash table for remote RMAC */
3421 zl3vni
->rmac_table
=
3422 hash_create(mac_hash_keymake
, mac_cmp
,
3423 "Zebra L3-VNI RMAC-Table");
3425 /* Create hash table for neighbors */
3426 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3427 "Zebra L3-VNI next-hop table");
3433 * Delete L3 VNI hash entry.
3435 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
3437 struct zebra_ns
*zns
;
3438 zebra_l3vni_t
*tmp_zl3vni
;
3440 zns
= zebra_ns_lookup(NS_DEFAULT
);
3443 /* free the list of l2vnis */
3444 list_delete_and_null(&zl3vni
->l2vnis
);
3445 zl3vni
->l2vnis
= NULL
;
3447 /* Free the rmac table */
3448 hash_free(zl3vni
->rmac_table
);
3449 zl3vni
->rmac_table
= NULL
;
3451 /* Free the nh table */
3452 hash_free(zl3vni
->nh_table
);
3453 zl3vni
->nh_table
= NULL
;
3455 /* Free the VNI hash entry and allocated memory. */
3456 tmp_zl3vni
= hash_release(zns
->l3vni_table
, zl3vni
);
3458 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
3463 static int is_vni_l3(vni_t vni
)
3465 zebra_l3vni_t
*zl3vni
= NULL
;
3467 zl3vni
= zl3vni_lookup(vni
);
3473 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
3475 struct zebra_ns
*zns
= NULL
;
3476 struct route_node
*rn
= NULL
;
3477 struct interface
*ifp
= NULL
;
3479 /* loop through all vxlan-interface */
3480 zns
= zebra_ns_lookup(NS_DEFAULT
);
3481 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3483 struct zebra_if
*zif
= NULL
;
3484 struct zebra_l2info_vxlan
*vxl
= NULL
;
3486 ifp
= (struct interface
*)rn
->info
;
3491 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3494 vxl
= &zif
->l2info
.vxl
;
3495 if (vxl
->vni
== zl3vni
->vni
) {
3496 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3504 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
3506 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
3507 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
3509 if (!zl3vni
->vxlan_if
)
3512 zif
= zl3vni
->vxlan_if
->info
;
3516 vxl
= &zif
->l2info
.vxl
;
3518 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3521 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
3523 struct zebra_vrf
*zvrf
= NULL
;
3525 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
3529 return zl3vni_lookup(zvrf
->l3vni
);
3533 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3534 * neighbor notifications, to see if they are of interest.
3536 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
3537 struct interface
*br_if
)
3541 u_char bridge_vlan_aware
= 0;
3542 zebra_l3vni_t
*zl3vni
= NULL
;
3543 struct zebra_ns
*zns
= NULL
;
3544 struct route_node
*rn
= NULL
;
3545 struct zebra_if
*zif
= NULL
;
3546 struct interface
*tmp_if
= NULL
;
3547 struct zebra_l2info_bridge
*br
= NULL
;
3548 struct zebra_l2info_vxlan
*vxl
= NULL
;
3553 /* Make sure the linked interface is a bridge. */
3554 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3557 /* Determine if bridge is VLAN-aware or not */
3560 br
= &zif
->l2info
.br
;
3561 bridge_vlan_aware
= br
->vlan_aware
;
3562 if (bridge_vlan_aware
) {
3563 struct zebra_l2info_vlan
*vl
;
3565 if (!IS_ZEBRA_IF_VLAN(ifp
))
3570 vl
= &zif
->l2info
.vl
;
3574 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3575 /* TODO: Optimize with a hash. */
3576 zns
= zebra_ns_lookup(NS_DEFAULT
);
3577 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3578 tmp_if
= (struct interface
*)rn
->info
;
3582 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3584 if (!if_is_operative(tmp_if
))
3586 vxl
= &zif
->l2info
.vxl
;
3588 if (zif
->brslave_info
.br_if
!= br_if
)
3591 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3600 zl3vni
= zl3vni_lookup(vxl
->vni
);
3605 * Inform BGP about l3-vni.
3607 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
3609 struct stream
*s
= NULL
;
3610 struct zserv
*client
= NULL
;
3611 struct ethaddr rmac
;
3612 char buf
[ETHER_ADDR_STRLEN
];
3614 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
3615 /* BGP may not be running. */
3620 memset(&rmac
, 0, sizeof(struct ethaddr
));
3621 zl3vni_get_rmac(zl3vni
, &rmac
);
3626 zclient_create_header(s
, ZEBRA_L3VNI_ADD
,
3627 zl3vni_vrf_id(zl3vni
));
3628 stream_putl(s
, zl3vni
->vni
);
3629 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
3630 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
3632 /* Write packet size. */
3633 stream_putw_at(s
, 0, stream_get_endp(s
));
3635 if (IS_ZEBRA_DEBUG_VXLAN
)
3636 zlog_debug("Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s to %s",
3637 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3638 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
3639 inet_ntoa(zl3vni
->local_vtep_ip
),
3640 zebra_route_string(client
->proto
));
3642 client
->l3vniadd_cnt
++;
3643 return zebra_server_send_message(client
);
3647 * Inform BGP about local l3-VNI deletion.
3649 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
3651 struct stream
*s
= NULL
;
3652 struct zserv
*client
= NULL
;
3654 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
3655 /* BGP may not be running. */
3662 zclient_create_header(s
, ZEBRA_L3VNI_DEL
,
3663 zl3vni_vrf_id(zl3vni
));
3664 stream_putl(s
, zl3vni
->vni
);
3666 /* Write packet size. */
3667 stream_putw_at(s
, 0, stream_get_endp(s
));
3669 if (IS_ZEBRA_DEBUG_VXLAN
)
3670 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s",
3672 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3673 zebra_route_string(client
->proto
));
3675 client
->l3vnidel_cnt
++;
3676 return zebra_server_send_message(client
);
3679 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
3681 if (IS_ZEBRA_DEBUG_VXLAN
)
3682 zlog_debug("L3-VNI %u is UP - send add to BGP",
3685 /* send l3vni add to BGP */
3686 zl3vni_send_add_to_client(zl3vni
);
3689 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
3691 if (IS_ZEBRA_DEBUG_VXLAN
)
3692 zlog_debug("L3-VNI %u is Down - Send del to BGP",
3695 /* send l3-vni del to BGP*/
3696 zl3vni_send_del_to_client(zl3vni
);
3699 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
,
3702 zebra_vni_t
*zvni
= (zebra_vni_t
*) backet
->data
;
3703 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*) ctxt
;
3705 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
3706 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3710 * handle transition of vni from l2 to l3 and vice versa
3712 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
,
3715 zebra_vni_t
*zvni
= NULL
;
3717 /* There is a possibility that VNI notification was already received
3718 * from kernel and we programmed it as L2-VNI
3719 * In such a case we need to delete this L2-VNI first, so
3720 * that it can be reprogrammed as L3-VNI in the system. It is also
3721 * possible that the vrf-vni mapping is removed from FRR while the vxlan
3722 * interface is still present in kernel. In this case to keep it
3723 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
3726 /* Locate hash entry */
3727 zvni
= zvni_lookup(vni
);
3731 if (IS_ZEBRA_DEBUG_VXLAN
)
3732 zlog_debug("Del L2-VNI %u - transition to L3-VNI",
3735 /* Delete VNI from BGP. */
3736 zvni_send_del_to_client(zvni
->vni
);
3738 /* Free up all neighbors and MAC, if any. */
3739 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
3740 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
3742 /* Free up all remote VTEPs, if any. */
3743 zvni_vtep_del_all(zvni
, 0);
3745 /* Delete the hash entry. */
3746 if (zvni_del(zvni
)) {
3747 zlog_err("Failed to del VNI hash %p, VNI %u",
3752 /* TODO_MITESH: This needs to be thought through. We don't have
3753 * enough information at this point to reprogram the vni as
3754 * l2-vni. One way is to store the required info in l3-vni and
3755 * used it solely for this purpose
3762 /* delete and uninstall rmac hash entry */
3763 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
,
3766 zebra_mac_t
*zrmac
= NULL
;
3767 zebra_l3vni_t
*zl3vni
= NULL
;
3769 zrmac
= (zebra_mac_t
*)backet
->data
;
3770 zl3vni
= (zebra_l3vni_t
*)ctx
;
3771 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3772 zl3vni_rmac_del(zl3vni
, zrmac
);
3775 /* delete and uninstall nh hash entry */
3776 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
,
3779 zebra_neigh_t
*n
= NULL
;
3780 zebra_l3vni_t
*zl3vni
= NULL
;
3782 n
= (zebra_neigh_t
*)backet
->data
;
3783 zl3vni
= (zebra_l3vni_t
*)ctx
;
3784 zl3vni_nh_uninstall(zl3vni
, n
);
3785 zl3vni_nh_del(zl3vni
, n
);
3788 static int ip_prefix_send_to_client(vrf_id_t vrf_id
,
3792 struct zserv
*client
= NULL
;
3793 struct stream
*s
= NULL
;
3794 char buf
[PREFIX_STRLEN
];
3796 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
3797 /* BGP may not be running. */
3804 zclient_create_header(s
, cmd
, vrf_id
);
3805 stream_put(s
, p
, sizeof(struct prefix
));
3807 /* Write packet size. */
3808 stream_putw_at(s
, 0, stream_get_endp(s
));
3810 if (IS_ZEBRA_DEBUG_VXLAN
)
3812 "Send ip prefix %s %s on vrf %s",
3813 prefix2str(p
, buf
, sizeof(buf
)),
3814 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
3815 vrf_id_to_name(vrf_id
));
3817 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
3818 client
->prefixadd_cnt
++;
3820 client
->prefixdel_cnt
++;
3822 return zebra_server_send_message(client
);
3825 /* re-add remote rmac if needed */
3826 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
3827 struct ethaddr
*rmac
)
3829 char buf
[ETHER_ADDR_STRLEN
];
3830 zebra_mac_t
*zrmac
= NULL
;
3832 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3836 if (IS_ZEBRA_DEBUG_VXLAN
)
3837 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
3838 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3841 zl3vni_rmac_install(zl3vni
, zrmac
);
3845 /* Public functions */
3847 /* handle evpn route in vrf table */
3848 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
,
3849 struct ethaddr
*rmac
,
3850 struct ipaddr
*vtep_ip
,
3851 struct prefix
*host_prefix
)
3853 zebra_l3vni_t
*zl3vni
= NULL
;
3855 zl3vni
= zl3vni_from_vrf(vrf_id
);
3856 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
3859 /* add the next hop neighbor */
3860 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
3863 zl3vni_remote_rmac_add(zl3vni
, rmac
, vtep_ip
, host_prefix
);
3866 /* handle evpn vrf route delete */
3867 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
3868 struct ethaddr
*rmac
,
3869 struct ipaddr
*vtep_ip
,
3870 struct prefix
*host_prefix
)
3872 zebra_l3vni_t
*zl3vni
= NULL
;
3874 zl3vni
= zl3vni_from_vrf(vrf_id
);
3878 /* delete the next hop entry */
3879 zl3vni_remote_nh_del(zl3vni
, vtep_ip
, host_prefix
);
3881 /* delete the rmac entry */
3882 zl3vni_remote_rmac_del(zl3vni
, rmac
, host_prefix
);
3885 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
,
3887 struct ethaddr
*rmac
,
3890 zebra_l3vni_t
*zl3vni
= NULL
;
3891 zebra_mac_t
*zrmac
= NULL
;
3892 json_object
*json
= NULL
;
3894 if (!is_evpn_enabled()) {
3896 vty_out(vty
, "{}\n");
3901 json
= json_object_new_object();
3903 zl3vni
= zl3vni_lookup(l3vni
);
3906 vty_out(vty
, "{}\n");
3908 vty_out(vty
, "%% L3-VNI %u doesnt exist\n",
3913 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3916 vty_out(vty
, "{}\n");
3919 "%% Requested RMAC doesnt exist in L3-VNI %u",
3924 zl3vni_print_rmac(zrmac
, vty
, json
);
3927 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3928 json
, JSON_C_TO_STRING_PRETTY
));
3929 json_object_free(json
);
3933 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
,
3937 zebra_l3vni_t
*zl3vni
;
3938 u_int32_t num_rmacs
;
3939 struct rmac_walk_ctx wctx
;
3940 json_object
*json
= NULL
;
3942 if (!is_evpn_enabled())
3945 zl3vni
= zl3vni_lookup(l3vni
);
3948 vty_out(vty
, "{}\n");
3950 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
3953 num_rmacs
= hashcount(zl3vni
->rmac_table
);
3958 json
= json_object_new_object();
3960 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
3965 "Number of Remote RMACs known for this VNI: %u\n",
3967 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
3969 json_object_int_add(json
, "numRmacs", num_rmacs
);
3971 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
3974 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3975 json
, JSON_C_TO_STRING_PRETTY
));
3976 json_object_free(json
);
3980 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
,
3983 struct zebra_ns
*zns
= NULL
;
3984 json_object
*json
= NULL
;
3987 if (!is_evpn_enabled()) {
3989 vty_out(vty
, "{}\n");
3993 zns
= zebra_ns_lookup(NS_DEFAULT
);
3996 vty_out(vty
, "{}\n");
4001 json
= json_object_new_object();
4005 hash_iterate(zns
->l3vni_table
,
4006 (void (*)(struct hash_backet
*,
4007 void *))zl3vni_print_rmac_hash_all_vni
,
4011 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4012 json
, JSON_C_TO_STRING_PRETTY
));
4013 json_object_free(json
);
4017 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
,
4022 zebra_l3vni_t
*zl3vni
= NULL
;
4023 zebra_neigh_t
*n
= NULL
;
4024 json_object
*json
= NULL
;
4026 if (!is_evpn_enabled()) {
4028 vty_out(vty
, "{}\n");
4033 json
= json_object_new_object();
4035 zl3vni
= zl3vni_lookup(l3vni
);
4038 vty_out(vty
, "{}\n");
4040 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4044 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4047 vty_out(vty
, "{}\n");
4050 "%% Requested next-hop not present for L3-VNI %u",
4055 zl3vni_print_nh(n
, vty
, json
);
4058 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4059 json
, JSON_C_TO_STRING_PRETTY
));
4060 json_object_free(json
);
4064 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
,
4069 struct nh_walk_ctx wctx
;
4070 json_object
*json
= NULL
;
4071 zebra_l3vni_t
*zl3vni
= NULL
;
4073 if (!is_evpn_enabled())
4076 zl3vni
= zl3vni_lookup(l3vni
);
4079 vty_out(vty
, "{}\n");
4081 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4085 num_nh
= hashcount(zl3vni
->nh_table
);
4090 json
= json_object_new_object();
4096 "Number of NH Neighbors known for this VNI: %u\n",
4098 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
4100 json_object_int_add(json
, "numNextHops", num_nh
);
4102 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
4105 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4106 json
, JSON_C_TO_STRING_PRETTY
));
4107 json_object_free(json
);
4111 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
,
4114 struct zebra_ns
*zns
= NULL
;
4115 json_object
*json
= NULL
;
4118 if (!is_evpn_enabled()) {
4120 vty_out(vty
, "{}\n");
4124 zns
= zebra_ns_lookup(NS_DEFAULT
);
4129 json
= json_object_new_object();
4133 hash_iterate(zns
->l3vni_table
,
4134 (void (*)(struct hash_backet
*,
4135 void *))zl3vni_print_nh_hash_all_vni
,
4139 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4140 json
, JSON_C_TO_STRING_PRETTY
));
4141 json_object_free(json
);
4147 * Display L3 VNI information (VTY command handler).
4149 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, u_char use_json
)
4152 json_object
*json
= NULL
;
4153 zebra_l3vni_t
*zl3vni
= NULL
;
4155 if (!is_evpn_enabled()) {
4157 vty_out(vty
, "{}\n");
4161 zl3vni
= zl3vni_lookup(vni
);
4164 vty_out(vty
, "{}\n");
4166 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4171 json
= json_object_new_object();
4175 zl3vni_print(zl3vni
, (void *)args
);
4178 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4179 json
, JSON_C_TO_STRING_PRETTY
));
4180 json_object_free(json
);
4184 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4185 json_object
*json_vrfs
)
4187 char buf
[ETHER_ADDR_STRLEN
];
4188 zebra_l3vni_t
*zl3vni
= NULL
;
4190 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4195 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
4198 zl3vni_vxlan_if_name(zl3vni
),
4199 zl3vni_svi_if_name(zl3vni
),
4200 zl3vni_state2str(zl3vni
),
4201 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4203 json_object
*json_vrf
= NULL
;
4204 json_vrf
= json_object_new_object();
4205 json_object_string_add(json_vrf
, "vrf",
4207 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
4208 json_object_string_add(json_vrf
, "vxlanIntf",
4209 zl3vni_vxlan_if_name(zl3vni
));
4210 json_object_string_add(json_vrf
, "sviIntf",
4211 zl3vni_svi_if_name(zl3vni
));
4212 json_object_string_add(json_vrf
, "state",
4213 zl3vni_state2str(zl3vni
));
4214 json_object_string_add(json_vrf
, "routerMac",
4215 zl3vni_rmac2str(zl3vni
, buf
,
4217 json_object_array_add(json_vrfs
, json_vrf
);
4222 * Display Neighbors for a VNI (VTY command handler).
4224 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4225 vni_t vni
, u_char use_json
)
4228 u_int32_t num_neigh
;
4229 struct neigh_walk_ctx wctx
;
4230 json_object
*json
= NULL
;
4232 if (!is_evpn_enabled())
4234 zvni
= zvni_lookup(vni
);
4237 vty_out(vty
, "{}\n");
4239 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4242 num_neigh
= hashcount(zvni
->neigh_table
);
4247 json
= json_object_new_object();
4249 /* Since we have IPv6 addresses to deal with which can vary widely in
4250 * size, we try to be a bit more elegant in display by first computing
4251 * the maximum width.
4253 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4256 wctx
.addr_width
= 15;
4258 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4262 "Number of ARPs (local and remote) known for this VNI: %u\n",
4264 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
4265 "Type", "MAC", "Remote VTEP");
4267 json_object_int_add(json
, "numArpNd", num_neigh
);
4269 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4271 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4272 json
, JSON_C_TO_STRING_PRETTY
));
4273 json_object_free(json
);
4278 * Display neighbors across all VNIs (VTY command handler).
4280 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4283 json_object
*json
= NULL
;
4286 if (!is_evpn_enabled())
4290 json
= json_object_new_object();
4294 hash_iterate(zvrf
->vni_table
,
4295 (void (*)(struct hash_backet
*,
4296 void *))zvni_print_neigh_hash_all_vni
,
4299 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4300 json
, JSON_C_TO_STRING_PRETTY
));
4301 json_object_free(json
);
4306 * Display specific neighbor for a VNI, if present (VTY command handler).
4308 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
4309 struct zebra_vrf
*zvrf
, vni_t vni
,
4310 struct ipaddr
*ip
, u_char use_json
)
4314 json_object
*json
= NULL
;
4316 if (!is_evpn_enabled())
4318 zvni
= zvni_lookup(vni
);
4321 vty_out(vty
, "{}\n");
4323 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4326 n
= zvni_neigh_lookup(zvni
, ip
);
4330 "%% Requested neighbor does not exist in VNI %u\n",
4335 json
= json_object_new_object();
4337 zvni_print_neigh(n
, vty
, json
);
4340 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4341 json
, JSON_C_TO_STRING_PRETTY
));
4342 json_object_free(json
);
4347 * Display neighbors for a VNI from specific VTEP (VTY command handler).
4348 * By definition, these are remote neighbors.
4350 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4351 vni_t vni
, struct in_addr vtep_ip
,
4355 u_int32_t num_neigh
;
4356 struct neigh_walk_ctx wctx
;
4357 json_object
*json
= NULL
;
4359 if (!is_evpn_enabled())
4361 zvni
= zvni_lookup(vni
);
4364 vty_out(vty
, "{}\n");
4366 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4369 num_neigh
= hashcount(zvni
->neigh_table
);
4373 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4376 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
4377 wctx
.r_vtep_ip
= vtep_ip
;
4379 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4382 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4383 json
, JSON_C_TO_STRING_PRETTY
));
4384 json_object_free(json
);
4389 * Display MACs for a VNI (VTY command handler).
4391 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4392 vni_t vni
, u_char use_json
)
4396 struct mac_walk_ctx wctx
;
4397 json_object
*json
= NULL
;
4398 json_object
*json_mac
= NULL
;
4400 if (!is_evpn_enabled())
4402 zvni
= zvni_lookup(vni
);
4405 vty_out(vty
, "{}\n");
4407 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4410 num_macs
= num_valid_macs(zvni
);
4415 json
= json_object_new_object();
4416 json_mac
= json_object_new_object();
4419 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4422 wctx
.json
= json_mac
;
4426 "Number of MACs (local and remote) known for this VNI: %u\n",
4428 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
4429 "Intf/Remote VTEP", "VLAN");
4431 json_object_int_add(json
, "numMacs", num_macs
);
4433 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4436 json_object_object_add(json
, "macs", json_mac
);
4437 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4438 json
, JSON_C_TO_STRING_PRETTY
));
4439 json_object_free(json
);
4444 * Display MACs for all VNIs (VTY command handler).
4446 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4449 struct mac_walk_ctx wctx
;
4450 json_object
*json
= NULL
;
4452 if (!is_evpn_enabled()) {
4454 vty_out(vty
, "{}\n");
4458 json
= json_object_new_object();
4460 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4463 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4466 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4467 json
, JSON_C_TO_STRING_PRETTY
));
4468 json_object_free(json
);
4473 * Display MACs for all VNIs (VTY command handler).
4475 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
4476 struct zebra_vrf
*zvrf
,
4477 struct in_addr vtep_ip
,
4480 struct mac_walk_ctx wctx
;
4481 json_object
*json
= NULL
;
4483 if (!is_evpn_enabled())
4487 json
= json_object_new_object();
4489 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4491 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4492 wctx
.r_vtep_ip
= vtep_ip
;
4494 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4497 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4498 json
, JSON_C_TO_STRING_PRETTY
));
4499 json_object_free(json
);
4504 * Display specific MAC for a VNI, if present (VTY command handler).
4506 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4507 vni_t vni
, struct ethaddr
*macaddr
)
4512 if (!is_evpn_enabled())
4514 zvni
= zvni_lookup(vni
);
4516 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4519 mac
= zvni_mac_lookup(zvni
, macaddr
);
4521 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
4526 zvni_print_mac(mac
, vty
);
4530 * Display MACs for a VNI from specific VTEP (VTY command handler).
4532 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4533 vni_t vni
, struct in_addr vtep_ip
,
4538 struct mac_walk_ctx wctx
;
4539 json_object
*json
= NULL
;
4540 json_object
*json_mac
= NULL
;
4542 if (!is_evpn_enabled())
4544 zvni
= zvni_lookup(vni
);
4547 vty_out(vty
, "{}\n");
4549 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4552 num_macs
= num_valid_macs(zvni
);
4557 json
= json_object_new_object();
4558 json_mac
= json_object_new_object();
4561 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4564 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4565 wctx
.r_vtep_ip
= vtep_ip
;
4566 wctx
.json
= json_mac
;
4567 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4570 json_object_int_add(json
, "numMacs", wctx
.count
);
4572 json_object_object_add(json
, "macs", json_mac
);
4573 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4574 json
, JSON_C_TO_STRING_PRETTY
));
4575 json_object_free(json
);
4581 * Display VNI information (VTY command handler).
4583 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
4586 json_object
*json
= NULL
;
4589 if (!is_evpn_enabled())
4593 json
= json_object_new_object();
4597 if (is_vni_l3(vni
)) {
4598 zebra_l3vni_t
*zl3vni
= NULL
;
4600 zl3vni
= zl3vni_lookup(vni
);
4603 vty_out(vty
, "{}\n");
4605 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4609 zl3vni_print(zl3vni
, (void *)args
);
4613 zvni
= zvni_lookup(vni
);
4616 vty_out(vty
, "{}\n");
4618 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4622 zvni_print(zvni
, (void *)args
);
4626 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4627 json
, JSON_C_TO_STRING_PRETTY
));
4628 json_object_free(json
);
4632 /* Display all global details for EVPN */
4633 void zebra_vxlan_print_evpn(struct vty
*vty
, u_char uj
)
4638 json_object
*json
= NULL
;
4639 struct zebra_ns
*zns
= NULL
;
4640 struct zebra_vrf
*zvrf
= NULL
;
4642 if (!is_evpn_enabled())
4645 zns
= zebra_ns_lookup(NS_DEFAULT
);
4649 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
4653 num_l3vnis
= hashcount(zns
->l3vni_table
);
4654 num_l2vnis
= hashcount(zvrf
->vni_table
);
4655 num_vnis
= num_l2vnis
+ num_l3vnis
;
4658 json
= json_object_new_object();
4659 json_object_string_add(json
, "advertiseGatewayMacip",
4660 zvrf
->advertise_gw_macip
? "Yes" : "No");
4661 json_object_int_add(json
, "numVnis", num_vnis
);
4662 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4663 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4665 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
4666 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
4667 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
4668 zvrf
->advertise_gw_macip
? "Yes" : "No");
4672 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4673 json
, JSON_C_TO_STRING_PRETTY
));
4674 json_object_free(json
);
4679 * Display VNI hash table (VTY command handler).
4681 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4684 json_object
*json
= NULL
;
4685 struct zebra_ns
*zns
= NULL
;
4688 if (!is_evpn_enabled())
4691 zns
= zebra_ns_lookup(NS_DEFAULT
);
4697 json
= json_object_new_object();
4700 "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n",
4701 "VNI", "Type", "VxLAN IF", "# MACs",
4702 "# ARPs", "# Remote VTEPs", "Tenant VRF");
4707 /* Display all L2-VNIs */
4708 hash_iterate(zvrf
->vni_table
,
4709 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
4712 /* Display all L3-VNIs */
4713 hash_iterate(zns
->l3vni_table
,
4714 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
4718 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4719 json
, JSON_C_TO_STRING_PRETTY
));
4720 json_object_free(json
);
4725 * Handle neighbor delete (on a VLAN device / L3 interface) from the
4726 * kernel. This may result in either the neighbor getting deleted from
4727 * our database or being re-added to the kernel (if it is a valid
4730 int zebra_vxlan_local_neigh_del(struct interface
*ifp
,
4731 struct interface
*link_if
, struct ipaddr
*ip
)
4733 char buf
[INET6_ADDRSTRLEN
];
4734 char buf2
[ETHER_ADDR_STRLEN
];
4735 zebra_neigh_t
*n
= NULL
;
4736 zebra_vni_t
*zvni
= NULL
;
4737 zebra_mac_t
*zmac
= NULL
;
4738 zebra_l3vni_t
*zl3vni
= NULL
;
4740 /* check if this is a remote neigh entry corresponding to remote
4743 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4745 return zl3vni_local_nh_del(zl3vni
, ip
);
4747 /* We are only interested in neighbors on an SVI that resides on top
4748 * of a VxLAN bridge.
4750 zvni
= zvni_from_svi(ifp
, link_if
);
4754 if (!zvni
->vxlan_if
) {
4756 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
4761 if (IS_ZEBRA_DEBUG_VXLAN
)
4762 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
4763 ipaddr2str(ip
, buf
, sizeof(buf
)),
4764 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
4766 /* If entry doesn't exist, nothing to do. */
4767 n
= zvni_neigh_lookup(zvni
, ip
);
4771 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
4773 if (IS_ZEBRA_DEBUG_VXLAN
)
4775 "Trying to del a neigh %s without a mac %s on VNI %u",
4776 ipaddr2str(ip
, buf
, sizeof(buf
)),
4777 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
4783 /* If it is a remote entry, the kernel has aged this out or someone has
4784 * deleted it, it needs to be re-installed as Quagga is the owner.
4786 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
4787 zvni_neigh_install(zvni
, n
);
4791 /* Remove neighbor from BGP. */
4792 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
4793 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
4796 /* Delete this neighbor entry. */
4797 zvni_neigh_del(zvni
, n
);
4799 /* see if the AUTO mac needs to be deleted */
4800 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
4801 && !listcount(zmac
->neigh_list
))
4802 zvni_mac_del(zvni
, zmac
);
4808 * Handle neighbor add or update (on a VLAN device / L3 interface)
4811 int zebra_vxlan_local_neigh_add_update(struct interface
*ifp
,
4812 struct interface
*link_if
,
4814 struct ethaddr
*macaddr
, u_int16_t state
,
4817 char buf
[ETHER_ADDR_STRLEN
];
4818 char buf2
[INET6_ADDRSTRLEN
];
4819 zebra_vni_t
*zvni
= NULL
;
4820 zebra_neigh_t
*n
= NULL
;
4821 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
4822 zebra_l3vni_t
*zl3vni
= NULL
;
4824 /* check if this is a remote neigh entry corresponding to remote
4827 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4829 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
4831 /* We are only interested in neighbors on an SVI that resides on top
4832 * of a VxLAN bridge.
4834 zvni
= zvni_from_svi(ifp
, link_if
);
4838 if (IS_ZEBRA_DEBUG_VXLAN
)
4840 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u",
4841 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
4842 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
4843 ifp
->ifindex
, state
, ext_learned
? "ext-learned " : "",
4846 /* create a dummy MAC if the MAC is not already present */
4847 zmac
= zvni_mac_lookup(zvni
, macaddr
);
4849 if (IS_ZEBRA_DEBUG_VXLAN
)
4851 "AUTO MAC %s created for neigh %s on VNI %u",
4852 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4853 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
4855 zmac
= zvni_mac_add(zvni
, macaddr
);
4857 zlog_warn("Failed to add MAC %s VNI %u",
4858 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4863 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
4864 memset(&zmac
->flags
, 0, sizeof(u_int32_t
));
4865 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
4868 /* If same entry already exists, it might be a change or it might be a
4869 * move from remote to local.
4871 n
= zvni_neigh_lookup(zvni
, ip
);
4873 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
4874 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
4877 /* Update any params and return - client doesn't
4878 * care about a purely local change.
4880 n
->ifindex
= ifp
->ifindex
;
4884 /* If the MAC has changed,
4885 * need to issue a delete first
4886 * as this means a different MACIP route.
4887 * Also, need to do some unlinking/relinking.
4889 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
4891 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
4893 listnode_delete(old_zmac
->neigh_list
, n
);
4894 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
4897 /* Set "local" forwarding info. */
4898 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
4899 n
->ifindex
= ifp
->ifindex
;
4900 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
4902 /* Link to new MAC */
4903 listnode_add_sort(zmac
->neigh_list
, n
);
4904 } else if (ext_learned
)
4905 /* The neighbor is remote and that is the notification we got.
4908 /* TODO: Evaluate if we need to do anything here. */
4911 /* Neighbor has moved from remote to local. */
4913 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4914 n
->r_vtep_ip
.s_addr
= 0;
4915 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
4916 n
->ifindex
= ifp
->ifindex
;
4919 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
4922 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
4923 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
4924 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4925 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
4928 /* Set "local" forwarding info. */
4929 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
4930 n
->ifindex
= ifp
->ifindex
;
4933 /* Before we program this in BGP, we need to check if MAC is locally
4935 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
4936 if (IS_ZEBRA_DEBUG_VXLAN
)
4938 "Skipping neigh %s add to client as MAC %s is not local on VNI %u",
4939 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
4940 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4947 if (IS_ZEBRA_DEBUG_VXLAN
)
4948 zlog_debug("neigh %s (MAC %s) is now ACTIVE on L2-VNI %u",
4949 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
4950 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4952 ZEBRA_NEIGH_SET_ACTIVE(n
);
4954 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, n
->flags
);
4959 * Handle message from client to delete a remote MACIP for a VNI.
4961 int zebra_vxlan_remote_macip_del(struct zserv
*client
, u_short length
,
4962 struct zebra_vrf
*zvrf
)
4966 struct ethaddr macaddr
;
4968 struct in_addr vtep_ip
;
4972 u_short l
= 0, ipa_len
;
4973 char buf
[ETHER_ADDR_STRLEN
];
4974 char buf1
[INET6_ADDRSTRLEN
];
4975 struct interface
*ifp
= NULL
;
4976 struct zebra_if
*zif
= NULL
;
4978 memset(&macaddr
, 0, sizeof(struct ethaddr
));
4979 memset(&ip
, 0, sizeof(struct ipaddr
));
4980 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
4984 while (l
< length
) {
4985 /* Obtain each remote MACIP and process. */
4986 /* Message contains VNI, followed by MAC followed by IP (if any)
4987 * followed by remote VTEP IP.
4991 memset(&ip
, 0, sizeof(ip
));
4992 STREAM_GETL(s
, vni
);
4993 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
4994 STREAM_GETL(s
, ipa_len
);
4996 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
4998 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5000 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5001 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5002 l
+= IPV4_MAX_BYTELEN
;
5004 if (IS_ZEBRA_DEBUG_VXLAN
)
5006 "Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
5007 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5008 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5010 zebra_route_string(client
->proto
));
5012 /* Locate VNI hash entry - expected to exist. */
5013 zvni
= zvni_lookup(vni
);
5015 if (IS_ZEBRA_DEBUG_VXLAN
)
5017 "Failed to locate VNI hash upon remote MACIP DEL, "
5022 ifp
= zvni
->vxlan_if
;
5025 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
5031 /* If down or not mapped to a bridge, we're done. */
5032 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5035 /* The remote VTEP specified is normally expected to exist, but
5037 * possible that the peer may delete the VTEP before deleting
5039 * referring to the VTEP, in which case the handler (see
5041 * would have already deleted the MACs.
5043 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5046 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5048 n
= zvni_neigh_lookup(zvni
, &ip
);
5052 "Failed to locate MAC %s for neigh %s VNI %u",
5053 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5054 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5058 /* If the remote mac or neighbor doesn't exist there is nothing
5060 * to do. Otherwise, uninstall the entry and then remove it.
5065 /* Ignore the delete if this mac is a gateway mac-ip */
5066 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
) &&
5067 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5068 zlog_err("%u: Ignore Del for MAC %s neigh %s on VNI %u as it is configured as a default gateway",
5070 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5071 ipaddr2str(&ip
, buf1
, sizeof(buf1
)),
5076 /* Uninstall remote neighbor or MAC. */
5078 /* When the MAC changes for an IP, it is possible the
5080 * update the new MAC before trying to delete the "old"
5082 * (as these are two different MACIP routes). Do the
5084 * if the MAC matches.
5086 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5087 && (memcmp(n
->emac
.octet
, macaddr
.octet
,
5090 zvni_neigh_uninstall(zvni
, n
);
5091 zvni_neigh_del(zvni
, n
);
5092 zvni_deref_ip2mac(zvni
, mac
, 1);
5095 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5096 zvni_process_neigh_on_remote_mac_del(zvni
,
5099 if (list_isempty(mac
->neigh_list
)) {
5100 zvni_mac_uninstall(zvni
, mac
, 0);
5101 zvni_mac_del(zvni
, mac
);
5103 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5113 * Handle message from client to add a remote MACIP for a VNI. This
5114 * could be just the add of a MAC address or the add of a neighbor
5117 int zebra_vxlan_remote_macip_add(struct zserv
*client
, u_short length
,
5118 struct zebra_vrf
*zvrf
)
5122 struct ethaddr macaddr
;
5124 struct in_addr vtep_ip
;
5126 zebra_vtep_t
*zvtep
;
5127 zebra_mac_t
*mac
, *old_mac
;
5129 u_short l
= 0, ipa_len
;
5130 int update_mac
= 0, update_neigh
= 0;
5131 char buf
[ETHER_ADDR_STRLEN
];
5132 char buf1
[INET6_ADDRSTRLEN
];
5135 struct interface
*ifp
= NULL
;
5136 struct zebra_if
*zif
= NULL
;
5138 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5139 memset(&ip
, 0, sizeof(struct ipaddr
));
5140 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5142 if (!EVPN_ENABLED(zvrf
)) {
5143 zlog_warn("%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
5144 __PRETTY_FUNCTION__
);
5150 while (l
< length
) {
5151 /* Obtain each remote MACIP and process. */
5152 /* Message contains VNI, followed by MAC followed by IP (if any)
5153 * followed by remote VTEP IP.
5155 update_mac
= update_neigh
= 0;
5158 memset(&ip
, 0, sizeof(ip
));
5159 STREAM_GETL(s
, vni
);
5160 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5161 STREAM_GETL(s
, ipa_len
);
5163 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5165 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5167 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5168 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5169 l
+= IPV4_MAX_BYTELEN
;
5171 /* Get flags - sticky mac and/or gateway mac */
5172 flags
= stream_getc(s
);
5173 sticky
= CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5176 if (IS_ZEBRA_DEBUG_VXLAN
)
5178 "Recv MACIP Add MAC %s IP %s VNI %u Remote VTEP %s with flags 0x%x from %s",
5179 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5180 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5181 inet_ntoa(vtep_ip
), flags
,
5182 zebra_route_string(client
->proto
));
5184 /* Locate VNI hash entry - expected to exist. */
5185 zvni
= zvni_lookup(vni
);
5188 "Failed to locate VNI hash upon remote MACIP ADD, VNI %u",
5192 ifp
= zvni
->vxlan_if
;
5195 "VNI %u hash %p doesn't have intf upon remote MACIP add",
5201 /* If down or not mapped to a bridge, we're done. */
5202 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5205 /* The remote VTEP specified should normally exist, but it is
5207 * that when peering comes up, peer may advertise MACIP routes
5209 * advertising type-3 routes.
5211 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5213 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5215 "Failed to add remote VTEP, VNI %u zvni %p",
5220 zvni_vtep_install(zvni
, &vtep_ip
);
5223 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5225 /* Ignore the update if the mac is already present
5227 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5228 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5229 if (IS_ZEBRA_DEBUG_VXLAN
)
5230 zlog_debug("%u:Ignore MAC %s IP %s on VNI %u as MAC is already configured as gateway mac",
5232 prefix_mac2str(&macaddr
,
5234 ipaddr2str(&ip
, buf1
,
5235 sizeof(buf1
)), vni
);
5239 /* check if the remote MAC is unknown or has a change.
5240 * If so, that needs to be updated first. Note that client could
5241 * install MAC and MACIP separately or just install the latter.
5243 if (!mac
|| !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5244 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0)
5246 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
))
5251 mac
= zvni_mac_add(zvni
, &macaddr
);
5254 "Failed to add MAC %s VNI %u Remote VTEP %s",
5255 prefix_mac2str(&macaddr
, buf
,
5257 vni
, inet_ntoa(vtep_ip
));
5261 /* Is this MAC created for a MACIP? */
5263 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5266 /* Set "auto" and "remote" forwarding info. */
5267 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5268 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5269 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5270 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5273 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5275 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5277 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5279 /* Install the entry. */
5280 zvni_mac_install(zvni
, mac
);
5283 /* If there is no IP, continue - after clearing AUTO flag of
5286 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5290 /* Check if the remote neighbor itself is unknown or has a
5292 * If so, create or update and then install the entry.
5294 n
= zvni_neigh_lookup(zvni
, &ip
);
5295 if (!n
|| !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5296 || (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
)) != 0)
5297 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
))
5302 n
= zvni_neigh_add(zvni
, &ip
, &macaddr
);
5305 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5306 ipaddr2str(&ip
, buf1
,
5308 prefix_mac2str(&macaddr
, buf
,
5310 vni
, inet_ntoa(vtep_ip
));
5314 } else if (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
))
5316 /* MAC change, update neigh list for old and new
5318 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5320 listnode_delete(old_mac
->neigh_list
, n
);
5321 zvni_deref_ip2mac(zvni
, old_mac
, 1);
5323 listnode_add_sort(mac
->neigh_list
, n
);
5324 memcpy(&n
->emac
, &macaddr
, ETH_ALEN
);
5327 /* Set "remote" forwarding info. */
5328 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5329 /* TODO: Handle MAC change. */
5330 n
->r_vtep_ip
= vtep_ip
;
5331 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5333 /* Install the entry. */
5334 zvni_neigh_install(zvni
, n
);
5343 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5344 * us, this must involve a multihoming scenario. Treat this as implicit delete
5345 * of any prior local MAC.
5347 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
5348 struct interface
*br_if
,
5349 struct ethaddr
*macaddr
, vlanid_t vid
)
5351 struct zebra_if
*zif
;
5352 struct zebra_l2info_vxlan
*vxl
;
5356 char buf
[ETHER_ADDR_STRLEN
];
5360 vxl
= &zif
->l2info
.vxl
;
5363 /* Check if EVPN is enabled. */
5364 if (!is_evpn_enabled())
5367 /* Locate hash entry; it is expected to exist. */
5368 zvni
= zvni_lookup(vni
);
5372 /* If entry doesn't exist, nothing to do. */
5373 mac
= zvni_mac_lookup(zvni
, macaddr
);
5377 /* Is it a local entry? */
5378 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5381 if (IS_ZEBRA_DEBUG_VXLAN
)
5383 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5384 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5385 ifp
->name
, ifp
->ifindex
, vni
);
5387 /* Remove MAC from BGP. */
5388 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5391 * If there are no neigh associated with the mac delete the mac
5392 * else mark it as AUTO for forward reference
5394 if (!listcount(mac
->neigh_list
)) {
5395 zvni_mac_del(zvni
, mac
);
5397 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5398 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5405 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5406 * This can happen because the remote MAC entries are also added as "dynamic",
5407 * so the kernel can ageout the entry.
5409 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
5410 struct interface
*br_if
,
5411 struct ethaddr
*macaddr
, vlanid_t vid
)
5413 struct zebra_if
*zif
= NULL
;
5414 struct zebra_l2info_vxlan
*vxl
= NULL
;
5416 zebra_vni_t
*zvni
= NULL
;
5417 zebra_l3vni_t
*zl3vni
= NULL
;
5418 zebra_mac_t
*mac
= NULL
;
5419 char buf
[ETHER_ADDR_STRLEN
];
5423 vxl
= &zif
->l2info
.vxl
;
5426 /* Check if EVPN is enabled. */
5427 if (!is_evpn_enabled())
5430 /* check if this is a remote RMAC and readd simillar to remote macs */
5431 zl3vni
= zl3vni_lookup(vni
);
5433 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
5435 /* Locate hash entry; it is expected to exist. */
5436 zvni
= zvni_lookup(vni
);
5440 /* If entry doesn't exist, nothing to do. */
5441 mac
= zvni_mac_lookup(zvni
, macaddr
);
5445 /* Is it a remote entry? */
5446 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
5449 if (IS_ZEBRA_DEBUG_VXLAN
)
5450 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
5451 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5454 zvni_mac_install(zvni
, mac
);
5459 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
5461 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
5462 struct ethaddr
*macaddr
, vlanid_t vid
)
5466 char buf
[ETHER_ADDR_STRLEN
];
5468 /* We are interested in MACs only on ports or (port, VLAN) that
5471 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5474 if (!zvni
->vxlan_if
) {
5475 zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL",
5480 if (IS_ZEBRA_DEBUG_VXLAN
)
5481 zlog_debug("Del MAC %s intf %s(%u) VID %u -> VNI %u",
5482 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5483 ifp
->ifindex
, vid
, zvni
->vni
);
5485 /* If entry doesn't exist, nothing to do. */
5486 mac
= zvni_mac_lookup(zvni
, macaddr
);
5490 /* Is it a local entry? */
5491 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5494 /* Remove MAC from BGP. */
5495 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5497 /* Update all the neigh entries associated with this mac */
5498 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
5501 * If there are no neigh associated with the mac delete the mac
5502 * else mark it as AUTO for forward reference
5504 if (!listcount(mac
->neigh_list
)) {
5505 zvni_mac_del(zvni
, mac
);
5507 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5508 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5515 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
5517 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
5518 struct interface
*br_if
,
5519 struct ethaddr
*macaddr
, vlanid_t vid
,
5524 char buf
[ETHER_ADDR_STRLEN
];
5528 /* We are interested in MACs only on ports or (port, VLAN) that
5531 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5533 if (IS_ZEBRA_DEBUG_VXLAN
)
5535 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5536 sticky
? "sticky " : "",
5537 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5538 ifp
->name
, ifp
->ifindex
, vid
);
5542 if (!zvni
->vxlan_if
) {
5543 zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD",
5548 if (IS_ZEBRA_DEBUG_VXLAN
)
5550 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
5551 sticky
? "sticky " : "",
5552 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5553 ifp
->ifindex
, vid
, zvni
->vni
);
5555 /* If same entry already exists, nothing to do. */
5556 mac
= zvni_mac_lookup(zvni
, macaddr
);
5558 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5559 mac_sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5565 * return if nothing has changed.
5566 * inform bgp if sticky flag has changed
5567 * update locally and do not inform bgp if local
5568 * parameters like interface has changed
5570 if (mac_sticky
== sticky
5571 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
5572 && mac
->fwd_info
.local
.vid
== vid
) {
5573 if (IS_ZEBRA_DEBUG_VXLAN
)
5575 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
5576 "entry exists and has not changed ",
5577 sticky
? "sticky " : "",
5578 prefix_mac2str(macaddr
, buf
,
5580 ifp
->name
, ifp
->ifindex
, vid
,
5583 } else if (mac_sticky
!= sticky
) {
5586 add
= 0; /* This is an update of local
5589 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5591 * If we have already learned the MAC as a remote sticky
5593 * this is a operator error and we must log a warning
5595 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
5597 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
5598 prefix_mac2str(macaddr
, buf
,
5600 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
5608 mac
= zvni_mac_add(zvni
, macaddr
);
5610 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
5611 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5612 ifp
->name
, ifp
->ifindex
, vid
);
5617 /* Set "local" forwarding info. */
5618 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5619 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5620 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5621 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5622 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
5623 mac
->fwd_info
.local
.vid
= vid
;
5626 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5628 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5630 /* Inform BGP if required. */
5632 zvni_process_neigh_on_local_mac_add(zvni
, mac
);
5633 return zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
5641 * Handle message from client to delete a remote VTEP for a VNI.
5643 int zebra_vxlan_remote_vtep_del(struct zserv
*client
, u_short length
,
5644 struct zebra_vrf
*zvrf
)
5649 struct in_addr vtep_ip
;
5651 zebra_vtep_t
*zvtep
;
5652 struct interface
*ifp
;
5653 struct zebra_if
*zif
;
5655 if (!is_evpn_enabled()) {
5656 zlog_warn("%s: EVPN is not enabled yet we have received a vtep del command",
5657 __PRETTY_FUNCTION__
);
5661 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5662 zlog_err("Recv MACIP DEL for non-default VRF %u",
5669 while (l
< length
) {
5670 /* Obtain each remote VTEP and process. */
5671 STREAM_GETL(s
, vni
);
5673 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5674 l
+= IPV4_MAX_BYTELEN
;
5676 if (IS_ZEBRA_DEBUG_VXLAN
)
5677 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
5678 inet_ntoa(vtep_ip
), vni
,
5679 zebra_route_string(client
->proto
));
5681 /* Locate VNI hash entry - expected to exist. */
5682 zvni
= zvni_lookup(vni
);
5684 if (IS_ZEBRA_DEBUG_VXLAN
)
5686 "Failed to locate VNI hash upon remote VTEP DEL, "
5692 ifp
= zvni
->vxlan_if
;
5695 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
5701 /* If down or not mapped to a bridge, we're done. */
5702 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5705 /* If the remote VTEP does not exist, there's nothing more to
5707 * Otherwise, uninstall any remote MACs pointing to this VTEP
5709 * then, the VTEP entry itself and remove it.
5711 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5715 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
5716 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
5717 zvni_vtep_uninstall(zvni
, &vtep_ip
);
5718 zvni_vtep_del(zvni
, zvtep
);
5726 * Handle message from client to add a remote VTEP for a VNI.
5728 int zebra_vxlan_remote_vtep_add(struct zserv
*client
, u_short length
,
5729 struct zebra_vrf
*zvrf
)
5734 struct in_addr vtep_ip
;
5736 struct interface
*ifp
;
5737 struct zebra_if
*zif
;
5739 if (!is_evpn_enabled()) {
5740 zlog_warn("%s: EVPN not enabled yet we received a vtep_add zapi call",
5741 __PRETTY_FUNCTION__
);
5745 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5746 zlog_err("Recv MACIP ADD for non-default VRF %u",
5753 while (l
< length
) {
5754 /* Obtain each remote VTEP and process. */
5755 STREAM_GETL(s
, vni
);
5757 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5758 l
+= IPV4_MAX_BYTELEN
;
5760 if (IS_ZEBRA_DEBUG_VXLAN
)
5761 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
5762 inet_ntoa(vtep_ip
), vni
,
5763 zebra_route_string(client
->proto
));
5765 /* Locate VNI hash entry - expected to exist. */
5766 zvni
= zvni_lookup(vni
);
5769 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
5774 ifp
= zvni
->vxlan_if
;
5777 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
5784 /* If down or not mapped to a bridge, we're done. */
5785 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5788 /* If the remote VTEP already exists,
5789 there's nothing more to do. */
5790 if (zvni_vtep_find(zvni
, &vtep_ip
))
5793 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5795 "Failed to add remote VTEP, VNI %u zvni %p",
5800 zvni_vtep_install(zvni
, &vtep_ip
);
5808 * Add/Del gateway macip to evpn
5810 * 1. SVI interface on a vlan aware bridge
5811 * 2. SVI interface on a vlan unaware bridge
5812 * 3. vrr interface (MACVLAN) associated to a SVI
5813 * We advertise macip routes for an interface if it is associated to VxLan vlan
5815 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
5819 struct ethaddr macaddr
;
5820 zebra_vni_t
*zvni
= NULL
;
5822 memset(&ip
, 0, sizeof(struct ipaddr
));
5823 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5825 /* Check if EVPN is enabled. */
5826 if (!is_evpn_enabled())
5829 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
5830 struct interface
*svi_if
=
5831 NULL
; /* SVI corresponding to the MACVLAN */
5832 struct zebra_if
*ifp_zif
=
5833 NULL
; /* Zebra daemon specific info for MACVLAN */
5834 struct zebra_if
*svi_if_zif
=
5835 NULL
; /* Zebra daemon specific info for SVI*/
5837 ifp_zif
= ifp
->info
;
5842 * for a MACVLAN interface the link represents the svi_if
5844 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
5845 ifp_zif
->link_ifindex
);
5847 zlog_err("MACVLAN %s(%u) without link information",
5848 ifp
->name
, ifp
->ifindex
);
5852 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
5854 * If it is a vlan aware bridge then the link gives the
5855 * bridge information
5857 struct interface
*svi_if_link
= NULL
;
5859 svi_if_zif
= svi_if
->info
;
5861 svi_if_link
= if_lookup_by_index_per_ns(
5862 zebra_ns_lookup(NS_DEFAULT
),
5863 svi_if_zif
->link_ifindex
);
5864 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
5866 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
5868 * If it is a vlan unaware bridge then svi is the bridge
5871 zvni
= zvni_from_svi(svi_if
, svi_if
);
5873 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
5874 struct zebra_if
*svi_if_zif
=
5875 NULL
; /* Zebra daemon specific info for SVI */
5876 struct interface
*svi_if_link
=
5877 NULL
; /* link info for the SVI = bridge info */
5879 svi_if_zif
= ifp
->info
;
5880 svi_if_link
= if_lookup_by_index_per_ns(
5881 zebra_ns_lookup(NS_DEFAULT
), svi_if_zif
->link_ifindex
);
5882 if (svi_if_zif
&& svi_if_link
)
5883 zvni
= zvni_from_svi(ifp
, svi_if_link
);
5884 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
5885 zvni
= zvni_from_svi(ifp
, ifp
);
5891 if (!zvni
->vxlan_if
) {
5892 zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
5898 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
5900 if (p
->family
== AF_INET
) {
5901 ip
.ipa_type
= IPADDR_V4
;
5902 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
5903 sizeof(struct in_addr
));
5904 } else if (p
->family
== AF_INET6
) {
5905 ip
.ipa_type
= IPADDR_V6
;
5906 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
5907 sizeof(struct in6_addr
));
5912 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
5914 zvni_gw_macip_del(ifp
, zvni
, &ip
);
5920 * Handle SVI interface going down.
5921 * SVI can be associated to either L3-VNI or L2-VNI.
5922 * For L2-VNI: At this point, this is a NOP since
5923 * the kernel deletes the neighbor entries on this SVI (if any).
5924 * We only need to update the vrf corresponding to zvni.
5925 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
5928 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
5930 zebra_l3vni_t
*zl3vni
= NULL
;
5932 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5935 /* process l3-vni down */
5936 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
5938 /* remove association with svi-if */
5939 zl3vni
->svi_if
= NULL
;
5941 zebra_vni_t
*zvni
= NULL
;
5943 /* since we dont have svi corresponding to zvni, we associate it
5944 * to default vrf. Note: the corresponding neigh entries on the
5945 * SVI would have already been deleted */
5946 zvni
= zvni_from_svi(ifp
, link_if
);
5948 zvni
->vrf_id
= VRF_DEFAULT
;
5950 /* update the tenant vrf in BGP */
5951 zvni_send_add_to_client(zvni
);
5958 * Handle SVI interface coming up.
5959 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
5961 * For L2-VNI: we need to install any remote neighbors entried (used for
5963 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
5965 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
5967 zebra_vni_t
*zvni
= NULL
;
5968 zebra_l3vni_t
*zl3vni
= NULL
;
5970 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5973 /* associate with svi */
5974 zl3vni
->svi_if
= ifp
;
5976 /* process oper-up */
5977 if (is_l3vni_oper_up(zl3vni
))
5978 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
5981 /* process SVI up for l2-vni */
5982 struct neigh_walk_ctx n_wctx
;
5984 zvni
= zvni_from_svi(ifp
, link_if
);
5988 if (!zvni
->vxlan_if
) {
5989 zlog_err("VNI %u hash %p doesn't have intf upon SVI up",
5994 if (IS_ZEBRA_DEBUG_VXLAN
)
5995 zlog_debug("SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
5996 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
5997 vrf_id_to_name(ifp
->vrf_id
));
5999 /* update the vrf information for l2-vni and inform bgp */
6000 zvni
->vrf_id
= ifp
->vrf_id
;
6001 zvni_send_add_to_client(zvni
);
6003 /* Install any remote neighbors for this VNI. */
6004 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6006 hash_iterate(zvni
->neigh_table
,
6007 zvni_install_neigh_hash
,
6015 * Handle VxLAN interface down
6017 int zebra_vxlan_if_down(struct interface
*ifp
)
6020 struct zebra_if
*zif
= NULL
;
6021 struct zebra_l2info_vxlan
*vxl
= NULL
;
6023 /* Check if EVPN is enabled. */
6024 if (!is_evpn_enabled())
6029 vxl
= &zif
->l2info
.vxl
;
6033 if (is_vni_l3(vni
)) {
6035 /* process-if-down for l3-vni */
6036 zebra_l3vni_t
*zl3vni
= NULL
;
6038 if (IS_ZEBRA_DEBUG_VXLAN
)
6039 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN",
6040 ifp
->name
, ifp
->ifindex
, vni
);
6042 zl3vni
= zl3vni_lookup(vni
);
6045 "Failed to locate L3-VNI hash at DOWN, IF %s(%u) VNI %u",
6046 ifp
->name
, ifp
->ifindex
, vni
);
6050 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6053 /* process if-down for l2-vni */
6056 if (IS_ZEBRA_DEBUG_VXLAN
)
6057 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN",
6058 ifp
->name
, ifp
->ifindex
, vni
);
6060 /* Locate hash entry; it is expected to exist. */
6061 zvni
= zvni_lookup(vni
);
6064 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
6065 ifp
->name
, ifp
->ifindex
, vni
);
6069 assert(zvni
->vxlan_if
== ifp
);
6071 /* Delete this VNI from BGP. */
6072 zvni_send_del_to_client(zvni
->vni
);
6074 /* Free up all neighbors and MACs, if any. */
6075 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6076 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6078 /* Free up all remote VTEPs, if any. */
6079 zvni_vtep_del_all(zvni
, 1);
6085 * Handle VxLAN interface up - update BGP if required.
6087 int zebra_vxlan_if_up(struct interface
*ifp
)
6090 struct zebra_if
*zif
= NULL
;
6091 struct zebra_l2info_vxlan
*vxl
= NULL
;
6093 /* Check if EVPN is enabled. */
6094 if (!is_evpn_enabled())
6099 vxl
= &zif
->l2info
.vxl
;
6102 if (is_vni_l3(vni
)) {
6104 /* Handle L3-VNI add */
6105 zebra_l3vni_t
*zl3vni
= NULL
;
6107 if (IS_ZEBRA_DEBUG_VXLAN
)
6108 zlog_debug("Intf %s(%u) L3-VNI %u is UP",
6109 ifp
->name
, ifp
->ifindex
, vni
);
6111 zl3vni
= zl3vni_lookup(vni
);
6114 "Failed to locate L3-VNI hash at UP, IF %s(%u) VNI %u",
6115 ifp
->name
, ifp
->ifindex
, vni
);
6119 /* we need to associate with SVI, if any, we can associate with
6120 * svi-if only after association with vxlan-intf is complete
6122 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6124 if (is_l3vni_oper_up(zl3vni
))
6125 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6127 /* Handle L2-VNI add */
6129 zebra_vni_t
*zvni
= NULL
;
6130 zebra_l3vni_t
*zl3vni
= NULL
;
6131 struct interface
*vlan_if
= NULL
;
6133 if (IS_ZEBRA_DEBUG_VXLAN
)
6134 zlog_debug("Intf %s(%u) L2-VNI %u is UP",
6135 ifp
->name
, ifp
->ifindex
, vni
);
6137 /* Locate hash entry; it is expected to exist. */
6138 zvni
= zvni_lookup(vni
);
6141 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
6142 ifp
->name
, ifp
->ifindex
, vni
);
6146 assert(zvni
->vxlan_if
== ifp
);
6147 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6148 zif
->brslave_info
.br_if
);
6150 zvni
->vrf_id
= vlan_if
->vrf_id
;
6151 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6153 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6156 /* If part of a bridge, inform BGP about this VNI. */
6157 /* Also, read and populate local MACs and neighbors. */
6158 if (zif
->brslave_info
.br_if
) {
6159 zvni_send_add_to_client(zvni
);
6160 zvni_read_mac_neigh(zvni
, ifp
);
6168 * Handle VxLAN interface delete. Locate and remove entry in hash table
6169 * and update BGP, if required.
6171 int zebra_vxlan_if_del(struct interface
*ifp
)
6174 struct zebra_if
*zif
= NULL
;
6175 struct zebra_l2info_vxlan
*vxl
= NULL
;
6177 /* Check if EVPN is enabled. */
6178 if (!is_evpn_enabled())
6183 vxl
= &zif
->l2info
.vxl
;
6186 if (is_vni_l3(vni
)) {
6188 /* process if-del for l3-vni */
6189 zebra_l3vni_t
*zl3vni
= NULL
;
6191 if (IS_ZEBRA_DEBUG_VXLAN
)
6192 zlog_debug("Del L3-VNI %u intf %s(%u)",
6193 vni
, ifp
->name
, ifp
->ifindex
);
6195 zl3vni
= zl3vni_lookup(vni
);
6198 "Failed to locate L3-VNI hash at del, IF %s(%u) VNI %u",
6199 ifp
->name
, ifp
->ifindex
, vni
);
6203 /* process oper-down for l3-vni */
6204 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6206 /* remove the association with vxlan_if */
6207 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
6208 zl3vni
->vxlan_if
= NULL
;
6211 /* process if-del for l2-vni*/
6212 zebra_vni_t
*zvni
= NULL
;
6213 zebra_l3vni_t
*zl3vni
= NULL
;
6215 if (IS_ZEBRA_DEBUG_VXLAN
)
6216 zlog_debug("Del L2-VNI %u intf %s(%u)",
6217 vni
, ifp
->name
, ifp
->ifindex
);
6219 /* Locate hash entry; it is expected to exist. */
6220 zvni
= zvni_lookup(vni
);
6223 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6224 ifp
->name
, ifp
->ifindex
, vni
);
6228 /* remove from l3-vni list */
6229 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
6231 listnode_delete(zl3vni
->l2vnis
, zvni
);
6233 /* Delete VNI from BGP. */
6234 zvni_send_del_to_client(zvni
->vni
);
6236 /* Free up all neighbors and MAC, if any. */
6237 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
6238 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
6240 /* Free up all remote VTEPs, if any. */
6241 zvni_vtep_del_all(zvni
, 0);
6243 /* Delete the hash entry. */
6244 if (zvni_del(zvni
)) {
6245 zlog_err("Failed to del VNI hash %p, IF %s(%u) VNI %u",
6246 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
6255 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6257 int zebra_vxlan_if_update(struct interface
*ifp
, u_int16_t chgflags
)
6260 struct zebra_if
*zif
= NULL
;
6261 struct zebra_l2info_vxlan
*vxl
= NULL
;
6263 /* Check if EVPN is enabled. */
6264 if (!is_evpn_enabled())
6269 vxl
= &zif
->l2info
.vxl
;
6272 if (is_vni_l3(vni
)) {
6273 zebra_l3vni_t
*zl3vni
= NULL
;
6275 zl3vni
= zl3vni_lookup(vni
);
6278 "Failed to find L3-VNI hash on update, IF %s(%u) VNI %u",
6279 ifp
->name
, ifp
->ifindex
, vni
);
6283 if (IS_ZEBRA_DEBUG_VXLAN
)
6285 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6286 vni
, ifp
->name
, ifp
->ifindex
,
6287 vxl
->access_vlan
, inet_ntoa(vxl
->vtep_ip
),
6288 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6290 /* Removed from bridge? Cleanup and return */
6291 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6292 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6293 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6297 /* access-vlan change - process oper down, associate with new
6298 * svi_if and then process oper up again
6300 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6301 if (if_is_operative(ifp
)) {
6302 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6303 zl3vni
->svi_if
= NULL
;
6304 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6305 if (is_l3vni_oper_up(zl3vni
))
6306 zebra_vxlan_process_l3vni_oper_up(
6311 /* if we have a valid new master, process l3-vni oper up */
6312 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
6313 if (is_l3vni_oper_up(zl3vni
))
6314 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6317 zebra_vni_t
*zvni
= NULL
;
6319 /* Update VNI hash. */
6320 zvni
= zvni_lookup(vni
);
6323 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6324 ifp
->name
, ifp
->ifindex
, vni
);
6328 if (IS_ZEBRA_DEBUG_VXLAN
)
6330 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6331 vni
, ifp
->name
, ifp
->ifindex
,
6332 vxl
->access_vlan
, inet_ntoa(vxl
->vtep_ip
),
6333 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6335 /* Removed from bridge? Cleanup and return */
6336 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6337 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6338 /* Delete from client, remove all remote VTEPs */
6339 /* Also, free up all MACs and neighbors. */
6340 zvni_send_del_to_client(zvni
->vni
);
6341 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6342 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6343 zvni_vtep_del_all(zvni
, 1);
6347 /* Handle other changes. */
6348 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6349 /* Remove all existing local neigh and MACs for this VNI
6350 * (including from BGP)
6352 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6353 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6356 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6357 zvni
->vxlan_if
= ifp
;
6359 /* Take further actions needed.
6360 * Note that if we are here, there is a change of interest.
6362 /* If down or not mapped to a bridge, we're done. */
6363 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6366 /* Inform BGP, if there is a change of interest. */
6368 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
6369 zvni_send_add_to_client(zvni
);
6371 /* If there is a valid new master or a VLAN mapping change,
6372 * read and populate local MACs and neighbors.
6373 * Also, reinstall any remote MACs and neighbors
6374 * for this VNI (based on new VLAN).
6376 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6377 zvni_read_mac_neigh(zvni
, ifp
);
6378 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6379 struct mac_walk_ctx m_wctx
;
6380 struct neigh_walk_ctx n_wctx
;
6382 zvni_read_mac_neigh(zvni
, ifp
);
6384 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6386 hash_iterate(zvni
->mac_table
,
6387 zvni_install_mac_hash
,
6390 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6392 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6401 * Handle VxLAN interface add.
6403 int zebra_vxlan_if_add(struct interface
*ifp
)
6406 struct zebra_if
*zif
= NULL
;
6407 struct zebra_l2info_vxlan
*vxl
= NULL
;
6409 /* Check if EVPN is enabled. */
6410 if (!is_evpn_enabled())
6415 vxl
= &zif
->l2info
.vxl
;
6418 if (is_vni_l3(vni
)) {
6420 /* process if-add for l3-vni*/
6421 zebra_l3vni_t
*zl3vni
= NULL
;
6423 if (IS_ZEBRA_DEBUG_VXLAN
)
6425 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6426 vni
, ifp
->name
, ifp
->ifindex
,
6427 vxl
->access_vlan
, inet_ntoa(vxl
->vtep_ip
),
6428 zif
->brslave_info
.bridge_ifindex
);
6431 * we expect the l3-vni has entry to be present here.
6432 * The only place l3-vni is created in zebra is vrf-vni mapping
6433 * command. This might change when we have the switchd support
6434 * for l3-vxlan interface.
6436 zl3vni
= zl3vni_lookup(vni
);
6439 "Failed to locate L3-VNI hash at del, IF %s(%u) VNI %u",
6440 ifp
->name
, ifp
->ifindex
, vni
);
6444 /* associate with vxlan_if */
6445 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6446 zl3vni
->vxlan_if
= ifp
;
6448 /* Associate with SVI, if any. We can associate with svi-if only
6449 * after association with vxlan_if is complete */
6450 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6452 if (is_l3vni_oper_up(zl3vni
))
6453 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6456 /* process if-add for l2-vni */
6457 zebra_vni_t
*zvni
= NULL
;
6458 zebra_l3vni_t
*zl3vni
= NULL
;
6459 struct interface
*vlan_if
= NULL
;
6461 /* Create or update VNI hash. */
6462 zvni
= zvni_lookup(vni
);
6464 zvni
= zvni_add(vni
);
6467 "Failed to add VNI hash, IF %s(%u) VNI %u",
6468 ifp
->name
, ifp
->ifindex
, vni
);
6473 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6474 zvni
->vxlan_if
= ifp
;
6475 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6476 zif
->brslave_info
.br_if
);
6478 zvni
->vrf_id
= vlan_if
->vrf_id
;
6479 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6481 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6484 if (IS_ZEBRA_DEBUG_VXLAN
)
6486 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6488 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
) :
6490 ifp
->name
, ifp
->ifindex
,
6491 vxl
->access_vlan
, inet_ntoa(vxl
->vtep_ip
),
6492 zif
->brslave_info
.bridge_ifindex
);
6494 /* If down or not mapped to a bridge, we're done. */
6495 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6499 zvni_send_add_to_client(zvni
);
6501 /* Read and populate local MACs and neighbors */
6502 zvni_read_mac_neigh(zvni
, ifp
);
6508 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
,
6510 char *err
, int err_str_sz
,
6513 zebra_l3vni_t
*zl3vni
= NULL
;
6514 struct zebra_vrf
*zvrf_default
= NULL
;
6516 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
6520 if (IS_ZEBRA_DEBUG_VXLAN
)
6521 zlog_debug("vrf %s vni %u %s",
6524 add
? "ADD" : "DEL");
6528 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6530 /* check if the vni is already present under zvrf */
6532 snprintf(err
, err_str_sz
,
6533 "VNI is already configured under the vrf");
6537 /* check if this VNI is already present in the system */
6538 zl3vni
= zl3vni_lookup(vni
);
6540 snprintf(err
, err_str_sz
,
6541 "VNI is already configured as L3-VNI");
6545 /* add the L3-VNI to the global table */
6546 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
6548 snprintf(err
, err_str_sz
,
6549 "Could not add L3-VNI");
6553 /* associate the vrf with vni */
6556 /* associate with vxlan-intf;
6557 * we need to associate with the vxlan-intf first
6559 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
6561 /* associate with corresponding SVI interface, we can associate
6562 * with svi-if only after vxlan interface association is
6565 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6567 /* formulate l2vni list */
6568 hash_iterate(zvrf_default
->vni_table
,
6569 zvni_add_to_l3vni_list
, zl3vni
);
6571 if (is_l3vni_oper_up(zl3vni
))
6572 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6575 zl3vni
= zl3vni_lookup(vni
);
6577 snprintf(err
, err_str_sz
, "VNI doesn't exist");
6581 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6583 /* delete and uninstall all rmacs */
6584 hash_iterate(zl3vni
->rmac_table
,
6585 zl3vni_del_rmac_hash_entry
,
6588 /* delete and uninstall all next-hops */
6589 hash_iterate(zl3vni
->nh_table
,
6590 zl3vni_del_nh_hash_entry
,
6596 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6601 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
6603 zebra_l3vni_t
*zl3vni
= NULL
;
6606 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6610 zl3vni
->vrf_id
= zvrf_id(zvrf
);
6611 if (is_l3vni_oper_up(zl3vni
))
6612 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6616 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
6618 zebra_l3vni_t
*zl3vni
= NULL
;
6621 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6625 zl3vni
->vrf_id
= VRF_UNKNOWN
;
6626 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6630 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
6632 zebra_l3vni_t
*zl3vni
= NULL
;
6636 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6642 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
6648 * Handle message from client to enable/disable advertisement of g/w macip
6651 int zebra_vxlan_advertise_subnet(struct zserv
*client
, u_short length
,
6652 struct zebra_vrf
*zvrf
)
6657 zebra_vni_t
*zvni
= NULL
;
6658 struct interface
*ifp
= NULL
;
6659 struct zebra_if
*zif
= NULL
;
6660 struct zebra_l2info_vxlan zl2_info
;
6661 struct interface
*vlan_if
= NULL
;
6663 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6664 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6670 advertise
= stream_getc(s
);
6671 vni
= stream_get3(s
);
6673 zvni
= zvni_lookup(vni
);
6677 if (zvni
->advertise_subnet
== advertise
)
6680 if (IS_ZEBRA_DEBUG_VXLAN
)
6682 "EVPN subnet Adv %s on VNI %d , currently %s",
6683 advertise
? "enabled" : "disabled", vni
,
6684 zvni
->advertise_subnet
? "enabled" : "disabled");
6687 zvni
->advertise_subnet
= advertise
;
6689 ifp
= zvni
->vxlan_if
;
6695 /* If down or not mapped to a bridge, we're done. */
6696 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6699 zl2_info
= zif
->l2info
.vxl
;
6701 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
6702 zif
->brslave_info
.br_if
);
6706 if (zvni
->advertise_subnet
)
6707 zvni_advertise_subnet(zvni
, vlan_if
, 1);
6709 zvni_advertise_subnet(zvni
, vlan_if
, 0);
6715 * Handle message from client to enable/disable advertisement of g/w macip
6718 int zebra_vxlan_advertise_gw_macip(struct zserv
*client
, u_short length
,
6719 struct zebra_vrf
*zvrf
)
6724 zebra_vni_t
*zvni
= NULL
;
6725 struct interface
*ifp
= NULL
;
6727 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6728 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6734 STREAM_GETC(s
, advertise
);
6735 STREAM_GET(&vni
, s
, 3);
6738 if (IS_ZEBRA_DEBUG_VXLAN
)
6739 zlog_debug("EVPN gateway macip Adv %s, currently %s",
6740 advertise
? "enabled" : "disabled",
6741 advertise_gw_macip_enabled(NULL
)
6745 if (zvrf
->advertise_gw_macip
== advertise
)
6748 zvrf
->advertise_gw_macip
= advertise
;
6750 if (advertise_gw_macip_enabled(zvni
))
6751 hash_iterate(zvrf
->vni_table
,
6752 zvni_gw_macip_add_for_vni_hash
, NULL
);
6754 hash_iterate(zvrf
->vni_table
,
6755 zvni_gw_macip_del_for_vni_hash
, NULL
);
6758 struct zebra_if
*zif
= NULL
;
6759 struct zebra_l2info_vxlan zl2_info
;
6760 struct interface
*vlan_if
= NULL
;
6761 struct interface
*vrr_if
= NULL
;
6763 if (IS_ZEBRA_DEBUG_VXLAN
)
6765 "EVPN gateway macip Adv %s on VNI %d , currently %s",
6766 advertise
? "enabled" : "disabled", vni
,
6767 advertise_gw_macip_enabled(zvni
)
6771 zvni
= zvni_lookup(vni
);
6775 if (zvni
->advertise_gw_macip
== advertise
)
6778 zvni
->advertise_gw_macip
= advertise
;
6780 ifp
= zvni
->vxlan_if
;
6786 /* If down or not mapped to a bridge, we're done. */
6787 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6790 zl2_info
= zif
->l2info
.vxl
;
6792 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
6793 zif
->brslave_info
.br_if
);
6797 if (advertise_gw_macip_enabled(zvni
)) {
6798 /* Add primary SVI MAC-IP */
6799 zvni_add_macip_for_intf(vlan_if
, zvni
);
6801 /* Add VRR MAC-IP - if any*/
6802 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6804 zvni_add_macip_for_intf(vrr_if
, zvni
);
6806 /* Del primary MAC-IP */
6807 zvni_del_macip_for_intf(vlan_if
, zvni
);
6809 /* Del VRR MAC-IP - if any*/
6810 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6812 zvni_del_macip_for_intf(vrr_if
, zvni
);
6822 * Handle message from client to learn (or stop learning) about VNIs and MACs.
6823 * When enabled, the VNI hash table will be built and MAC FDB table read;
6824 * when disabled, the entries should be deleted and remote VTEPs and MACs
6825 * uninstalled from the kernel.
6827 int zebra_vxlan_advertise_all_vni(struct zserv
*client
,
6828 u_short length
, struct zebra_vrf
*zvrf
)
6830 struct stream
*s
= NULL
;
6832 struct zebra_ns
*zns
= NULL
;
6834 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6835 zlog_err("EVPN VNI Adv for non-default VRF %u",
6841 STREAM_GETC(s
, advertise
);
6843 if (IS_ZEBRA_DEBUG_VXLAN
)
6844 zlog_debug("EVPN VNI Adv %s, currently %s",
6845 advertise
? "enabled" : "disabled",
6846 is_evpn_enabled() ? "enabled" : "disabled");
6848 if (zvrf
->advertise_all_vni
== advertise
)
6851 zvrf
->advertise_all_vni
= advertise
;
6852 if (is_evpn_enabled()) {
6853 /* Build VNI hash table and inform BGP. */
6854 zvni_build_hash_table();
6856 /* Add all SVI (L3 GW) MACs to BGP*/
6857 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
6860 /* Read the MAC FDB */
6861 macfdb_read(zvrf
->zns
);
6863 /* Read neighbors */
6864 neigh_read(zvrf
->zns
);
6866 /* Cleanup VTEPs for all VNIs - uninstall from
6867 * kernel and free entries.
6869 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6871 /* cleanup all l3vnis */
6872 zns
= zebra_ns_lookup(NS_DEFAULT
);
6876 hash_iterate(zns
->l3vni_table
, zl3vni_cleanup_all
, NULL
);
6884 * Allocate VNI hash table for this VRF and do other initialization.
6885 * NOTE: Currently supported only for default VRF.
6887 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
6891 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
6892 "Zebra VRF VNI Table");
6895 /* Cleanup VNI info, but don't free the table. */
6896 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
6900 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6903 /* Close all VNI handling */
6904 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
6908 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6909 hash_free(zvrf
->vni_table
);
6912 /* init the l3vni table */
6913 void zebra_vxlan_ns_init(struct zebra_ns
*zns
)
6915 zns
->l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
6916 "Zebra VRF L3 VNI table");
6919 /* free l3vni table */
6920 void zebra_vxlan_ns_disable(struct zebra_ns
*zns
)
6922 hash_free(zns
->l3vni_table
);
6925 /* get the l3vni svi ifindex */
6926 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
6928 zebra_l3vni_t
*zl3vni
= NULL
;
6930 zl3vni
= zl3vni_from_vrf(vrf_id
);
6931 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
6934 return zl3vni
->svi_if
->ifindex
;