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 <linux/neighbour.h>
40 #include "zebra/rib.h"
42 #include "zebra/zebra_ns.h"
43 #include "zebra/zserv.h"
44 #include "zebra/debug.h"
45 #include "zebra/interface.h"
46 #include "zebra/zebra_vrf.h"
47 #include "zebra/rt_netlink.h"
48 #include "zebra/zebra_vxlan_private.h"
49 #include "zebra/zebra_vxlan.h"
50 #include "zebra/zebra_memory.h"
51 #include "zebra/zebra_l2.h"
53 DEFINE_MTYPE_STATIC(ZEBRA
, HOST_PREFIX
, "host prefix");
54 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI
, "VNI hash");
55 DEFINE_MTYPE_STATIC(ZEBRA
, ZL3VNI
, "L3 VNI hash");
56 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI_VTEP
, "VNI remote VTEP");
57 DEFINE_MTYPE_STATIC(ZEBRA
, MAC
, "VNI MAC");
58 DEFINE_MTYPE_STATIC(ZEBRA
, NEIGH
, "VNI Neighbor");
62 /* static function declarations */
63 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
65 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
66 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
);
67 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
69 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
71 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
73 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
);
74 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
);
75 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
);
76 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
77 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[]);
79 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
80 struct ipaddr
*ip
, uint8_t 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 void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
89 struct in_addr
*r_vtep_ip
);
90 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
92 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
);
93 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
94 struct ethaddr
*macaddr
,
96 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
97 struct ethaddr
*macaddr
,
99 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
100 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
101 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
102 struct interface
*br_if
);
103 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
);
105 /* l3-vni next-hop neigh related APIs */
106 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
108 static void *zl3vni_nh_alloc(void *p
);
109 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
110 struct ipaddr
*vtep_ip
,
111 struct ethaddr
*rmac
);
112 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
113 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
114 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
116 /* l3-vni rmac related APIs */
117 static void zl3vni_print_rmac_hash(struct hash_backet
*, void *);
118 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
119 struct ethaddr
*rmac
);
120 static void *zl3vni_rmac_alloc(void *p
);
121 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
122 struct ethaddr
*rmac
);
123 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
124 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
125 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
127 /* l3-vni related APIs*/
128 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
);
129 static void *zl3vni_alloc(void *p
);
130 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
131 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
132 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t
);
133 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
);
134 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
);
135 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
136 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
138 static unsigned int mac_hash_keymake(void *p
);
139 static int mac_cmp(const void *p1
, const void *p2
);
140 static void *zvni_mac_alloc(void *p
);
141 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
142 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
143 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
144 struct in_addr
*r_vtep_ip
);
145 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
147 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
148 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
150 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
152 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
153 struct interface
*br_if
, vlanid_t vid
);
154 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
155 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
);
156 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
);
158 static unsigned int vni_hash_keymake(void *p
);
159 static int vni_hash_cmp(const void *p1
, const void *p2
);
160 static void *zvni_alloc(void *p
);
161 static zebra_vni_t
*zvni_lookup(vni_t vni
);
162 static zebra_vni_t
*zvni_add(vni_t vni
);
163 static int zvni_del(zebra_vni_t
*zvni
);
164 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
165 static int zvni_send_del_to_client(vni_t vni
);
166 static void zvni_build_hash_table();
167 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
168 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
169 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
170 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
171 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
172 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
173 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
174 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
175 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
176 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
177 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
178 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
180 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
181 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
182 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
185 /* Private functions */
186 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
187 const struct host_rb_entry
*hle2
)
189 if (hle1
->p
.family
< hle2
->p
.family
)
192 if (hle1
->p
.family
> hle2
->p
.family
)
195 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
198 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
201 if (hle1
->p
.family
== AF_INET
) {
202 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
205 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
210 zlog_warn("%s: Unexpected family type: %d", __PRETTY_FUNCTION__
,
215 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
217 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
219 struct host_rb_entry
*hle
;
222 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
229 * Return number of valid MACs in a VNI's MAC hash table - all
230 * remote MACs and non-internal (auto) local MACs count.
232 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
235 uint32_t num_macs
= 0;
237 struct hash_backet
*hb
;
240 hash
= zvni
->mac_table
;
243 for (i
= 0; i
< hash
->size
; i
++) {
244 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
245 mac
= (zebra_mac_t
*)hb
->data
;
246 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
247 || CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
248 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
256 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
258 struct zebra_vrf
*zvrf
;
260 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
261 if (zvrf
&& zvrf
->advertise_gw_macip
)
264 if (zvni
&& zvni
->advertise_gw_macip
)
271 * Helper function to determine maximum width of neighbor IP address for
272 * display - just because we're dealing with IPv6 addresses that can
275 static void zvni_find_neigh_addr_width(struct hash_backet
*backet
, void *ctxt
)
278 char buf
[INET6_ADDRSTRLEN
];
279 struct neigh_walk_ctx
*wctx
= ctxt
;
282 n
= (zebra_neigh_t
*)backet
->data
;
286 ipaddr2str(&n
->ip
, buf
, sizeof(buf
)), width
= strlen(buf
);
287 if (width
> wctx
->addr_width
)
288 wctx
->addr_width
= width
;
293 * Print a specific neighbor entry.
295 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
298 char buf1
[ETHER_ADDR_STRLEN
];
299 char buf2
[INET6_ADDRSTRLEN
];
301 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
302 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
303 vty
= (struct vty
*)ctxt
;
305 vty_out(vty
, "IP: %s\n",
306 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
307 vty_out(vty
, " MAC: %s",
308 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
310 json_object_string_add(json
, "ip", buf2
);
311 json_object_string_add(json
, "mac", buf1
);
313 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
315 vty_out(vty
, " Remote VTEP: %s",
316 inet_ntoa(n
->r_vtep_ip
));
318 json_object_string_add(json
, "remoteVtep",
319 inet_ntoa(n
->r_vtep_ip
));
321 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
324 vty_out(vty
, " State: %s",
325 IS_ZEBRA_NEIGH_ACTIVE(n
) ? "Active"
329 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
331 vty_out(vty
, " Default-gateway");
333 json_object_boolean_true_add(json
, "defaultGateway");
335 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
337 vty_out(vty
, " Router");
344 * Print neighbor hash entry - called for display of all neighbors.
346 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
349 json_object
*json_vni
= NULL
, *json_row
= NULL
;
351 char buf1
[ETHER_ADDR_STRLEN
];
352 char buf2
[INET6_ADDRSTRLEN
];
353 struct neigh_walk_ctx
*wctx
= ctxt
;
356 json_vni
= wctx
->json
;
357 n
= (zebra_neigh_t
*)backet
->data
;
362 json_row
= json_object_new_object();
364 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
365 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
366 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)
367 && !(wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)) {
368 if (json_vni
== NULL
) {
369 vty_out(vty
, "%*s %-6s %-17s\n", -wctx
->addr_width
,
370 buf2
, "local", buf1
);
372 json_object_string_add(json_row
, "type", "local");
373 json_object_string_add(json_row
, "mac", buf1
);
377 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) {
378 if (IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
)) {
379 if (json_vni
== NULL
) {
380 if (wctx
->count
== 0)
382 "%*s %-6s %-17s %-21s\n",
385 "MAC", "Remote VTEP");
386 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
387 -wctx
->addr_width
, buf2
,
389 inet_ntoa(n
->r_vtep_ip
));
391 json_object_string_add(json_row
, "type",
393 json_object_string_add(json_row
, "mac",
395 json_object_string_add(
396 json_row
, "remoteVtep",
397 inet_ntoa(n
->r_vtep_ip
));
402 if (json_vni
== NULL
) {
403 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
404 -wctx
->addr_width
, buf2
, "remote", buf1
,
405 inet_ntoa(n
->r_vtep_ip
));
407 json_object_string_add(json_row
, "type",
409 json_object_string_add(json_row
, "mac", buf1
);
410 json_object_string_add(json_row
, "remoteVtep",
411 inet_ntoa(n
->r_vtep_ip
));
418 json_object_object_add(json_vni
, buf2
, json_row
);
422 * Print neighbors for all VNI.
424 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
428 json_object
*json
= NULL
, *json_vni
= NULL
;
431 struct neigh_walk_ctx wctx
;
432 char vni_str
[VNI_STR_LEN
];
434 vty
= (struct vty
*)args
[0];
435 json
= (json_object
*)args
[1];
437 zvni
= (zebra_vni_t
*)backet
->data
;
440 vty_out(vty
, "{}\n");
443 num_neigh
= hashcount(zvni
->neigh_table
);
446 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
447 zvni
->vni
, num_neigh
);
449 json_vni
= json_object_new_object();
450 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
451 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
455 json_object_object_add(json
, vni_str
, json_vni
);
459 /* Since we have IPv6 addresses to deal with which can vary widely in
460 * size, we try to be a bit more elegant in display by first computing
463 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
466 wctx
.addr_width
= 15;
467 wctx
.json
= json_vni
;
468 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
471 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
472 "Type", "MAC", "Remote VTEP");
474 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
477 json_object_object_add(json
, vni_str
, json_vni
);
480 /* print a specific next hop for an l3vni */
481 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
484 char buf1
[ETHER_ADDR_STRLEN
];
485 char buf2
[INET6_ADDRSTRLEN
];
486 json_object
*json_hosts
= NULL
;
487 struct host_rb_entry
*hle
;
490 vty_out(vty
, "Ip: %s\n",
491 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
492 vty_out(vty
, " RMAC: %s\n",
493 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
494 vty_out(vty
, " Refcount: %d\n",
495 rb_host_count(&n
->host_rb
));
496 vty_out(vty
, " Prefixes:\n");
497 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
498 vty_out(vty
, " %s\n",
499 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
501 json_hosts
= json_object_new_array();
502 json_object_string_add(
503 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
504 json_object_string_add(
506 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
507 json_object_int_add(json
, "refCount",
508 rb_host_count(&n
->host_rb
));
509 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
510 json_object_array_add(json_hosts
,
511 json_object_new_string(prefix2str(
512 &hle
->p
, buf2
, sizeof(buf2
))));
513 json_object_object_add(json
, "prefixList", json_hosts
);
517 /* Print a specific RMAC entry */
518 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
521 char buf1
[ETHER_ADDR_STRLEN
];
522 char buf2
[PREFIX_STRLEN
];
523 json_object
*json_hosts
= NULL
;
524 struct host_rb_entry
*hle
;
527 vty_out(vty
, "MAC: %s\n",
528 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
529 vty_out(vty
, " Remote VTEP: %s\n",
530 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
531 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
532 vty_out(vty
, " Prefixes:\n");
533 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
534 vty_out(vty
, " %s\n",
535 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
537 json_hosts
= json_object_new_array();
538 json_object_string_add(
540 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
541 json_object_string_add(json
, "vtepIp",
542 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
543 json_object_int_add(json
, "refCount",
544 rb_host_count(&zrmac
->host_rb
));
545 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
546 json_object_array_add(
548 json_object_new_string(prefix2str(
549 &hle
->p
, buf2
, sizeof(buf2
))));
550 json_object_object_add(json
, "prefixList", json_hosts
);
555 * Print a specific MAC entry.
557 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
)
560 zebra_neigh_t
*n
= NULL
;
561 struct listnode
*node
= NULL
;
563 char buf2
[INET6_ADDRSTRLEN
];
565 vty
= (struct vty
*)ctxt
;
566 vty_out(vty
, "MAC: %s",
567 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
)));
568 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
569 struct zebra_ns
*zns
;
570 struct interface
*ifp
;
573 ifindex
= mac
->fwd_info
.local
.ifindex
;
574 zns
= zebra_ns_lookup(NS_DEFAULT
);
575 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
576 if (!ifp
) // unexpected
578 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
579 if (mac
->fwd_info
.local
.vid
)
580 vty_out(vty
, " VLAN: %u", mac
->fwd_info
.local
.vid
);
581 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
582 vty_out(vty
, " Remote VTEP: %s",
583 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
584 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
585 vty_out(vty
, " Auto Mac ");
588 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
589 vty_out(vty
, " Sticky Mac ");
591 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
592 vty_out(vty
, " Default-gateway Mac ");
594 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
595 vty_out(vty
, " Remote-gateway Mac ");
598 /* print all the associated neigh */
599 vty_out(vty
, " Neighbors:\n");
600 if (!listcount(mac
->neigh_list
))
601 vty_out(vty
, " No Neighbors\n");
603 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
604 vty_out(vty
, " %s %s\n",
605 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
606 CHECK_FLAG(n
->flags
, ZEBRA_MAC_LOCAL
)
607 ? (IS_ZEBRA_NEIGH_ACTIVE(n
)
618 * Print MAC hash entry - called for display of all MACs.
620 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
623 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
626 struct mac_walk_ctx
*wctx
= ctxt
;
629 json_mac_hdr
= wctx
->json
;
630 mac
= (zebra_mac_t
*)backet
->data
;
634 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
637 json_mac
= json_object_new_object();
639 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
640 && !(wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)) {
641 struct zebra_ns
*zns
;
643 struct interface
*ifp
;
646 zns
= zebra_ns_lookup(NS_DEFAULT
);
647 ifindex
= mac
->fwd_info
.local
.ifindex
;
648 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
649 if (!ifp
) // unexpected
651 vid
= mac
->fwd_info
.local
.vid
;
652 if (json_mac_hdr
== NULL
)
653 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
656 json_object_string_add(json_mac
, "type", "local");
657 json_object_string_add(json_mac
, "intf", ifp
->name
);
660 if (json_mac_hdr
== NULL
)
661 vty_out(vty
, " %-5u", vid
);
663 json_object_int_add(json_mac
, "vlan", vid
);
665 if (json_mac_hdr
== NULL
)
668 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
670 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
671 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) {
672 if (IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
674 if (wctx
->count
== 0) {
675 if (json_mac_hdr
== NULL
) {
676 vty_out(vty
, "\nVNI %u\n\n",
679 "%-17s %-6s %-21s %-5s\n",
685 if (json_mac_hdr
== NULL
)
686 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
688 inet_ntoa(mac
->fwd_info
691 json_object_string_add(json_mac
, "type",
693 json_object_string_add(
694 json_mac
, "remoteVtep",
695 inet_ntoa(mac
->fwd_info
697 json_object_object_add(json_mac_hdr
,
703 if (json_mac_hdr
== NULL
)
704 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
706 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
708 json_object_string_add(json_mac
, "type",
710 json_object_string_add(
711 json_mac
, "remoteVtep",
712 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
713 json_object_object_add(json_mac_hdr
, buf1
,
722 * Print MACs for all VNI.
724 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
727 json_object
*json
= NULL
, *json_vni
= NULL
;
728 json_object
*json_mac
= NULL
;
731 struct mac_walk_ctx
*wctx
= ctxt
;
732 char vni_str
[VNI_STR_LEN
];
734 vty
= (struct vty
*)wctx
->vty
;
735 json
= (struct json_object
*)wctx
->json
;
737 zvni
= (zebra_vni_t
*)backet
->data
;
740 vty_out(vty
, "{}\n");
745 /*We are iterating over a new VNI, set the count to 0*/
748 num_macs
= num_valid_macs(zvni
);
753 json_vni
= json_object_new_object();
754 json_mac
= json_object_new_object();
755 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
758 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
760 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
761 zvni
->vni
, num_macs
);
762 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
763 "Intf/Remote VTEP", "VLAN");
765 json_object_int_add(json_vni
, "numMacs", num_macs
);
767 /* assign per-vni to wctx->json object to fill macs
768 * under the vni. Re-assign primary json object to fill
769 * next vni information.
771 wctx
->json
= json_mac
;
772 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
776 json_object_object_add(json_vni
, "macs", json_mac
);
777 json_object_object_add(json
, vni_str
, json_vni
);
781 static void zl3vni_print_nh_hash(struct hash_backet
*backet
, void *ctx
)
783 struct nh_walk_ctx
*wctx
= NULL
;
784 struct vty
*vty
= NULL
;
785 struct json_object
*json_vni
= NULL
;
786 struct json_object
*json_nh
= NULL
;
787 zebra_neigh_t
*n
= NULL
;
788 char buf1
[ETHER_ADDR_STRLEN
];
789 char buf2
[INET6_ADDRSTRLEN
];
791 wctx
= (struct nh_walk_ctx
*)ctx
;
793 json_vni
= wctx
->json
;
795 json_nh
= json_object_new_object();
796 n
= (zebra_neigh_t
*)backet
->data
;
801 vty_out(vty
, "%-15s %-17s\n",
802 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
803 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
805 json_object_string_add(json_nh
, "nexthopIp",
806 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
807 json_object_string_add(
808 json_nh
, "routerMac",
809 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
810 json_object_object_add(json_vni
,
811 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
816 static void zl3vni_print_nh_hash_all_vni(struct hash_backet
*backet
,
819 struct vty
*vty
= NULL
;
820 json_object
*json
= NULL
;
821 json_object
*json_vni
= NULL
;
822 zebra_l3vni_t
*zl3vni
= NULL
;
824 struct nh_walk_ctx wctx
;
825 char vni_str
[VNI_STR_LEN
];
827 vty
= (struct vty
*)args
[0];
828 json
= (struct json_object
*)args
[1];
830 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
833 vty_out(vty
, "{}\n");
837 num_nh
= hashcount(zl3vni
->nh_table
);
842 json_vni
= json_object_new_object();
843 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
847 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
848 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
850 json_object_int_add(json_vni
, "numNextHops", num_nh
);
852 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
854 wctx
.json
= json_vni
;
855 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
857 json_object_object_add(json
, vni_str
, json_vni
);
860 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet
*backet
,
863 struct vty
*vty
= NULL
;
864 json_object
*json
= NULL
;
865 json_object
*json_vni
= NULL
;
866 zebra_l3vni_t
*zl3vni
= NULL
;
868 struct rmac_walk_ctx wctx
;
869 char vni_str
[VNI_STR_LEN
];
871 vty
= (struct vty
*)args
[0];
872 json
= (struct json_object
*)args
[1];
874 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
877 vty_out(vty
, "{}\n");
881 num_rmacs
= hashcount(zl3vni
->rmac_table
);
886 json_vni
= json_object_new_object();
887 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
891 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
892 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
894 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
896 /* assign per-vni to wctx->json object to fill macs
897 * under the vni. Re-assign primary json object to fill
898 * next vni information.
900 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
902 wctx
.json
= json_vni
;
903 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
905 json_object_object_add(json
, vni_str
, json_vni
);
908 static void zl3vni_print_rmac_hash(struct hash_backet
*backet
, void *ctx
)
910 zebra_mac_t
*zrmac
= NULL
;
911 struct rmac_walk_ctx
*wctx
= NULL
;
912 struct vty
*vty
= NULL
;
913 struct json_object
*json
= NULL
;
914 struct json_object
*json_rmac
= NULL
;
915 char buf
[ETHER_ADDR_STRLEN
];
917 wctx
= (struct rmac_walk_ctx
*)ctx
;
921 json_rmac
= json_object_new_object();
922 zrmac
= (zebra_mac_t
*)backet
->data
;
927 vty_out(vty
, "%-17s %-21s\n",
928 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
929 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
931 json_object_string_add(
932 json_rmac
, "routerMac",
933 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
934 json_object_string_add(json_rmac
, "vtepIp",
935 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
936 json_object_object_add(
937 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
942 /* print a specific L3 VNI entry */
943 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
945 char buf
[ETHER_ADDR_STRLEN
];
946 struct vty
*vty
= NULL
;
947 json_object
*json
= NULL
;
948 zebra_vni_t
*zvni
= NULL
;
949 json_object
*json_vni_list
= NULL
;
950 struct listnode
*node
= NULL
, *nnode
= NULL
;
956 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
957 vty_out(vty
, " Type: %s\n", "L3");
958 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
959 vty_out(vty
, " Local Vtep Ip: %s\n",
960 inet_ntoa(zl3vni
->local_vtep_ip
));
961 vty_out(vty
, " Vxlan-Intf: %s\n",
962 zl3vni_vxlan_if_name(zl3vni
));
963 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
964 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
965 vty_out(vty
, " VNI Filter: %s\n",
966 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
967 ? "prefix-routes-only"
969 vty_out(vty
, " Router MAC: %s\n",
970 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
971 vty_out(vty
, " L2 VNIs: ");
972 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
973 vty_out(vty
, "%u ", zvni
->vni
);
976 json_vni_list
= json_object_new_array();
977 json_object_int_add(json
, "vni", zl3vni
->vni
);
978 json_object_string_add(json
, "type", "L3");
979 json_object_string_add(json
, "localVtepIp",
980 inet_ntoa(zl3vni
->local_vtep_ip
));
981 json_object_string_add(json
, "vxlanIntf",
982 zl3vni_vxlan_if_name(zl3vni
));
983 json_object_string_add(json
, "sviIntf",
984 zl3vni_svi_if_name(zl3vni
));
985 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
986 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
987 json_object_string_add(
989 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
990 json_object_string_add(
992 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
993 ? "prefix-routes-only"
995 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
996 json_object_array_add(json_vni_list
,
997 json_object_new_int(zvni
->vni
));
999 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1004 * Print a specific VNI entry.
1006 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1009 zebra_vtep_t
*zvtep
;
1012 json_object
*json
= NULL
;
1013 json_object
*json_vtep_list
= NULL
;
1014 json_object
*json_ip_str
= NULL
;
1020 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1021 vty_out(vty
, " Type: %s\n", "L2");
1022 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1024 json_object_int_add(json
, "vni", zvni
->vni
);
1025 json_object_string_add(json
, "type", "L2");
1026 json_object_string_add(json
, "vrf",
1027 vrf_id_to_name(zvni
->vrf_id
));
1030 if (!zvni
->vxlan_if
) { // unexpected
1032 vty_out(vty
, " VxLAN interface: unknown\n");
1035 num_macs
= num_valid_macs(zvni
);
1036 num_neigh
= hashcount(zvni
->neigh_table
);
1038 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1039 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1040 vty_out(vty
, " Local VTEP IP: %s\n",
1041 inet_ntoa(zvni
->local_vtep_ip
));
1043 json_object_string_add(json
, "vxlanInterface",
1044 zvni
->vxlan_if
->name
);
1045 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1046 json_object_string_add(json
, "vtepIp",
1047 inet_ntoa(zvni
->local_vtep_ip
));
1048 json_object_string_add(json
, "advertiseGatewayMacip",
1049 zvni
->advertise_gw_macip
? "Yes" : "No");
1050 json_object_int_add(json
, "numMacs", num_macs
);
1051 json_object_int_add(json
, "numArpNd", num_neigh
);
1055 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1058 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1060 json_vtep_list
= json_object_new_array();
1061 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1063 vty_out(vty
, " %s\n",
1064 inet_ntoa(zvtep
->vtep_ip
));
1066 json_ip_str
= json_object_new_string(
1067 inet_ntoa(zvtep
->vtep_ip
));
1068 json_object_array_add(json_vtep_list
,
1073 json_object_object_add(json
, "numRemoteVteps",
1078 " Number of MACs (local and remote) known for this VNI: %u\n",
1081 " Number of ARPs (IPv4 and IPv6, local and remote) "
1082 "known for this VNI: %u\n",
1084 vty_out(vty
, " Advertise-gw-macip: %s\n",
1085 zvni
->advertise_gw_macip
? "Yes" : "No");
1089 /* print a L3 VNI hash entry */
1090 static void zl3vni_print_hash(struct hash_backet
*backet
, void *ctx
[])
1092 struct vty
*vty
= NULL
;
1093 json_object
*json
= NULL
;
1094 json_object
*json_vni
= NULL
;
1095 zebra_l3vni_t
*zl3vni
= NULL
;
1097 vty
= (struct vty
*)ctx
[0];
1098 json
= (json_object
*)ctx
[1];
1100 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1105 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1106 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1107 hashcount(zl3vni
->rmac_table
),
1108 hashcount(zl3vni
->nh_table
), "n/a",
1109 zl3vni_vrf_name(zl3vni
));
1111 char vni_str
[VNI_STR_LEN
];
1113 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1114 json_vni
= json_object_new_object();
1115 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1116 json_object_string_add(json_vni
, "vxlanIf",
1117 zl3vni_vxlan_if_name(zl3vni
));
1118 json_object_int_add(json_vni
, "numMacs",
1119 hashcount(zl3vni
->rmac_table
));
1120 json_object_int_add(json_vni
, "numArpNd",
1121 hashcount(zl3vni
->nh_table
));
1122 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1123 json_object_string_add(json_vni
, "type", "L3");
1124 json_object_string_add(json_vni
, "tenantVrf",
1125 zl3vni_vrf_name(zl3vni
));
1126 json_object_object_add(json
, vni_str
, json_vni
);
1131 * Print a VNI hash entry - called for display of all VNIs.
1133 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1137 zebra_vtep_t
*zvtep
;
1138 uint32_t num_vteps
= 0;
1139 uint32_t num_macs
= 0;
1140 uint32_t num_neigh
= 0;
1141 json_object
*json
= NULL
;
1142 json_object
*json_vni
= NULL
;
1143 json_object
*json_ip_str
= NULL
;
1144 json_object
*json_vtep_list
= NULL
;
1149 zvni
= (zebra_vni_t
*)backet
->data
;
1153 zvtep
= zvni
->vteps
;
1156 zvtep
= zvtep
->next
;
1159 num_macs
= num_valid_macs(zvni
);
1160 num_neigh
= hashcount(zvni
->neigh_table
);
1162 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1164 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1165 num_macs
, num_neigh
, num_vteps
,
1166 vrf_id_to_name(zvni
->vrf_id
));
1168 char vni_str
[VNI_STR_LEN
];
1169 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1170 json_vni
= json_object_new_object();
1171 json_object_int_add(json_vni
, "vni", zvni
->vni
);
1172 json_object_string_add(json_vni
, "type", "L2");
1173 json_object_string_add(json_vni
, "vxlanIf",
1174 zvni
->vxlan_if
? zvni
->vxlan_if
->name
1176 json_object_int_add(json_vni
, "numMacs", num_macs
);
1177 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1178 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
1179 json_object_string_add(json_vni
, "tenantVrf",
1180 vrf_id_to_name(zvni
->vrf_id
));
1182 json_vtep_list
= json_object_new_array();
1183 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1184 json_ip_str
= json_object_new_string(
1185 inet_ntoa(zvtep
->vtep_ip
));
1186 json_object_array_add(json_vtep_list
,
1189 json_object_object_add(json_vni
, "remoteVteps",
1192 json_object_object_add(json
, vni_str
, json_vni
);
1197 * Inform BGP about local MACIP.
1199 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
1200 struct ipaddr
*ip
, uint8_t flags
,
1203 char buf
[ETHER_ADDR_STRLEN
];
1204 char buf2
[INET6_ADDRSTRLEN
];
1206 struct zserv
*client
= NULL
;
1207 struct stream
*s
= NULL
;
1209 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
1210 /* BGP may not be running. */
1214 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
1216 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
1217 stream_putl(s
, vni
);
1218 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
1221 if (IS_IPADDR_V4(ip
))
1222 ipa_len
= IPV4_MAX_BYTELEN
;
1223 else if (IS_IPADDR_V6(ip
))
1224 ipa_len
= IPV6_MAX_BYTELEN
;
1226 stream_putl(s
, ipa_len
); /* IP address length */
1228 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
1230 stream_putl(s
, 0); /* Just MAC. */
1232 stream_putc(s
, flags
); /* sticky mac/gateway mac */
1235 /* Write packet size. */
1236 stream_putw_at(s
, 0, stream_get_endp(s
));
1238 if (IS_ZEBRA_DEBUG_VXLAN
)
1240 "Send MACIP %s flags 0x%x MAC %s IP %s L2-VNI %u to %s",
1241 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
1242 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1243 ipaddr2str(ip
, buf2
, sizeof(buf2
)), vni
,
1244 zebra_route_string(client
->proto
));
1246 if (cmd
== ZEBRA_MACIP_ADD
)
1247 client
->macipadd_cnt
++;
1249 client
->macipdel_cnt
++;
1251 return zserv_send_message(client
, s
);
1255 * Make hash key for neighbors.
1257 static unsigned int neigh_hash_keymake(void *p
)
1259 zebra_neigh_t
*n
= p
;
1260 struct ipaddr
*ip
= &n
->ip
;
1262 if (IS_IPADDR_V4(ip
))
1263 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
1265 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
1266 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
1270 * Compare two neighbor hash structures.
1272 static int neigh_cmp(const void *p1
, const void *p2
)
1274 const zebra_neigh_t
*n1
= p1
;
1275 const zebra_neigh_t
*n2
= p2
;
1277 if (n1
== NULL
&& n2
== NULL
)
1280 if (n1
== NULL
|| n2
== NULL
)
1283 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
1287 * Callback to allocate neighbor hash entry.
1289 static void *zvni_neigh_alloc(void *p
)
1291 const zebra_neigh_t
*tmp_n
= p
;
1294 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
1301 * Add neighbor entry.
1303 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
1304 struct ethaddr
*mac
)
1306 zebra_neigh_t tmp_n
;
1307 zebra_neigh_t
*n
= NULL
;
1308 zebra_mac_t
*zmac
= NULL
;
1310 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
1311 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1312 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
1315 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1316 n
->state
= ZEBRA_NEIGH_INACTIVE
;
1318 /* Associate the neigh to mac */
1319 zmac
= zvni_mac_lookup(zvni
, mac
);
1321 listnode_add_sort(zmac
->neigh_list
, n
);
1327 * Delete neighbor entry.
1329 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1331 zebra_neigh_t
*tmp_n
;
1332 zebra_mac_t
*zmac
= NULL
;
1334 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
1336 listnode_delete(zmac
->neigh_list
, n
);
1338 /* Free the VNI hash entry and allocated memory. */
1339 tmp_n
= hash_release(zvni
->neigh_table
, n
);
1341 XFREE(MTYPE_NEIGH
, tmp_n
);
1347 * Free neighbor hash entry (callback)
1349 static void zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
1351 struct neigh_walk_ctx
*wctx
= arg
;
1352 zebra_neigh_t
*n
= backet
->data
;
1354 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1355 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
1356 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
1357 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
1358 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
1359 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
1360 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1361 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
1364 if (wctx
->uninstall
)
1365 zvni_neigh_uninstall(wctx
->zvni
, n
);
1367 zvni_neigh_del(wctx
->zvni
, n
);
1374 * Delete all neighbor entries from specific VTEP for a particular VNI.
1376 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
1377 struct in_addr
*r_vtep_ip
)
1379 struct neigh_walk_ctx wctx
;
1381 if (!zvni
->neigh_table
)
1384 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1386 wctx
.uninstall
= uninstall
;
1387 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
1388 wctx
.r_vtep_ip
= *r_vtep_ip
;
1390 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1394 * Delete all neighbor entries for this VNI.
1396 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
1399 struct neigh_walk_ctx wctx
;
1401 if (!zvni
->neigh_table
)
1404 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1406 wctx
.uninstall
= uninstall
;
1407 wctx
.upd_client
= upd_client
;
1410 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1414 * Look up neighbor hash entry.
1416 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
1421 memset(&tmp
, 0, sizeof(tmp
));
1422 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
1423 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
1428 /* Process all neigh associated to a mac upon local mac add event */
1429 static void zvni_process_neigh_on_local_mac_add(zebra_vni_t
*zvni
,
1432 zebra_neigh_t
*n
= NULL
;
1433 struct listnode
*node
= NULL
;
1434 char buf
[ETHER_ADDR_STRLEN
];
1435 char buf2
[INET6_ADDRSTRLEN
];
1437 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1438 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1439 /* MAC is learnt locally, program all inactive neigh
1440 * pointing to this mac */
1441 if (IS_ZEBRA_NEIGH_INACTIVE(n
)) {
1442 if (IS_ZEBRA_DEBUG_VXLAN
)
1444 "neigh %s (MAC %s) on L2-VNI %u is now ACTIVE",
1445 ipaddr2str(&n
->ip
, buf2
,
1447 prefix_mac2str(&n
->emac
, buf
,
1451 ZEBRA_NEIGH_SET_ACTIVE(n
);
1452 zvni_neigh_send_add_to_client(
1453 zvni
->vni
, &n
->ip
, &n
->emac
, n
->flags
);
1455 if (IS_ZEBRA_DEBUG_VXLAN
)
1457 "neigh %s (MAC %s) on VNI %u should NOT be ACTIVE",
1458 ipaddr2str(&n
->ip
, buf2
,
1460 prefix_mac2str(&n
->emac
, buf
,
1464 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1465 /* TODO: assume the neigh has moved too ?? */
1470 /* Process all neigh associated to a mac upon local mac del event */
1471 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
1474 zebra_neigh_t
*n
= NULL
;
1475 struct listnode
*node
= NULL
;
1476 char buf
[ETHER_ADDR_STRLEN
];
1477 char buf2
[INET6_ADDRSTRLEN
];
1479 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1480 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1481 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1482 if (IS_ZEBRA_DEBUG_VXLAN
)
1484 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1485 ipaddr2str(&n
->ip
, buf2
,
1487 prefix_mac2str(&n
->emac
, buf
,
1491 ZEBRA_NEIGH_SET_INACTIVE(n
);
1492 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1495 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1496 if (IS_ZEBRA_DEBUG_VXLAN
)
1498 "local MAC %s getting deleted on VNI %u has remote neigh %s",
1499 prefix_mac2str(&n
->emac
, buf
,
1502 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1507 /* process all neigh associated to a mac entry upon remote mac add */
1508 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
1511 zebra_neigh_t
*n
= NULL
;
1512 struct listnode
*node
= NULL
;
1513 char buf
[ETHER_ADDR_STRLEN
];
1514 char buf2
[INET6_ADDRSTRLEN
];
1516 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1517 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1518 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1519 if (IS_ZEBRA_DEBUG_VXLAN
)
1521 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1522 ipaddr2str(&n
->ip
, buf2
,
1524 prefix_mac2str(&n
->emac
, buf
,
1528 ZEBRA_NEIGH_SET_INACTIVE(n
);
1529 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1536 /* process all neigh associated to mac entry upon remote mac del */
1537 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
1540 zebra_neigh_t
*n
= NULL
;
1541 struct listnode
*node
= NULL
;
1542 char buf
[ETHER_ADDR_STRLEN
];
1543 char buf2
[INET6_ADDRSTRLEN
];
1545 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1546 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1547 if (IS_ZEBRA_DEBUG_VXLAN
)
1549 "remote MAC %s getting deleted on VNI %u has local neigh %s",
1550 prefix_mac2str(&n
->emac
, buf
,
1553 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1559 * Inform BGP about local neighbor addition.
1561 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
1562 struct ethaddr
*macaddr
,
1563 uint8_t neigh_flags
)
1567 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
1568 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
1569 /* Set router flag (R-bit) based on local neigh entry add */
1570 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
1571 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
1573 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1578 * Inform BGP about local neighbor deletion.
1580 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
1581 struct ethaddr
*macaddr
, uint8_t flags
)
1583 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1588 * Install remote neighbor into the kernel.
1590 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1592 struct zebra_if
*zif
;
1593 struct zebra_l2info_vxlan
*vxl
;
1594 struct interface
*vlan_if
;
1598 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1601 zif
= zvni
->vxlan_if
->info
;
1604 vxl
= &zif
->l2info
.vxl
;
1606 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1610 flags
= NTF_EXT_LEARNED
;
1611 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
1612 flags
|= NTF_ROUTER
;
1613 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
1619 * Uninstall remote neighbor from the kernel.
1621 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1623 struct zebra_if
*zif
;
1624 struct zebra_l2info_vxlan
*vxl
;
1625 struct interface
*vlan_if
;
1627 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1630 if (!zvni
->vxlan_if
) {
1631 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
1636 zif
= zvni
->vxlan_if
->info
;
1639 vxl
= &zif
->l2info
.vxl
;
1640 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1644 return kernel_del_neigh(vlan_if
, &n
->ip
);
1648 * Install neighbor hash entry - called upon access VLAN change.
1650 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
1653 struct neigh_walk_ctx
*wctx
= ctxt
;
1655 n
= (zebra_neigh_t
*)backet
->data
;
1659 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
1660 zvni_neigh_install(wctx
->zvni
, n
);
1663 /* Get the VRR interface for SVI if any */
1664 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
1666 struct zebra_vrf
*zvrf
= NULL
;
1667 struct interface
*tmp_if
= NULL
;
1668 struct zebra_if
*zif
= NULL
;
1670 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1673 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
1678 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
1681 if (zif
->link
== ifp
)
1688 static int zvni_del_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_del(ifp
, zvni
, &ip
);
1721 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1723 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1724 struct connected
*c
= NULL
;
1725 struct ethaddr macaddr
;
1727 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1729 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1732 memset(&ip
, 0, sizeof(struct ipaddr
));
1733 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1736 if (c
->address
->family
== AF_INET
) {
1737 ip
.ipa_type
= IPADDR_V4
;
1738 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1739 sizeof(struct in_addr
));
1740 } else if (c
->address
->family
== AF_INET6
) {
1741 ip
.ipa_type
= IPADDR_V6
;
1742 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1743 sizeof(struct in6_addr
));
1748 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
1754 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
1757 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1758 struct connected
*c
= NULL
;
1759 struct ethaddr macaddr
;
1761 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1763 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1766 memcpy(&p
, c
->address
, sizeof(struct prefix
));
1768 /* skip link local address */
1769 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
1774 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1775 ZEBRA_IP_PREFIX_ROUTE_ADD
);
1777 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1778 ZEBRA_IP_PREFIX_ROUTE_DEL
);
1784 * zvni_gw_macip_add_to_client
1786 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
1787 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
1789 char buf
[ETHER_ADDR_STRLEN
];
1790 char buf2
[INET6_ADDRSTRLEN
];
1791 zebra_neigh_t
*n
= NULL
;
1792 zebra_mac_t
*mac
= NULL
;
1793 struct zebra_if
*zif
= NULL
;
1794 struct zebra_l2info_vxlan
*vxl
= NULL
;
1796 zif
= zvni
->vxlan_if
->info
;
1800 vxl
= &zif
->l2info
.vxl
;
1802 mac
= zvni_mac_lookup(zvni
, macaddr
);
1804 mac
= zvni_mac_add(zvni
, macaddr
);
1806 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
1807 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1808 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
1813 /* Set "local" forwarding info. */
1814 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
1815 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
1816 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
1817 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
1818 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
1819 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
1821 n
= zvni_neigh_lookup(zvni
, ip
);
1823 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
1826 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1827 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
1828 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1829 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
1834 /* Set "local" forwarding info. */
1835 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
1836 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
1837 /* Set Router flag (R-bit) */
1838 if (ip
->ipa_type
== IPADDR_V6
)
1839 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
1840 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
1841 n
->ifindex
= ifp
->ifindex
;
1843 /* Only advertise in BGP if the knob is enabled */
1844 if (!advertise_gw_macip_enabled(zvni
))
1847 if (IS_ZEBRA_DEBUG_VXLAN
)
1849 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
1850 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1851 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1852 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
1854 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, n
->flags
);
1860 * zvni_gw_macip_del_from_client
1862 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
1865 char buf1
[ETHER_ADDR_STRLEN
];
1866 char buf2
[INET6_ADDRSTRLEN
];
1867 zebra_neigh_t
*n
= NULL
;
1868 zebra_mac_t
*mac
= NULL
;
1870 /* If the neigh entry is not present nothing to do*/
1871 n
= zvni_neigh_lookup(zvni
, ip
);
1875 /* mac entry should be present */
1876 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
1878 zlog_err("MAC %s doesnt exists for neigh %s on VNI %u",
1879 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
1880 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1884 /* If the entry is not local nothing to do*/
1885 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
1888 /* only need to delete the entry from bgp if we sent it before */
1889 if (IS_ZEBRA_DEBUG_VXLAN
)
1891 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
1892 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1893 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
1894 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1896 /* Remove neighbor from BGP. */
1897 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
1898 ZEBRA_MACIP_TYPE_GW
);
1900 /* Delete this neighbor entry. */
1901 zvni_neigh_del(zvni
, n
);
1903 /* see if the mac needs to be deleted as well*/
1905 zvni_deref_ip2mac(zvni
, mac
, 0);
1910 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
1913 zebra_vni_t
*zvni
= NULL
;
1914 struct zebra_if
*zif
= NULL
;
1915 struct zebra_l2info_vxlan zl2_info
;
1916 struct interface
*vlan_if
= NULL
;
1917 struct interface
*vrr_if
= NULL
;
1918 struct interface
*ifp
;
1920 /* Add primary SVI MAC*/
1921 zvni
= (zebra_vni_t
*)backet
->data
;
1925 ifp
= zvni
->vxlan_if
;
1930 /* If down or not mapped to a bridge, we're done. */
1931 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1934 zl2_info
= zif
->l2info
.vxl
;
1937 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1941 /* Del primary MAC-IP */
1942 zvni_del_macip_for_intf(vlan_if
, zvni
);
1944 /* Del VRR MAC-IP - if any*/
1945 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1947 zvni_del_macip_for_intf(vrr_if
, zvni
);
1952 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
1955 zebra_vni_t
*zvni
= NULL
;
1956 struct zebra_if
*zif
= NULL
;
1957 struct zebra_l2info_vxlan zl2_info
;
1958 struct interface
*vlan_if
= NULL
;
1959 struct interface
*vrr_if
= NULL
;
1960 struct interface
*ifp
= NULL
;
1962 zvni
= (zebra_vni_t
*)backet
->data
;
1966 ifp
= zvni
->vxlan_if
;
1971 /* If down or not mapped to a bridge, we're done. */
1972 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1974 zl2_info
= zif
->l2info
.vxl
;
1977 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1981 /* Add primary SVI MAC-IP */
1982 zvni_add_macip_for_intf(vlan_if
, zvni
);
1984 /* Add VRR MAC-IP - if any*/
1985 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1987 zvni_add_macip_for_intf(vrr_if
, zvni
);
1992 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
1993 struct interface
*ifp
,
1995 struct ethaddr
*macaddr
,
1996 uint8_t router_flag
)
1998 char buf
[ETHER_ADDR_STRLEN
];
1999 char buf2
[INET6_ADDRSTRLEN
];
2000 zebra_neigh_t
*n
= NULL
;
2001 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2003 /* create a dummy MAC if the MAC is not already present */
2004 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2006 if (IS_ZEBRA_DEBUG_VXLAN
)
2008 "AUTO MAC %s created for neigh %s on VNI %u",
2009 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2010 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2012 zmac
= zvni_mac_add(zvni
, macaddr
);
2014 zlog_warn("Failed to add MAC %s VNI %u",
2015 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2020 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
2021 memset(&zmac
->flags
, 0, sizeof(uint32_t));
2022 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2025 /* If same entry already exists, it might be a change or it might be a
2026 * move from remote to local.
2028 n
= zvni_neigh_lookup(zvni
, ip
);
2030 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2031 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2033 /* Update any params and return - client doesn't
2034 * care about a purely local change.
2036 n
->ifindex
= ifp
->ifindex
;
2040 /* If the MAC has changed,
2041 * need to issue a delete first
2042 * as this means a different MACIP route.
2043 * Also, need to do some unlinking/relinking.
2045 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2047 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2049 listnode_delete(old_zmac
->neigh_list
, n
);
2050 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
2053 /* Update the forwarding info. */
2054 n
->ifindex
= ifp
->ifindex
;
2055 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2057 /* Link to new MAC */
2058 listnode_add_sort(zmac
->neigh_list
, n
);
2061 /* Neighbor has moved from remote to local. */
2063 /* If MAC has changed, do the unlink/link */
2064 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2066 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2068 listnode_delete(old_zmac
->neigh_list
,
2070 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
2073 /* Link to new MAC */
2074 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2075 listnode_add_sort(zmac
->neigh_list
, n
);
2078 /* Mark appropriately */
2079 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2080 n
->r_vtep_ip
.s_addr
= 0;
2081 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2082 n
->ifindex
= ifp
->ifindex
;
2085 /* New neighbor - create */
2086 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2089 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2090 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2091 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2092 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2095 /* Set "local" forwarding info. */
2096 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2097 n
->ifindex
= ifp
->ifindex
;
2100 /* Before we program this in BGP, we need to check if MAC is locally
2103 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
2104 if (IS_ZEBRA_DEBUG_VXLAN
)
2106 "Skipping neigh %s add to client as MAC %s is not local on VNI %u",
2107 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2108 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2114 /*Set router flag (R-bit) */
2116 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2119 if (IS_ZEBRA_DEBUG_VXLAN
)
2120 zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u with flags 0x%x",
2121 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2122 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2123 zvni
->vni
, n
->flags
);
2124 ZEBRA_NEIGH_SET_ACTIVE(n
);
2126 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, n
->flags
);
2129 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
2130 struct interface
*ifp
,
2132 struct ethaddr
*macaddr
,
2135 char buf
[ETHER_ADDR_STRLEN
];
2136 char buf2
[INET6_ADDRSTRLEN
];
2137 zebra_neigh_t
*n
= NULL
;
2138 zebra_mac_t
*zmac
= NULL
;
2140 /* If the neighbor is unknown, there is no further action. */
2141 n
= zvni_neigh_lookup(zvni
, ip
);
2145 /* If a remote entry, see if it needs to be refreshed */
2146 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2148 if (state
& NUD_STALE
)
2149 zvni_neigh_install(zvni
, n
);
2152 /* We got a "remote" neighbor notification for an entry
2153 * we think is local. This can happen in a multihoming
2154 * scenario - but only if the MAC is already "remote".
2155 * Just mark our entry as "remote".
2157 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2158 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2159 zlog_err("Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
2160 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
2161 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2166 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2167 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2168 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
2175 * Make hash key for MAC.
2177 static unsigned int mac_hash_keymake(void *p
)
2179 zebra_mac_t
*pmac
= p
;
2180 const void *pnt
= (void *)pmac
->macaddr
.octet
;
2182 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
2186 * Compare two MAC addresses.
2188 static int mac_cmp(const void *p1
, const void *p2
)
2190 const zebra_mac_t
*pmac1
= p1
;
2191 const zebra_mac_t
*pmac2
= p2
;
2193 if (pmac1
== NULL
&& pmac2
== NULL
)
2196 if (pmac1
== NULL
|| pmac2
== NULL
)
2199 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
2204 * Callback to allocate MAC hash entry.
2206 static void *zvni_mac_alloc(void *p
)
2208 const zebra_mac_t
*tmp_mac
= p
;
2211 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2214 return ((void *)mac
);
2220 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
2222 zebra_mac_t tmp_mac
;
2223 zebra_mac_t
*mac
= NULL
;
2225 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
2226 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
2227 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
2230 mac
->neigh_list
= list_new();
2231 mac
->neigh_list
->cmp
= (int (*)(void *, void *))neigh_cmp
;
2239 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2241 zebra_mac_t
*tmp_mac
;
2243 list_delete_and_null(&mac
->neigh_list
);
2245 /* Free the VNI hash entry and allocated memory. */
2246 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
2248 XFREE(MTYPE_MAC
, tmp_mac
);
2254 * Free MAC hash entry (callback)
2256 static void zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2258 struct mac_walk_ctx
*wctx
= arg
;
2259 zebra_mac_t
*mac
= backet
->data
;
2261 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
2262 || ((wctx
->flags
& DEL_REMOTE_MAC
)
2263 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
2264 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
2265 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
2266 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
2267 &wctx
->r_vtep_ip
))) {
2268 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
2269 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
2270 &mac
->macaddr
, mac
->flags
);
2273 if (wctx
->uninstall
)
2274 zvni_mac_uninstall(wctx
->zvni
, mac
, 0);
2276 zvni_mac_del(wctx
->zvni
, mac
);
2283 * Delete all MAC entries from specific VTEP for a particular VNI.
2285 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2286 struct in_addr
*r_vtep_ip
)
2288 struct mac_walk_ctx wctx
;
2290 if (!zvni
->mac_table
)
2293 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2295 wctx
.uninstall
= uninstall
;
2296 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
2297 wctx
.r_vtep_ip
= *r_vtep_ip
;
2299 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2303 * Delete all MAC entries for this VNI.
2305 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2308 struct mac_walk_ctx wctx
;
2310 if (!zvni
->mac_table
)
2313 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2315 wctx
.uninstall
= uninstall
;
2316 wctx
.upd_client
= upd_client
;
2319 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2323 * Look up MAC hash entry.
2325 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
2330 memset(&tmp
, 0, sizeof(tmp
));
2331 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
2332 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
2338 * Inform BGP about local MAC addition.
2340 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2345 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2346 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2347 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2348 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2350 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2355 * Inform BGP about local MAC deletion.
2357 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2362 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2363 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2364 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2365 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2367 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2372 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2373 * notifications, to see if they are of interest.
2375 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
2376 struct interface
*br_if
, vlanid_t vid
)
2378 struct zebra_ns
*zns
;
2379 struct route_node
*rn
;
2380 struct interface
*tmp_if
= NULL
;
2381 struct zebra_if
*zif
;
2382 struct zebra_l2info_bridge
*br
;
2383 struct zebra_l2info_vxlan
*vxl
= NULL
;
2384 uint8_t bridge_vlan_aware
;
2388 /* Determine if bridge is VLAN-aware or not */
2391 br
= &zif
->l2info
.br
;
2392 bridge_vlan_aware
= br
->vlan_aware
;
2394 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2395 /* TODO: Optimize with a hash. */
2396 zns
= zebra_ns_lookup(NS_DEFAULT
);
2397 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2398 tmp_if
= (struct interface
*)rn
->info
;
2402 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2404 if (!if_is_operative(tmp_if
))
2406 vxl
= &zif
->l2info
.vxl
;
2408 if (zif
->brslave_info
.br_if
!= br_if
)
2411 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2420 zvni
= zvni_lookup(vxl
->vni
);
2425 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2426 * neighbor notifications, to see if they are of interest.
2428 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
2429 struct interface
*br_if
)
2431 struct zebra_ns
*zns
;
2432 struct route_node
*rn
;
2433 struct interface
*tmp_if
= NULL
;
2434 struct zebra_if
*zif
;
2435 struct zebra_l2info_bridge
*br
;
2436 struct zebra_l2info_vxlan
*vxl
= NULL
;
2437 uint8_t bridge_vlan_aware
;
2445 /* Make sure the linked interface is a bridge. */
2446 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
2449 /* Determine if bridge is VLAN-aware or not */
2452 br
= &zif
->l2info
.br
;
2453 bridge_vlan_aware
= br
->vlan_aware
;
2454 if (bridge_vlan_aware
) {
2455 struct zebra_l2info_vlan
*vl
;
2457 if (!IS_ZEBRA_IF_VLAN(ifp
))
2462 vl
= &zif
->l2info
.vl
;
2466 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2467 /* TODO: Optimize with a hash. */
2468 zns
= zebra_ns_lookup(NS_DEFAULT
);
2469 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2470 tmp_if
= (struct interface
*)rn
->info
;
2474 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2476 if (!if_is_operative(tmp_if
))
2478 vxl
= &zif
->l2info
.vxl
;
2480 if (zif
->brslave_info
.br_if
!= br_if
)
2483 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2492 zvni
= zvni_lookup(vxl
->vni
);
2496 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
2498 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
2499 * linked to the bridge
2500 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
2503 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
2505 struct zebra_ns
*zns
;
2506 struct route_node
*rn
;
2507 struct interface
*tmp_if
= NULL
;
2508 struct zebra_if
*zif
;
2509 struct zebra_l2info_bridge
*br
;
2510 struct zebra_l2info_vlan
*vl
;
2511 uint8_t bridge_vlan_aware
;
2514 /* Defensive check, caller expected to invoke only with valid bridge. */
2518 /* Determine if bridge is VLAN-aware or not */
2521 br
= &zif
->l2info
.br
;
2522 bridge_vlan_aware
= br
->vlan_aware
;
2524 /* Check oper status of the SVI. */
2525 if (!bridge_vlan_aware
)
2526 return if_is_operative(br_if
) ? br_if
: NULL
;
2528 /* Identify corresponding VLAN interface. */
2529 /* TODO: Optimize with a hash. */
2530 zns
= zebra_ns_lookup(NS_DEFAULT
);
2531 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2532 tmp_if
= (struct interface
*)rn
->info
;
2533 /* Check oper status of the SVI. */
2534 if (!tmp_if
|| !if_is_operative(tmp_if
))
2537 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
2538 || zif
->link
!= br_if
)
2540 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
2542 if (vl
->vid
== vid
) {
2548 return found
? tmp_if
: NULL
;
2552 * Install remote MAC into the kernel.
2554 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2556 struct zebra_if
*zif
;
2557 struct zebra_l2info_vxlan
*vxl
;
2560 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2563 zif
= zvni
->vxlan_if
->info
;
2566 vxl
= &zif
->l2info
.vxl
;
2568 sticky
= CHECK_FLAG(mac
->flags
,
2569 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
)) ? 1 : 0;
2571 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
2572 mac
->fwd_info
.r_vtep_ip
, sticky
);
2576 * Uninstall remote MAC from the kernel. In the scenario where the MAC
2577 * moves to remote, we have to uninstall any existing local entry first.
2579 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
)
2581 struct zebra_if
*zif
;
2582 struct zebra_l2info_vxlan
*vxl
;
2583 struct in_addr vtep_ip
= {.s_addr
= 0};
2584 struct zebra_ns
*zns
;
2585 struct interface
*ifp
;
2587 if (!local
&& !(mac
->flags
& ZEBRA_MAC_REMOTE
))
2590 if (!zvni
->vxlan_if
) {
2591 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2596 zif
= zvni
->vxlan_if
->info
;
2599 vxl
= &zif
->l2info
.vxl
;
2602 zns
= zebra_ns_lookup(NS_DEFAULT
);
2603 ifp
= if_lookup_by_index_per_ns(zns
,
2604 mac
->fwd_info
.local
.ifindex
);
2605 if (!ifp
) // unexpected
2608 ifp
= zvni
->vxlan_if
;
2609 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
2612 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
,
2617 * Install MAC hash entry - called upon access VLAN change.
2619 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
2622 struct mac_walk_ctx
*wctx
= ctxt
;
2624 mac
= (zebra_mac_t
*)backet
->data
;
2628 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
2629 zvni_mac_install(wctx
->zvni
, mac
);
2633 * Decrement neighbor refcount of MAC; uninstall and free it if
2636 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
2639 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)
2640 || !list_isempty(mac
->neigh_list
))
2644 zvni_mac_uninstall(zvni
, mac
, 0);
2646 zvni_mac_del(zvni
, mac
);
2650 * Read and populate local MACs and neighbors corresponding to this VNI.
2652 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
2654 struct zebra_ns
*zns
;
2655 struct zebra_if
*zif
;
2656 struct interface
*vlan_if
;
2657 struct zebra_l2info_vxlan
*vxl
;
2658 struct interface
*vrr_if
;
2661 vxl
= &zif
->l2info
.vxl
;
2662 zns
= zebra_ns_lookup(NS_DEFAULT
);
2664 if (IS_ZEBRA_DEBUG_VXLAN
)
2666 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2667 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2668 zif
->brslave_info
.bridge_ifindex
);
2670 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
2671 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2674 /* Add SVI MAC-IP */
2675 zvni_add_macip_for_intf(vlan_if
, zvni
);
2677 /* Add VRR MAC-IP - if any*/
2678 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2680 zvni_add_macip_for_intf(vrr_if
, zvni
);
2682 neigh_read_for_vlan(zns
, vlan_if
);
2687 * Hash function for VNI.
2689 static unsigned int vni_hash_keymake(void *p
)
2691 const zebra_vni_t
*zvni
= p
;
2693 return (jhash_1word(zvni
->vni
, 0));
2697 * Compare 2 VNI hash entries.
2699 static int vni_hash_cmp(const void *p1
, const void *p2
)
2701 const zebra_vni_t
*zvni1
= p1
;
2702 const zebra_vni_t
*zvni2
= p2
;
2704 return (zvni1
->vni
== zvni2
->vni
);
2708 * Callback to allocate VNI hash entry.
2710 static void *zvni_alloc(void *p
)
2712 const zebra_vni_t
*tmp_vni
= p
;
2715 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
2716 zvni
->vni
= tmp_vni
->vni
;
2717 return ((void *)zvni
);
2721 * Look up VNI hash entry.
2723 static zebra_vni_t
*zvni_lookup(vni_t vni
)
2725 struct zebra_vrf
*zvrf
;
2726 zebra_vni_t tmp_vni
;
2727 zebra_vni_t
*zvni
= NULL
;
2729 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2731 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
2733 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
2739 * Add VNI hash entry.
2741 static zebra_vni_t
*zvni_add(vni_t vni
)
2743 struct zebra_vrf
*zvrf
;
2744 zebra_vni_t tmp_zvni
;
2745 zebra_vni_t
*zvni
= NULL
;
2747 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2749 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
2751 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
2754 /* Create hash table for MAC */
2756 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
2758 /* Create hash table for neighbors */
2759 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
2760 "Zebra VNI Neighbor Table");
2766 * Delete VNI hash entry.
2768 static int zvni_del(zebra_vni_t
*zvni
)
2770 struct zebra_vrf
*zvrf
;
2771 zebra_vni_t
*tmp_zvni
;
2773 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2776 zvni
->vxlan_if
= NULL
;
2778 /* Free the neighbor hash table. */
2779 hash_free(zvni
->neigh_table
);
2780 zvni
->neigh_table
= NULL
;
2782 /* Free the MAC hash table. */
2783 hash_free(zvni
->mac_table
);
2784 zvni
->mac_table
= NULL
;
2786 /* Free the VNI hash entry and allocated memory. */
2787 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
2789 XFREE(MTYPE_ZVNI
, tmp_zvni
);
2795 * Inform BGP about local VNI addition.
2797 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
2799 struct zserv
*client
;
2802 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2803 /* BGP may not be running. */
2807 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2809 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
2810 stream_putl(s
, zvni
->vni
);
2811 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
2812 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
2814 /* Write packet size. */
2815 stream_putw_at(s
, 0, stream_get_endp(s
));
2817 if (IS_ZEBRA_DEBUG_VXLAN
)
2818 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
2819 inet_ntoa(zvni
->local_vtep_ip
),
2820 vrf_id_to_name(zvni
->vrf_id
),
2821 zebra_route_string(client
->proto
));
2823 client
->vniadd_cnt
++;
2824 return zserv_send_message(client
, s
);
2828 * Inform BGP about local VNI deletion.
2830 static int zvni_send_del_to_client(vni_t vni
)
2832 struct zserv
*client
;
2835 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2836 /* BGP may not be running. */
2840 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2843 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
2844 stream_putl(s
, vni
);
2846 /* Write packet size. */
2847 stream_putw_at(s
, 0, stream_get_endp(s
));
2849 if (IS_ZEBRA_DEBUG_VXLAN
)
2850 zlog_debug("Send VNI_DEL %u to %s", vni
,
2851 zebra_route_string(client
->proto
));
2853 client
->vnidel_cnt
++;
2854 return zserv_send_message(client
, s
);
2858 * Build the VNI hash table by going over the VxLAN interfaces. This
2859 * is called when EVPN (advertise-all-vni) is enabled.
2861 static void zvni_build_hash_table()
2863 struct zebra_ns
*zns
;
2864 struct route_node
*rn
;
2865 struct interface
*ifp
;
2867 /* Walk VxLAN interfaces and create VNI hash. */
2868 zns
= zebra_ns_lookup(NS_DEFAULT
);
2869 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2871 zebra_vni_t
*zvni
= NULL
;
2872 zebra_l3vni_t
*zl3vni
= NULL
;
2873 struct zebra_if
*zif
;
2874 struct zebra_l2info_vxlan
*vxl
;
2876 ifp
= (struct interface
*)rn
->info
;
2880 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2883 vxl
= &zif
->l2info
.vxl
;
2886 /* L3-VNI and L2-VNI are handled seperately */
2887 zl3vni
= zl3vni_lookup(vni
);
2890 if (IS_ZEBRA_DEBUG_VXLAN
)
2892 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
2893 ifp
->name
, ifp
->ifindex
, vni
);
2895 /* associate with vxlan_if */
2896 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
2897 zl3vni
->vxlan_if
= ifp
;
2900 * we need to associate with SVI.
2901 * we can associate with svi-if only after association
2902 * with vxlan-intf is complete
2904 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
2906 if (is_l3vni_oper_up(zl3vni
))
2907 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
2910 struct interface
*vlan_if
= NULL
;
2912 if (IS_ZEBRA_DEBUG_VXLAN
)
2914 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
2915 ifp
->name
, ifp
->ifindex
, vni
,
2916 inet_ntoa(vxl
->vtep_ip
));
2918 /* VNI hash entry is not expected to exist. */
2919 zvni
= zvni_lookup(vni
);
2922 "VNI hash already present for IF %s(%u) L2-VNI %u",
2923 ifp
->name
, ifp
->ifindex
, vni
);
2927 zvni
= zvni_add(vni
);
2930 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
2931 ifp
->name
, ifp
->ifindex
, vni
);
2935 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
2936 zvni
->vxlan_if
= ifp
;
2937 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
2938 zif
->brslave_info
.br_if
);
2940 zvni
->vrf_id
= vlan_if
->vrf_id
;
2941 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
2943 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
2947 /* Inform BGP if intf is up and mapped to bridge. */
2948 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
2949 zvni_send_add_to_client(zvni
);
2955 * See if remote VTEP matches with prefix.
2957 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
2959 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
2963 * Locate remote VTEP in VNI hash table.
2965 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2967 zebra_vtep_t
*zvtep
;
2972 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2973 if (zvni_vtep_match(vtep_ip
, zvtep
))
2981 * Add remote VTEP to VNI hash table.
2983 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2985 zebra_vtep_t
*zvtep
;
2987 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
2989 zvtep
->vtep_ip
= *vtep_ip
;
2992 zvni
->vteps
->prev
= zvtep
;
2993 zvtep
->next
= zvni
->vteps
;
2994 zvni
->vteps
= zvtep
;
3000 * Remove remote VTEP from VNI hash table.
3002 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
3005 zvtep
->next
->prev
= zvtep
->prev
;
3007 zvtep
->prev
->next
= zvtep
->next
;
3009 zvni
->vteps
= zvtep
->next
;
3011 zvtep
->prev
= zvtep
->next
= NULL
;
3012 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
3018 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
3019 * uninstall from kernel if asked to.
3021 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
3023 zebra_vtep_t
*zvtep
, *zvtep_next
;
3028 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
3029 zvtep_next
= zvtep
->next
;
3031 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
3032 zvni_vtep_del(zvni
, zvtep
);
3039 * Install remote VTEP into the kernel.
3041 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3043 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3047 * Uninstall remote VTEP from the kernel.
3049 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3051 if (!zvni
->vxlan_if
) {
3052 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
3057 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3061 * Cleanup VNI/VTEP and update kernel
3063 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
3065 zebra_vni_t
*zvni
= NULL
;
3066 zebra_l3vni_t
*zl3vni
= NULL
;
3067 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
3069 zvni
= (zebra_vni_t
*)backet
->data
;
3073 /* remove from l3-vni list */
3075 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
3077 listnode_delete(zl3vni
->l2vnis
, zvni
);
3079 /* Free up all neighbors and MACs, if any. */
3080 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
3081 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
3083 /* Free up all remote VTEPs, if any. */
3084 zvni_vtep_del_all(zvni
, 1);
3086 /* Delete the hash entry. */
3091 static void zl3vni_cleanup_all(struct hash_backet
*backet
, void *args
)
3093 zebra_l3vni_t
*zl3vni
= NULL
;
3095 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
3099 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
3102 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
3103 struct prefix
*host
)
3105 struct host_rb_entry lookup
;
3106 struct host_rb_entry
*hle
;
3108 memset(&lookup
, 0, sizeof(lookup
));
3109 memcpy(&lookup
.p
, host
, sizeof(*host
));
3111 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3115 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
3116 memcpy(hle
, &lookup
, sizeof(lookup
));
3118 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
3121 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
3123 struct host_rb_entry lookup
;
3124 struct host_rb_entry
*hle
;
3126 memset(&lookup
, 0, sizeof(lookup
));
3127 memcpy(&lookup
.p
, host
, sizeof(*host
));
3129 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3131 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
3132 XFREE(MTYPE_HOST_PREFIX
, hle
);
3139 * Look up MAC hash entry.
3141 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
3142 struct ethaddr
*rmac
)
3147 memset(&tmp
, 0, sizeof(tmp
));
3148 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
3149 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
3155 * Callback to allocate RMAC hash entry.
3157 static void *zl3vni_rmac_alloc(void *p
)
3159 const zebra_mac_t
*tmp_rmac
= p
;
3162 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3165 return ((void *)zrmac
);
3169 * Add RMAC entry to l3-vni
3171 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
3173 zebra_mac_t tmp_rmac
;
3174 zebra_mac_t
*zrmac
= NULL
;
3176 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
3177 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
3178 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
3181 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
3183 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
3184 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
3192 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3194 zebra_mac_t
*tmp_rmac
;
3195 struct host_rb_entry
*hle
;
3197 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3198 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
3200 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
3201 XFREE(MTYPE_HOST_PREFIX
, hle
);
3204 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
3206 XFREE(MTYPE_MAC
, tmp_rmac
);
3212 * Install remote RMAC into the kernel.
3214 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3216 struct zebra_if
*zif
= NULL
;
3217 struct zebra_l2info_vxlan
*vxl
= NULL
;
3219 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3220 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3223 zif
= zl3vni
->vxlan_if
->info
;
3227 vxl
= &zif
->l2info
.vxl
;
3229 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3230 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3234 * Uninstall remote RMAC from the kernel.
3236 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3238 char buf
[ETHER_ADDR_STRLEN
];
3239 struct zebra_if
*zif
= NULL
;
3240 struct zebra_l2info_vxlan
*vxl
= NULL
;
3242 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3243 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3246 if (!zl3vni
->vxlan_if
) {
3248 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
3249 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
3250 zl3vni
->vni
, zl3vni
);
3254 zif
= zl3vni
->vxlan_if
->info
;
3258 vxl
= &zif
->l2info
.vxl
;
3260 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3261 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3264 /* handle rmac add */
3265 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
3266 struct ipaddr
*vtep_ip
,
3267 struct prefix
*host_prefix
)
3269 char buf
[ETHER_ADDR_STRLEN
];
3270 char buf1
[INET6_ADDRSTRLEN
];
3271 zebra_mac_t
*zrmac
= NULL
;
3273 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3276 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
3279 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
3280 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3282 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
3285 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
3286 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
3288 /* install rmac in kernel */
3289 zl3vni_rmac_install(zl3vni
, zrmac
);
3292 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
3298 /* handle rmac delete */
3299 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
3300 struct prefix
*host_prefix
)
3302 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
3304 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3305 /* uninstall from kernel */
3306 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3308 /* del the rmac entry */
3309 zl3vni_rmac_del(zl3vni
, zrmac
);
3314 * Look up nh hash entry on a l3-vni.
3316 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3321 memset(&tmp
, 0, sizeof(tmp
));
3322 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
3323 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
3330 * Callback to allocate NH hash entry on L3-VNI.
3332 static void *zl3vni_nh_alloc(void *p
)
3334 const zebra_neigh_t
*tmp_n
= p
;
3337 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
3344 * Add neighbor entry.
3346 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3347 struct ethaddr
*mac
)
3349 zebra_neigh_t tmp_n
;
3350 zebra_neigh_t
*n
= NULL
;
3352 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
3353 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
3354 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
3357 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
3359 memcpy(&n
->emac
, mac
, ETH_ALEN
);
3360 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3361 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
3367 * Delete neighbor entry.
3369 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3371 zebra_neigh_t
*tmp_n
;
3372 struct host_rb_entry
*hle
;
3374 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
3375 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
3377 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
3378 XFREE(MTYPE_HOST_PREFIX
, hle
);
3381 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
3383 XFREE(MTYPE_NEIGH
, tmp_n
);
3389 * Install remote nh as neigh into the kernel.
3391 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3396 if (!is_l3vni_oper_up(zl3vni
))
3399 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3400 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3403 flags
= NTF_EXT_LEARNED
;
3404 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
3405 flags
|= NTF_ROUTER
;
3406 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
3412 * Uninstall remote nh from the kernel.
3414 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3416 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3417 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3420 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
3423 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
3426 /* add remote vtep as a neigh entry */
3427 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
3428 struct ethaddr
*rmac
,
3429 struct prefix
*host_prefix
)
3431 char buf
[ETHER_ADDR_STRLEN
];
3432 char buf1
[INET6_ADDRSTRLEN
];
3433 zebra_neigh_t
*nh
= NULL
;
3435 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3437 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
3441 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
3442 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
3443 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3448 /* install the nh neigh in kernel */
3449 zl3vni_nh_install(zl3vni
, nh
);
3452 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
3457 /* handle nh neigh delete */
3458 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
3459 struct prefix
*host_prefix
)
3461 rb_delete_host(&nh
->host_rb
, host_prefix
);
3463 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
3464 /* uninstall from kernel */
3465 zl3vni_nh_uninstall(zl3vni
, nh
);
3467 /* delete the nh entry */
3468 zl3vni_nh_del(zl3vni
, nh
);
3472 /* handle neigh update from kernel - the only thing of interest is to
3473 * readd stale entries.
3475 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3479 zebra_neigh_t
*n
= NULL
;
3481 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3485 /* all next hop neigh are remote and installed by frr.
3486 * If the kernel has aged this entry, re-install.
3488 if (state
& NUD_STALE
)
3489 zl3vni_nh_install(zl3vni
, n
);
3494 /* handle neigh delete from kernel */
3495 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3497 zebra_neigh_t
*n
= NULL
;
3499 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3503 /* all next hop neigh are remote and installed by frr.
3504 * If we get an age out notification for these neigh entries, we have to
3507 zl3vni_nh_install(zl3vni
, n
);
3513 * Hash function for L3 VNI.
3515 static unsigned int l3vni_hash_keymake(void *p
)
3517 const zebra_l3vni_t
*zl3vni
= p
;
3519 return jhash_1word(zl3vni
->vni
, 0);
3523 * Compare 2 L3 VNI hash entries.
3525 static int l3vni_hash_cmp(const void *p1
, const void *p2
)
3527 const zebra_l3vni_t
*zl3vni1
= p1
;
3528 const zebra_l3vni_t
*zl3vni2
= p2
;
3530 return (zl3vni1
->vni
== zl3vni2
->vni
);
3534 * Callback to allocate L3 VNI hash entry.
3536 static void *zl3vni_alloc(void *p
)
3538 zebra_l3vni_t
*zl3vni
= NULL
;
3539 const zebra_l3vni_t
*tmp_l3vni
= p
;
3541 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
3542 zl3vni
->vni
= tmp_l3vni
->vni
;
3543 return ((void *)zl3vni
);
3547 * Look up L3 VNI hash entry.
3549 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
3551 struct zebra_ns
*zns
;
3552 zebra_l3vni_t tmp_l3vni
;
3553 zebra_l3vni_t
*zl3vni
= NULL
;
3555 zns
= zebra_ns_lookup(NS_DEFAULT
);
3557 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
3558 tmp_l3vni
.vni
= vni
;
3559 zl3vni
= hash_lookup(zns
->l3vni_table
, &tmp_l3vni
);
3565 * Add L3 VNI hash entry.
3567 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
3569 zebra_l3vni_t tmp_zl3vni
;
3570 struct zebra_ns
*zns
= NULL
;
3571 zebra_l3vni_t
*zl3vni
= NULL
;
3573 zns
= zebra_ns_lookup(NS_DEFAULT
);
3576 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
3577 tmp_zl3vni
.vni
= vni
;
3579 zl3vni
= hash_get(zns
->l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
3582 zl3vni
->vrf_id
= vrf_id
;
3583 zl3vni
->svi_if
= NULL
;
3584 zl3vni
->vxlan_if
= NULL
;
3585 zl3vni
->l2vnis
= list_new();
3586 zl3vni
->l2vnis
->cmp
= (int (*)(void *, void *))vni_hash_cmp
;
3588 /* Create hash table for remote RMAC */
3589 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
3590 "Zebra L3-VNI RMAC-Table");
3592 /* Create hash table for neighbors */
3593 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3594 "Zebra L3-VNI next-hop table");
3600 * Delete L3 VNI hash entry.
3602 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
3604 struct zebra_ns
*zns
;
3605 zebra_l3vni_t
*tmp_zl3vni
;
3607 zns
= zebra_ns_lookup(NS_DEFAULT
);
3610 /* free the list of l2vnis */
3611 list_delete_and_null(&zl3vni
->l2vnis
);
3612 zl3vni
->l2vnis
= NULL
;
3614 /* Free the rmac table */
3615 hash_free(zl3vni
->rmac_table
);
3616 zl3vni
->rmac_table
= NULL
;
3618 /* Free the nh table */
3619 hash_free(zl3vni
->nh_table
);
3620 zl3vni
->nh_table
= NULL
;
3622 /* Free the VNI hash entry and allocated memory. */
3623 tmp_zl3vni
= hash_release(zns
->l3vni_table
, zl3vni
);
3625 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
3630 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
3632 struct zebra_ns
*zns
= NULL
;
3633 struct route_node
*rn
= NULL
;
3634 struct interface
*ifp
= NULL
;
3636 /* loop through all vxlan-interface */
3637 zns
= zebra_ns_lookup(NS_DEFAULT
);
3638 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3640 struct zebra_if
*zif
= NULL
;
3641 struct zebra_l2info_vxlan
*vxl
= NULL
;
3643 ifp
= (struct interface
*)rn
->info
;
3648 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3651 vxl
= &zif
->l2info
.vxl
;
3652 if (vxl
->vni
== zl3vni
->vni
) {
3653 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3661 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
3663 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
3664 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
3669 if (!zl3vni
->vxlan_if
)
3672 zif
= zl3vni
->vxlan_if
->info
;
3676 vxl
= &zif
->l2info
.vxl
;
3678 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3681 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
3683 struct zebra_vrf
*zvrf
= NULL
;
3685 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
3689 return zl3vni_lookup(zvrf
->l3vni
);
3693 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3694 * neighbor notifications, to see if they are of interest.
3696 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
3697 struct interface
*br_if
)
3701 uint8_t bridge_vlan_aware
= 0;
3702 zebra_l3vni_t
*zl3vni
= NULL
;
3703 struct zebra_ns
*zns
= NULL
;
3704 struct route_node
*rn
= NULL
;
3705 struct zebra_if
*zif
= NULL
;
3706 struct interface
*tmp_if
= NULL
;
3707 struct zebra_l2info_bridge
*br
= NULL
;
3708 struct zebra_l2info_vxlan
*vxl
= NULL
;
3713 /* Make sure the linked interface is a bridge. */
3714 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3717 /* Determine if bridge is VLAN-aware or not */
3720 br
= &zif
->l2info
.br
;
3721 bridge_vlan_aware
= br
->vlan_aware
;
3722 if (bridge_vlan_aware
) {
3723 struct zebra_l2info_vlan
*vl
;
3725 if (!IS_ZEBRA_IF_VLAN(ifp
))
3730 vl
= &zif
->l2info
.vl
;
3734 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3735 /* TODO: Optimize with a hash. */
3736 zns
= zebra_ns_lookup(NS_DEFAULT
);
3737 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3738 tmp_if
= (struct interface
*)rn
->info
;
3742 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3744 if (!if_is_operative(tmp_if
))
3746 vxl
= &zif
->l2info
.vxl
;
3748 if (zif
->brslave_info
.br_if
!= br_if
)
3751 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3760 zl3vni
= zl3vni_lookup(vxl
->vni
);
3765 * Inform BGP about l3-vni.
3767 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
3769 struct stream
*s
= NULL
;
3770 struct zserv
*client
= NULL
;
3771 struct ethaddr rmac
;
3772 char buf
[ETHER_ADDR_STRLEN
];
3774 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3775 /* BGP may not be running. */
3780 memset(&rmac
, 0, sizeof(struct ethaddr
));
3781 zl3vni_get_rmac(zl3vni
, &rmac
);
3783 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3785 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
3786 stream_putl(s
, zl3vni
->vni
);
3787 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
3788 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
3789 stream_put(s
, &zl3vni
->filter
, sizeof(int));
3791 /* Write packet size. */
3792 stream_putw_at(s
, 0, stream_get_endp(s
));
3794 if (IS_ZEBRA_DEBUG_VXLAN
)
3796 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
3797 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3798 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
3799 inet_ntoa(zl3vni
->local_vtep_ip
),
3800 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
3801 ? "prefix-routes-only"
3803 zebra_route_string(client
->proto
));
3805 client
->l3vniadd_cnt
++;
3806 return zserv_send_message(client
, s
);
3810 * Inform BGP about local l3-VNI deletion.
3812 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
3814 struct stream
*s
= NULL
;
3815 struct zserv
*client
= NULL
;
3817 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3818 /* BGP may not be running. */
3822 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3824 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
3825 stream_putl(s
, zl3vni
->vni
);
3827 /* Write packet size. */
3828 stream_putw_at(s
, 0, stream_get_endp(s
));
3830 if (IS_ZEBRA_DEBUG_VXLAN
)
3831 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
3832 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3833 zebra_route_string(client
->proto
));
3835 client
->l3vnidel_cnt
++;
3836 return zserv_send_message(client
, s
);
3839 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
3844 /* send l3vni add to BGP */
3845 zl3vni_send_add_to_client(zl3vni
);
3848 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
3853 /* send l3-vni del to BGP*/
3854 zl3vni_send_del_to_client(zl3vni
);
3857 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
, void *ctxt
)
3859 zebra_vni_t
*zvni
= (zebra_vni_t
*)backet
->data
;
3860 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
3862 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
3863 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3867 * handle transition of vni from l2 to l3 and vice versa
3869 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
3872 zebra_vni_t
*zvni
= NULL
;
3874 /* There is a possibility that VNI notification was already received
3875 * from kernel and we programmed it as L2-VNI
3876 * In such a case we need to delete this L2-VNI first, so
3877 * that it can be reprogrammed as L3-VNI in the system. It is also
3878 * possible that the vrf-vni mapping is removed from FRR while the vxlan
3879 * interface is still present in kernel. In this case to keep it
3880 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
3883 /* Locate hash entry */
3884 zvni
= zvni_lookup(vni
);
3888 if (IS_ZEBRA_DEBUG_VXLAN
)
3889 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
3891 /* Delete VNI from BGP. */
3892 zvni_send_del_to_client(zvni
->vni
);
3894 /* Free up all neighbors and MAC, if any. */
3895 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
3896 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
3898 /* Free up all remote VTEPs, if any. */
3899 zvni_vtep_del_all(zvni
, 0);
3901 /* Delete the hash entry. */
3902 if (zvni_del(zvni
)) {
3903 zlog_err("Failed to del VNI hash %p, VNI %u", zvni
,
3908 /* TODO_MITESH: This needs to be thought through. We don't have
3909 * enough information at this point to reprogram the vni as
3910 * l2-vni. One way is to store the required info in l3-vni and
3911 * used it solely for this purpose
3918 /* delete and uninstall rmac hash entry */
3919 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
, void *ctx
)
3921 zebra_mac_t
*zrmac
= NULL
;
3922 zebra_l3vni_t
*zl3vni
= NULL
;
3924 zrmac
= (zebra_mac_t
*)backet
->data
;
3925 zl3vni
= (zebra_l3vni_t
*)ctx
;
3926 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3927 zl3vni_rmac_del(zl3vni
, zrmac
);
3930 /* delete and uninstall nh hash entry */
3931 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
, void *ctx
)
3933 zebra_neigh_t
*n
= NULL
;
3934 zebra_l3vni_t
*zl3vni
= NULL
;
3936 n
= (zebra_neigh_t
*)backet
->data
;
3937 zl3vni
= (zebra_l3vni_t
*)ctx
;
3938 zl3vni_nh_uninstall(zl3vni
, n
);
3939 zl3vni_nh_del(zl3vni
, n
);
3942 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
3945 struct zserv
*client
= NULL
;
3946 struct stream
*s
= NULL
;
3947 char buf
[PREFIX_STRLEN
];
3949 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3950 /* BGP may not be running. */
3954 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3956 zclient_create_header(s
, cmd
, vrf_id
);
3957 stream_put(s
, p
, sizeof(struct prefix
));
3959 /* Write packet size. */
3960 stream_putw_at(s
, 0, stream_get_endp(s
));
3962 if (IS_ZEBRA_DEBUG_VXLAN
)
3963 zlog_debug("Send ip prefix %s %s on vrf %s",
3964 prefix2str(p
, buf
, sizeof(buf
)),
3965 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
3966 vrf_id_to_name(vrf_id
));
3968 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
3969 client
->prefixadd_cnt
++;
3971 client
->prefixdel_cnt
++;
3973 return zserv_send_message(client
, s
);
3976 /* re-add remote rmac if needed */
3977 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
3978 struct ethaddr
*rmac
)
3980 char buf
[ETHER_ADDR_STRLEN
];
3981 zebra_mac_t
*zrmac
= NULL
;
3983 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3987 if (IS_ZEBRA_DEBUG_VXLAN
)
3988 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
3989 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
3991 zl3vni_rmac_install(zl3vni
, zrmac
);
3995 /* Public functions */
3997 int is_l3vni_for_prefix_routes_only(vni_t vni
)
3999 zebra_l3vni_t
*zl3vni
= NULL
;
4001 zl3vni
= zl3vni_lookup(vni
);
4005 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
4008 /* handle evpn route in vrf table */
4009 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
4010 struct ipaddr
*vtep_ip
,
4011 struct prefix
*host_prefix
)
4013 zebra_l3vni_t
*zl3vni
= NULL
;
4014 struct ipaddr ipv4_vtep
;
4016 zl3vni
= zl3vni_from_vrf(vrf_id
);
4017 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
4021 * add the next hop neighbor -
4022 * neigh to be installed is the ipv6 nexthop neigh
4024 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
4027 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
4028 * address. Rmac is programmed against the ipv4 vtep because we only
4029 * support ipv4 tunnels in the h/w right now
4031 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
4032 ipv4_vtep
.ipa_type
= IPADDR_V4
;
4033 if (vtep_ip
->ipa_type
== IPADDR_V6
)
4034 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
4035 &(ipv4_vtep
.ipaddr_v4
));
4037 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
4038 sizeof(struct in_addr
));
4041 * add the rmac - remote rmac to be installed is against the ipv4
4044 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
4047 /* handle evpn vrf route delete */
4048 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
4049 struct ipaddr
*vtep_ip
,
4050 struct prefix
*host_prefix
)
4052 zebra_l3vni_t
*zl3vni
= NULL
;
4053 zebra_neigh_t
*nh
= NULL
;
4054 zebra_mac_t
*zrmac
= NULL
;
4056 zl3vni
= zl3vni_from_vrf(vrf_id
);
4060 /* find the next hop entry and rmac entry */
4061 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4064 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
4066 /* delete the next hop entry */
4067 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
4069 /* delete the rmac entry */
4071 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
4075 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
4076 struct ethaddr
*rmac
,
4079 zebra_l3vni_t
*zl3vni
= NULL
;
4080 zebra_mac_t
*zrmac
= NULL
;
4081 json_object
*json
= NULL
;
4083 if (!is_evpn_enabled()) {
4085 vty_out(vty
, "{}\n");
4090 json
= json_object_new_object();
4092 zl3vni
= zl3vni_lookup(l3vni
);
4095 vty_out(vty
, "{}\n");
4097 vty_out(vty
, "%% L3-VNI %u doesnt exist\n", l3vni
);
4101 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4104 vty_out(vty
, "{}\n");
4107 "%% Requested RMAC doesnt exist in L3-VNI %u",
4112 zl3vni_print_rmac(zrmac
, vty
, json
);
4115 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4116 json
, JSON_C_TO_STRING_PRETTY
));
4117 json_object_free(json
);
4121 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
,
4124 zebra_l3vni_t
*zl3vni
;
4126 struct rmac_walk_ctx wctx
;
4127 json_object
*json
= NULL
;
4129 if (!is_evpn_enabled())
4132 zl3vni
= zl3vni_lookup(l3vni
);
4135 vty_out(vty
, "{}\n");
4137 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4140 num_rmacs
= hashcount(zl3vni
->rmac_table
);
4145 json
= json_object_new_object();
4147 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
4151 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
4153 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
4155 json_object_int_add(json
, "numRmacs", num_rmacs
);
4157 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
4160 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4161 json
, JSON_C_TO_STRING_PRETTY
));
4162 json_object_free(json
);
4166 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, uint8_t use_json
)
4168 struct zebra_ns
*zns
= NULL
;
4169 json_object
*json
= NULL
;
4172 if (!is_evpn_enabled()) {
4174 vty_out(vty
, "{}\n");
4178 zns
= zebra_ns_lookup(NS_DEFAULT
);
4181 vty_out(vty
, "{}\n");
4186 json
= json_object_new_object();
4190 hash_iterate(zns
->l3vni_table
,
4191 (void (*)(struct hash_backet
*,
4192 void *))zl3vni_print_rmac_hash_all_vni
,
4196 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4197 json
, JSON_C_TO_STRING_PRETTY
));
4198 json_object_free(json
);
4202 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
4203 struct ipaddr
*ip
, uint8_t use_json
)
4205 zebra_l3vni_t
*zl3vni
= NULL
;
4206 zebra_neigh_t
*n
= NULL
;
4207 json_object
*json
= NULL
;
4209 if (!is_evpn_enabled()) {
4211 vty_out(vty
, "{}\n");
4216 json
= json_object_new_object();
4218 zl3vni
= zl3vni_lookup(l3vni
);
4221 vty_out(vty
, "{}\n");
4223 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4227 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4230 vty_out(vty
, "{}\n");
4233 "%% Requested next-hop not present for L3-VNI %u",
4238 zl3vni_print_nh(n
, vty
, json
);
4241 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4242 json
, JSON_C_TO_STRING_PRETTY
));
4243 json_object_free(json
);
4247 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, uint8_t use_json
)
4250 struct nh_walk_ctx wctx
;
4251 json_object
*json
= NULL
;
4252 zebra_l3vni_t
*zl3vni
= NULL
;
4254 if (!is_evpn_enabled())
4257 zl3vni
= zl3vni_lookup(l3vni
);
4260 vty_out(vty
, "{}\n");
4262 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4266 num_nh
= hashcount(zl3vni
->nh_table
);
4271 json
= json_object_new_object();
4276 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
4278 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
4280 json_object_int_add(json
, "numNextHops", num_nh
);
4282 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
4285 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4286 json
, JSON_C_TO_STRING_PRETTY
));
4287 json_object_free(json
);
4291 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, uint8_t use_json
)
4293 struct zebra_ns
*zns
= NULL
;
4294 json_object
*json
= NULL
;
4297 if (!is_evpn_enabled()) {
4299 vty_out(vty
, "{}\n");
4303 zns
= zebra_ns_lookup(NS_DEFAULT
);
4308 json
= json_object_new_object();
4312 hash_iterate(zns
->l3vni_table
,
4313 (void (*)(struct hash_backet
*,
4314 void *))zl3vni_print_nh_hash_all_vni
,
4318 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4319 json
, JSON_C_TO_STRING_PRETTY
));
4320 json_object_free(json
);
4326 * Display L3 VNI information (VTY command handler).
4328 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, uint8_t use_json
)
4331 json_object
*json
= NULL
;
4332 zebra_l3vni_t
*zl3vni
= NULL
;
4334 if (!is_evpn_enabled()) {
4336 vty_out(vty
, "{}\n");
4340 zl3vni
= zl3vni_lookup(vni
);
4343 vty_out(vty
, "{}\n");
4345 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4350 json
= json_object_new_object();
4354 zl3vni_print(zl3vni
, (void *)args
);
4357 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4358 json
, JSON_C_TO_STRING_PRETTY
));
4359 json_object_free(json
);
4363 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4364 json_object
*json_vrfs
)
4366 char buf
[ETHER_ADDR_STRLEN
];
4367 zebra_l3vni_t
*zl3vni
= NULL
;
4369 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4374 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
4375 zvrf_name(zvrf
), zl3vni
->vni
,
4376 zl3vni_vxlan_if_name(zl3vni
),
4377 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
4378 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4380 json_object
*json_vrf
= NULL
;
4381 json_vrf
= json_object_new_object();
4382 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
4383 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
4384 json_object_string_add(json_vrf
, "vxlanIntf",
4385 zl3vni_vxlan_if_name(zl3vni
));
4386 json_object_string_add(json_vrf
, "sviIntf",
4387 zl3vni_svi_if_name(zl3vni
));
4388 json_object_string_add(json_vrf
, "state",
4389 zl3vni_state2str(zl3vni
));
4390 json_object_string_add(
4391 json_vrf
, "routerMac",
4392 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4393 json_object_array_add(json_vrfs
, json_vrf
);
4398 * Display Neighbors for a VNI (VTY command handler).
4400 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4401 vni_t vni
, uint8_t use_json
)
4405 struct neigh_walk_ctx wctx
;
4406 json_object
*json
= NULL
;
4408 if (!is_evpn_enabled())
4410 zvni
= zvni_lookup(vni
);
4413 vty_out(vty
, "{}\n");
4415 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4418 num_neigh
= hashcount(zvni
->neigh_table
);
4423 json
= json_object_new_object();
4425 /* Since we have IPv6 addresses to deal with which can vary widely in
4426 * size, we try to be a bit more elegant in display by first computing
4427 * the maximum width.
4429 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4432 wctx
.addr_width
= 15;
4434 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4438 "Number of ARPs (local and remote) known for this VNI: %u\n",
4440 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
4441 "Type", "MAC", "Remote VTEP");
4443 json_object_int_add(json
, "numArpNd", num_neigh
);
4445 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4447 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4448 json
, JSON_C_TO_STRING_PRETTY
));
4449 json_object_free(json
);
4454 * Display neighbors across all VNIs (VTY command handler).
4456 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4459 json_object
*json
= NULL
;
4462 if (!is_evpn_enabled())
4466 json
= json_object_new_object();
4470 hash_iterate(zvrf
->vni_table
,
4471 (void (*)(struct hash_backet
*,
4472 void *))zvni_print_neigh_hash_all_vni
,
4475 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4476 json
, JSON_C_TO_STRING_PRETTY
));
4477 json_object_free(json
);
4482 * Display specific neighbor for a VNI, if present (VTY command handler).
4484 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
4485 struct zebra_vrf
*zvrf
, vni_t vni
,
4486 struct ipaddr
*ip
, uint8_t use_json
)
4490 json_object
*json
= NULL
;
4492 if (!is_evpn_enabled())
4494 zvni
= zvni_lookup(vni
);
4497 vty_out(vty
, "{}\n");
4499 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4502 n
= zvni_neigh_lookup(zvni
, ip
);
4506 "%% Requested neighbor does not exist in VNI %u\n",
4511 json
= json_object_new_object();
4513 zvni_print_neigh(n
, vty
, json
);
4516 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4517 json
, JSON_C_TO_STRING_PRETTY
));
4518 json_object_free(json
);
4523 * Display neighbors for a VNI from specific VTEP (VTY command handler).
4524 * By definition, these are remote neighbors.
4526 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4527 vni_t vni
, struct in_addr vtep_ip
,
4532 struct neigh_walk_ctx wctx
;
4533 json_object
*json
= NULL
;
4535 if (!is_evpn_enabled())
4537 zvni
= zvni_lookup(vni
);
4540 vty_out(vty
, "{}\n");
4542 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4545 num_neigh
= hashcount(zvni
->neigh_table
);
4549 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4552 wctx
.addr_width
= 15;
4553 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
4554 wctx
.r_vtep_ip
= vtep_ip
;
4556 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4557 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4560 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4561 json
, JSON_C_TO_STRING_PRETTY
));
4562 json_object_free(json
);
4567 * Display MACs for a VNI (VTY command handler).
4569 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4570 vni_t vni
, uint8_t use_json
)
4574 struct mac_walk_ctx wctx
;
4575 json_object
*json
= NULL
;
4576 json_object
*json_mac
= NULL
;
4578 if (!is_evpn_enabled())
4580 zvni
= zvni_lookup(vni
);
4583 vty_out(vty
, "{}\n");
4585 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4588 num_macs
= num_valid_macs(zvni
);
4593 json
= json_object_new_object();
4594 json_mac
= json_object_new_object();
4597 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4600 wctx
.json
= json_mac
;
4604 "Number of MACs (local and remote) known for this VNI: %u\n",
4606 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
4607 "Intf/Remote VTEP", "VLAN");
4609 json_object_int_add(json
, "numMacs", num_macs
);
4611 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4614 json_object_object_add(json
, "macs", json_mac
);
4615 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4616 json
, JSON_C_TO_STRING_PRETTY
));
4617 json_object_free(json
);
4622 * Display MACs for all VNIs (VTY command handler).
4624 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4627 struct mac_walk_ctx wctx
;
4628 json_object
*json
= NULL
;
4630 if (!is_evpn_enabled()) {
4632 vty_out(vty
, "{}\n");
4636 json
= json_object_new_object();
4638 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4641 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4644 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4645 json
, JSON_C_TO_STRING_PRETTY
));
4646 json_object_free(json
);
4651 * Display MACs for all VNIs (VTY command handler).
4653 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
4654 struct zebra_vrf
*zvrf
,
4655 struct in_addr vtep_ip
,
4658 struct mac_walk_ctx wctx
;
4659 json_object
*json
= NULL
;
4661 if (!is_evpn_enabled())
4665 json
= json_object_new_object();
4667 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4669 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4670 wctx
.r_vtep_ip
= vtep_ip
;
4672 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4675 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4676 json
, JSON_C_TO_STRING_PRETTY
));
4677 json_object_free(json
);
4682 * Display specific MAC for a VNI, if present (VTY command handler).
4684 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4685 vni_t vni
, struct ethaddr
*macaddr
)
4690 if (!is_evpn_enabled())
4692 zvni
= zvni_lookup(vni
);
4694 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4697 mac
= zvni_mac_lookup(zvni
, macaddr
);
4699 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
4704 zvni_print_mac(mac
, vty
);
4708 * Display MACs for a VNI from specific VTEP (VTY command handler).
4710 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4711 vni_t vni
, struct in_addr vtep_ip
,
4716 struct mac_walk_ctx wctx
;
4717 json_object
*json
= NULL
;
4718 json_object
*json_mac
= NULL
;
4720 if (!is_evpn_enabled())
4722 zvni
= zvni_lookup(vni
);
4725 vty_out(vty
, "{}\n");
4727 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4730 num_macs
= num_valid_macs(zvni
);
4735 json
= json_object_new_object();
4736 json_mac
= json_object_new_object();
4739 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4742 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4743 wctx
.r_vtep_ip
= vtep_ip
;
4744 wctx
.json
= json_mac
;
4745 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4748 json_object_int_add(json
, "numMacs", wctx
.count
);
4750 json_object_object_add(json
, "macs", json_mac
);
4751 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4752 json
, JSON_C_TO_STRING_PRETTY
));
4753 json_object_free(json
);
4759 * Display VNI information (VTY command handler).
4761 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
4764 json_object
*json
= NULL
;
4766 zebra_l3vni_t
*zl3vni
= NULL
;
4767 zebra_vni_t
*zvni
= NULL
;
4769 if (!is_evpn_enabled())
4773 json
= json_object_new_object();
4777 zl3vni
= zl3vni_lookup(vni
);
4779 zl3vni_print(zl3vni
, (void *)args
);
4781 zvni
= zvni_lookup(vni
);
4784 vty_out(vty
, "{}\n");
4786 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4790 zvni_print(zvni
, (void *)args
);
4794 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4795 json
, JSON_C_TO_STRING_PRETTY
));
4796 json_object_free(json
);
4800 /* Display all global details for EVPN */
4801 void zebra_vxlan_print_evpn(struct vty
*vty
, uint8_t uj
)
4806 json_object
*json
= NULL
;
4807 struct zebra_ns
*zns
= NULL
;
4808 struct zebra_vrf
*zvrf
= NULL
;
4810 if (!is_evpn_enabled())
4813 zns
= zebra_ns_lookup(NS_DEFAULT
);
4817 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
4821 num_l3vnis
= hashcount(zns
->l3vni_table
);
4822 num_l2vnis
= hashcount(zvrf
->vni_table
);
4823 num_vnis
= num_l2vnis
+ num_l3vnis
;
4826 json
= json_object_new_object();
4827 json_object_string_add(json
, "advertiseGatewayMacip",
4828 zvrf
->advertise_gw_macip
? "Yes" : "No");
4829 json_object_int_add(json
, "numVnis", num_vnis
);
4830 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4831 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4833 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
4834 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
4835 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
4836 zvrf
->advertise_gw_macip
? "Yes" : "No");
4840 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4841 json
, JSON_C_TO_STRING_PRETTY
));
4842 json_object_free(json
);
4847 * Display VNI hash table (VTY command handler).
4849 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4852 json_object
*json
= NULL
;
4853 struct zebra_ns
*zns
= NULL
;
4856 if (!is_evpn_enabled())
4859 zns
= zebra_ns_lookup(NS_DEFAULT
);
4865 json
= json_object_new_object();
4867 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
4868 "Type", "VxLAN IF", "# MACs", "# ARPs",
4869 "# Remote VTEPs", "Tenant VRF");
4874 /* Display all L2-VNIs */
4875 hash_iterate(zvrf
->vni_table
,
4876 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
4879 /* Display all L3-VNIs */
4880 hash_iterate(zns
->l3vni_table
,
4881 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
4885 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4886 json
, JSON_C_TO_STRING_PRETTY
));
4887 json_object_free(json
);
4892 * Handle neighbor delete notification from the kernel (on a VLAN device
4893 * / L3 interface). This may result in either the neighbor getting deleted
4894 * from our database or being re-added to the kernel (if it is a valid
4897 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
4898 struct interface
*link_if
,
4901 char buf
[INET6_ADDRSTRLEN
];
4902 char buf2
[ETHER_ADDR_STRLEN
];
4903 zebra_neigh_t
*n
= NULL
;
4904 zebra_vni_t
*zvni
= NULL
;
4905 zebra_mac_t
*zmac
= NULL
;
4906 zebra_l3vni_t
*zl3vni
= NULL
;
4908 /* check if this is a remote neigh entry corresponding to remote
4911 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4913 return zl3vni_local_nh_del(zl3vni
, ip
);
4915 /* We are only interested in neighbors on an SVI that resides on top
4916 * of a VxLAN bridge.
4918 zvni
= zvni_from_svi(ifp
, link_if
);
4922 if (!zvni
->vxlan_if
) {
4924 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
4929 if (IS_ZEBRA_DEBUG_VXLAN
)
4930 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
4931 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
4932 ifp
->ifindex
, zvni
->vni
);
4934 /* If entry doesn't exist, nothing to do. */
4935 n
= zvni_neigh_lookup(zvni
, ip
);
4939 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
4941 if (IS_ZEBRA_DEBUG_VXLAN
)
4943 "Trying to del a neigh %s without a mac %s on VNI %u",
4944 ipaddr2str(ip
, buf
, sizeof(buf
)),
4945 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
4951 /* If it is a remote entry, the kernel has aged this out or someone has
4952 * deleted it, it needs to be re-installed as Quagga is the owner.
4954 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
4955 zvni_neigh_install(zvni
, n
);
4959 /* Remove neighbor from BGP. */
4960 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
4961 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0);
4963 /* Delete this neighbor entry. */
4964 zvni_neigh_del(zvni
, n
);
4966 /* see if the AUTO mac needs to be deleted */
4967 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
4968 && !listcount(zmac
->neigh_list
))
4969 zvni_mac_del(zvni
, zmac
);
4975 * Handle neighbor add or update notification from the kernel (on a VLAN
4976 * device / L3 interface). This is typically for a local neighbor but can
4977 * also be for a remote neighbor (e.g., ageout notification). It could
4978 * also be a "move" scenario.
4980 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
4981 struct interface
*link_if
,
4983 struct ethaddr
*macaddr
,
4985 uint8_t ext_learned
,
4986 uint8_t router_flag
)
4988 char buf
[ETHER_ADDR_STRLEN
];
4989 char buf2
[INET6_ADDRSTRLEN
];
4990 zebra_vni_t
*zvni
= NULL
;
4991 zebra_l3vni_t
*zl3vni
= NULL
;
4993 /* check if this is a remote neigh entry corresponding to remote
4996 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4998 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
5000 /* We are only interested in neighbors on an SVI that resides on top
5001 * of a VxLAN bridge.
5003 zvni
= zvni_from_svi(ifp
, link_if
);
5007 if (IS_ZEBRA_DEBUG_VXLAN
)
5009 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u",
5010 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
5011 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5012 ifp
->ifindex
, state
, ext_learned
? "ext-learned " : "",
5015 /* Is this about a local neighbor or a remote one? */
5017 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
5020 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
5025 * Handle message from client to delete a remote MACIP for a VNI.
5027 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
5031 struct ethaddr macaddr
;
5033 struct in_addr vtep_ip
;
5037 unsigned short l
= 0, ipa_len
;
5038 char buf
[ETHER_ADDR_STRLEN
];
5039 char buf1
[INET6_ADDRSTRLEN
];
5040 struct interface
*ifp
= NULL
;
5041 struct zebra_if
*zif
= NULL
;
5043 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5044 memset(&ip
, 0, sizeof(struct ipaddr
));
5045 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5049 while (l
< hdr
->length
) {
5050 /* Obtain each remote MACIP and process. */
5051 /* Message contains VNI, followed by MAC followed by IP (if any)
5052 * followed by remote VTEP IP.
5056 memset(&ip
, 0, sizeof(ip
));
5057 STREAM_GETL(s
, vni
);
5058 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5059 STREAM_GETL(s
, ipa_len
);
5061 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5063 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5065 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5066 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5067 l
+= IPV4_MAX_BYTELEN
;
5069 if (IS_ZEBRA_DEBUG_VXLAN
)
5071 "Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
5072 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5073 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5075 zebra_route_string(client
->proto
));
5077 /* Locate VNI hash entry - expected to exist. */
5078 zvni
= zvni_lookup(vni
);
5080 if (IS_ZEBRA_DEBUG_VXLAN
)
5082 "Failed to locate VNI hash upon remote MACIP DEL, "
5087 ifp
= zvni
->vxlan_if
;
5090 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
5096 /* If down or not mapped to a bridge, we're done. */
5097 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5100 /* The remote VTEP specified is normally expected to exist, but
5102 * possible that the peer may delete the VTEP before deleting
5104 * referring to the VTEP, in which case the handler (see
5106 * would have already deleted the MACs.
5108 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5111 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5113 n
= zvni_neigh_lookup(zvni
, &ip
);
5116 zlog_err("Failed to locate MAC %s for neigh %s VNI %u",
5117 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5118 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5122 /* If the remote mac or neighbor doesn't exist there is nothing
5124 * to do. Otherwise, uninstall the entry and then remove it.
5129 /* Ignore the delete if this mac is a gateway mac-ip */
5130 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5131 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5133 "%u: Ignore Del for MAC %s neigh %s on VNI %u as it is configured as a default gateway",
5135 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5136 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5140 /* Uninstall remote neighbor or MAC. */
5142 /* When the MAC changes for an IP, it is possible the
5144 * update the new MAC before trying to delete the "old"
5146 * (as these are two different MACIP routes). Do the
5148 * if the MAC matches.
5150 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5151 && (memcmp(n
->emac
.octet
, macaddr
.octet
, ETH_ALEN
)
5153 zvni_neigh_uninstall(zvni
, n
);
5154 zvni_neigh_del(zvni
, n
);
5155 zvni_deref_ip2mac(zvni
, mac
, 1);
5158 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5159 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5161 if (list_isempty(mac
->neigh_list
)) {
5162 zvni_mac_uninstall(zvni
, mac
, 0);
5163 zvni_mac_del(zvni
, mac
);
5165 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5175 * Handle message from client to add a remote MACIP for a VNI. This
5176 * could be just the add of a MAC address or the add of a neighbor
5179 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
5183 struct ethaddr macaddr
;
5185 struct in_addr vtep_ip
;
5187 zebra_vtep_t
*zvtep
;
5188 zebra_mac_t
*mac
, *old_mac
;
5190 unsigned short l
= 0, ipa_len
;
5191 int update_mac
= 0, update_neigh
= 0;
5192 char buf
[ETHER_ADDR_STRLEN
];
5193 char buf1
[INET6_ADDRSTRLEN
];
5195 u_char remote_gw
= 0;
5197 struct interface
*ifp
= NULL
;
5198 struct zebra_if
*zif
= NULL
;
5200 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5201 memset(&ip
, 0, sizeof(struct ipaddr
));
5202 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5204 if (!EVPN_ENABLED(zvrf
)) {
5206 "%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
5207 __PRETTY_FUNCTION__
);
5213 while (l
< hdr
->length
) {
5214 /* Obtain each remote MACIP and process. */
5215 /* Message contains VNI, followed by MAC followed by IP (if any)
5216 * followed by remote VTEP IP.
5218 update_mac
= update_neigh
= 0;
5221 memset(&ip
, 0, sizeof(ip
));
5222 STREAM_GETL(s
, vni
);
5223 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5224 STREAM_GETL(s
, ipa_len
);
5226 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5228 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5230 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5231 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5232 l
+= IPV4_MAX_BYTELEN
;
5234 /* Get flags - sticky mac and/or gateway mac */
5235 STREAM_GETC(s
, flags
);
5236 sticky
= CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5237 remote_gw
= CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5240 if (IS_ZEBRA_DEBUG_VXLAN
)
5242 "Recv MACIP Add MAC %s IP %s VNI %u Remote VTEP %s with flags 0x%x from %s",
5243 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5244 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5245 inet_ntoa(vtep_ip
), flags
,
5246 zebra_route_string(client
->proto
));
5248 /* Locate VNI hash entry - expected to exist. */
5249 zvni
= zvni_lookup(vni
);
5252 "Failed to locate VNI hash upon remote MACIP ADD, VNI %u",
5256 ifp
= zvni
->vxlan_if
;
5259 "VNI %u hash %p doesn't have intf upon remote MACIP add",
5265 /* If down or not mapped to a bridge, we're done. */
5266 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5269 /* The remote VTEP specified should normally exist, but it is
5271 * that when peering comes up, peer may advertise MACIP routes
5273 * advertising type-3 routes.
5275 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5277 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5279 "Failed to add remote VTEP, VNI %u zvni %p",
5284 zvni_vtep_install(zvni
, &vtep_ip
);
5287 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5289 /* Ignore the update if the mac is already present
5291 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)
5292 && CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5293 if (IS_ZEBRA_DEBUG_VXLAN
)
5295 "%u:Ignore MAC %s IP %s on VNI %u as MAC is already configured as gateway mac",
5297 prefix_mac2str(&macaddr
, buf
,
5299 ipaddr2str(&ip
, buf1
, sizeof(buf1
)),
5304 /* check if the remote MAC is unknown or has a change.
5305 * If so, that needs to be updated first. Note that client could
5306 * install MAC and MACIP separately or just install the latter.
5308 if (!mac
|| !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5309 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0)
5311 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
) ? 1 : 0)
5313 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
))
5318 mac
= zvni_mac_add(zvni
, &macaddr
);
5321 "Failed to add MAC %s VNI %u Remote VTEP %s",
5322 prefix_mac2str(&macaddr
, buf
,
5324 vni
, inet_ntoa(vtep_ip
));
5328 /* Is this MAC created for a MACIP? */
5330 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5333 /* Set "auto" and "remote" forwarding info. */
5334 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5335 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5336 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5337 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5340 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5342 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5345 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5347 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5349 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5351 /* Install the entry. */
5352 zvni_mac_install(zvni
, mac
);
5355 /* If there is no IP, continue - after clearing AUTO flag of
5358 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5362 /* Check if the remote neighbor itself is unknown or has a
5364 * If so, create or update and then install the entry.
5366 n
= zvni_neigh_lookup(zvni
, &ip
);
5367 if (!n
|| !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5368 || (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
)) != 0)
5369 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
))
5374 n
= zvni_neigh_add(zvni
, &ip
, &macaddr
);
5377 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5378 ipaddr2str(&ip
, buf1
,
5380 prefix_mac2str(&macaddr
, buf
,
5382 vni
, inet_ntoa(vtep_ip
));
5386 } else if (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
))
5388 /* MAC change, update neigh list for old and new
5390 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5392 listnode_delete(old_mac
->neigh_list
, n
);
5393 zvni_deref_ip2mac(zvni
, old_mac
, 1);
5395 listnode_add_sort(mac
->neigh_list
, n
);
5396 memcpy(&n
->emac
, &macaddr
, ETH_ALEN
);
5399 /* Set "remote" forwarding info. */
5400 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5401 /* TODO: Handle MAC change. */
5402 n
->r_vtep_ip
= vtep_ip
;
5403 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5405 /* Set router flag (R-bit) to this Neighbor entry */
5406 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5407 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5409 /* Install the entry. */
5410 zvni_neigh_install(zvni
, n
);
5419 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5420 * us, this must involve a multihoming scenario. Treat this as implicit delete
5421 * of any prior local MAC.
5423 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
5424 struct interface
*br_if
,
5425 struct ethaddr
*macaddr
, vlanid_t vid
)
5427 struct zebra_if
*zif
;
5428 struct zebra_l2info_vxlan
*vxl
;
5432 char buf
[ETHER_ADDR_STRLEN
];
5436 vxl
= &zif
->l2info
.vxl
;
5439 /* Check if EVPN is enabled. */
5440 if (!is_evpn_enabled())
5443 /* Locate hash entry; it is expected to exist. */
5444 zvni
= zvni_lookup(vni
);
5448 /* If entry doesn't exist, nothing to do. */
5449 mac
= zvni_mac_lookup(zvni
, macaddr
);
5453 /* Is it a local entry? */
5454 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5457 if (IS_ZEBRA_DEBUG_VXLAN
)
5459 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5460 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5463 /* Remove MAC from BGP. */
5464 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5467 * If there are no neigh associated with the mac delete the mac
5468 * else mark it as AUTO for forward reference
5470 if (!listcount(mac
->neigh_list
)) {
5471 zvni_mac_del(zvni
, mac
);
5473 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5474 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5481 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5482 * This can happen because the remote MAC entries are also added as "dynamic",
5483 * so the kernel can ageout the entry.
5485 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
5486 struct interface
*br_if
,
5487 struct ethaddr
*macaddr
, vlanid_t vid
)
5489 struct zebra_if
*zif
= NULL
;
5490 struct zebra_l2info_vxlan
*vxl
= NULL
;
5492 zebra_vni_t
*zvni
= NULL
;
5493 zebra_l3vni_t
*zl3vni
= NULL
;
5494 zebra_mac_t
*mac
= NULL
;
5495 char buf
[ETHER_ADDR_STRLEN
];
5499 vxl
= &zif
->l2info
.vxl
;
5502 /* Check if EVPN is enabled. */
5503 if (!is_evpn_enabled())
5506 /* check if this is a remote RMAC and readd simillar to remote macs */
5507 zl3vni
= zl3vni_lookup(vni
);
5509 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
5511 /* Locate hash entry; it is expected to exist. */
5512 zvni
= zvni_lookup(vni
);
5516 /* If entry doesn't exist, nothing to do. */
5517 mac
= zvni_mac_lookup(zvni
, macaddr
);
5521 /* Is it a remote entry? */
5522 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
5525 if (IS_ZEBRA_DEBUG_VXLAN
)
5526 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
5527 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5530 zvni_mac_install(zvni
, mac
);
5535 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
5537 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
5538 struct ethaddr
*macaddr
, vlanid_t vid
)
5542 char buf
[ETHER_ADDR_STRLEN
];
5544 /* We are interested in MACs only on ports or (port, VLAN) that
5547 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5550 if (!zvni
->vxlan_if
) {
5551 zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL",
5556 if (IS_ZEBRA_DEBUG_VXLAN
)
5557 zlog_debug("Del MAC %s intf %s(%u) VID %u -> VNI %u",
5558 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5559 ifp
->ifindex
, vid
, zvni
->vni
);
5561 /* If entry doesn't exist, nothing to do. */
5562 mac
= zvni_mac_lookup(zvni
, macaddr
);
5566 /* Is it a local entry? */
5567 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5570 /* Remove MAC from BGP. */
5571 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5573 /* Update all the neigh entries associated with this mac */
5574 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
5577 * If there are no neigh associated with the mac delete the mac
5578 * else mark it as AUTO for forward reference
5580 if (!listcount(mac
->neigh_list
)) {
5581 zvni_mac_del(zvni
, mac
);
5583 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5584 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5591 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
5593 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
5594 struct interface
*br_if
,
5595 struct ethaddr
*macaddr
, vlanid_t vid
,
5600 char buf
[ETHER_ADDR_STRLEN
];
5604 /* We are interested in MACs only on ports or (port, VLAN) that
5607 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5609 if (IS_ZEBRA_DEBUG_VXLAN
)
5611 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5612 sticky
? "sticky " : "",
5613 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5614 ifp
->name
, ifp
->ifindex
, vid
);
5618 if (!zvni
->vxlan_if
) {
5619 zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD",
5624 if (IS_ZEBRA_DEBUG_VXLAN
)
5625 zlog_debug("Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
5626 sticky
? "sticky " : "",
5627 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5628 ifp
->ifindex
, vid
, zvni
->vni
);
5630 /* If same entry already exists, nothing to do. */
5631 mac
= zvni_mac_lookup(zvni
, macaddr
);
5633 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5634 mac_sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5640 * return if nothing has changed.
5641 * inform bgp if sticky flag has changed
5642 * update locally and do not inform bgp if local
5643 * parameters like interface has changed
5645 if (mac_sticky
== sticky
5646 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
5647 && mac
->fwd_info
.local
.vid
== vid
) {
5648 if (IS_ZEBRA_DEBUG_VXLAN
)
5650 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
5651 "entry exists and has not changed ",
5652 sticky
? "sticky " : "",
5653 prefix_mac2str(macaddr
, buf
,
5655 ifp
->name
, ifp
->ifindex
, vid
,
5658 } else if (mac_sticky
!= sticky
) {
5661 add
= 0; /* This is an update of local
5664 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5666 * If we have already learned the MAC as a remote sticky
5668 * this is a operator error and we must log a warning
5670 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
5672 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
5673 prefix_mac2str(macaddr
, buf
,
5675 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
5683 mac
= zvni_mac_add(zvni
, macaddr
);
5685 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
5686 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5687 ifp
->name
, ifp
->ifindex
, vid
);
5692 /* Set "local" forwarding info. */
5693 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5694 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5695 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5696 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5697 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
5698 mac
->fwd_info
.local
.vid
= vid
;
5701 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5703 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5705 /* Inform BGP if required. */
5707 zvni_process_neigh_on_local_mac_add(zvni
, mac
);
5708 return zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
5716 * Handle message from client to delete a remote VTEP for a VNI.
5718 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
5721 unsigned short l
= 0;
5723 struct in_addr vtep_ip
;
5725 zebra_vtep_t
*zvtep
;
5726 struct interface
*ifp
;
5727 struct zebra_if
*zif
;
5729 if (!is_evpn_enabled()) {
5731 "%s: EVPN is not enabled yet we have received a vtep del command",
5732 __PRETTY_FUNCTION__
);
5736 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5737 zlog_err("Recv MACIP DEL for non-default VRF %u",
5744 while (l
< hdr
->length
) {
5745 /* Obtain each remote VTEP and process. */
5746 STREAM_GETL(s
, vni
);
5748 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5749 l
+= IPV4_MAX_BYTELEN
;
5751 if (IS_ZEBRA_DEBUG_VXLAN
)
5752 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
5753 inet_ntoa(vtep_ip
), vni
,
5754 zebra_route_string(client
->proto
));
5756 /* Locate VNI hash entry - expected to exist. */
5757 zvni
= zvni_lookup(vni
);
5759 if (IS_ZEBRA_DEBUG_VXLAN
)
5761 "Failed to locate VNI hash upon remote VTEP DEL, "
5767 ifp
= zvni
->vxlan_if
;
5770 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
5776 /* If down or not mapped to a bridge, we're done. */
5777 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5780 /* If the remote VTEP does not exist, there's nothing more to
5782 * Otherwise, uninstall any remote MACs pointing to this VTEP
5784 * then, the VTEP entry itself and remove it.
5786 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5790 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
5791 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
5792 zvni_vtep_uninstall(zvni
, &vtep_ip
);
5793 zvni_vtep_del(zvni
, zvtep
);
5801 * Handle message from client to add a remote VTEP for a VNI.
5803 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
5806 unsigned short l
= 0;
5808 struct in_addr vtep_ip
;
5810 struct interface
*ifp
;
5811 struct zebra_if
*zif
;
5813 if (!is_evpn_enabled()) {
5815 "%s: EVPN not enabled yet we received a vtep_add zapi call",
5816 __PRETTY_FUNCTION__
);
5820 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5821 zlog_err("Recv MACIP ADD for non-default VRF %u",
5828 while (l
< hdr
->length
) {
5829 /* Obtain each remote VTEP and process. */
5830 STREAM_GETL(s
, vni
);
5832 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5833 l
+= IPV4_MAX_BYTELEN
;
5835 if (IS_ZEBRA_DEBUG_VXLAN
)
5836 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
5837 inet_ntoa(vtep_ip
), vni
,
5838 zebra_route_string(client
->proto
));
5840 /* Locate VNI hash entry - expected to exist. */
5841 zvni
= zvni_lookup(vni
);
5844 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
5849 ifp
= zvni
->vxlan_if
;
5852 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
5859 /* If down or not mapped to a bridge, we're done. */
5860 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5863 /* If the remote VTEP already exists,
5864 there's nothing more to do. */
5865 if (zvni_vtep_find(zvni
, &vtep_ip
))
5868 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5869 zlog_err("Failed to add remote VTEP, VNI %u zvni %p",
5874 zvni_vtep_install(zvni
, &vtep_ip
);
5882 * Add/Del gateway macip to evpn
5884 * 1. SVI interface on a vlan aware bridge
5885 * 2. SVI interface on a vlan unaware bridge
5886 * 3. vrr interface (MACVLAN) associated to a SVI
5887 * We advertise macip routes for an interface if it is associated to VxLan vlan
5889 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
5893 struct ethaddr macaddr
;
5894 zebra_vni_t
*zvni
= NULL
;
5896 memset(&ip
, 0, sizeof(struct ipaddr
));
5897 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5899 /* Check if EVPN is enabled. */
5900 if (!is_evpn_enabled())
5903 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
5904 struct interface
*svi_if
=
5905 NULL
; /* SVI corresponding to the MACVLAN */
5906 struct zebra_if
*ifp_zif
=
5907 NULL
; /* Zebra daemon specific info for MACVLAN */
5908 struct zebra_if
*svi_if_zif
=
5909 NULL
; /* Zebra daemon specific info for SVI*/
5911 ifp_zif
= ifp
->info
;
5916 * for a MACVLAN interface the link represents the svi_if
5918 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
5919 ifp_zif
->link_ifindex
);
5921 zlog_err("MACVLAN %s(%u) without link information",
5922 ifp
->name
, ifp
->ifindex
);
5926 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
5928 * If it is a vlan aware bridge then the link gives the
5929 * bridge information
5931 struct interface
*svi_if_link
= NULL
;
5933 svi_if_zif
= svi_if
->info
;
5935 svi_if_link
= if_lookup_by_index_per_ns(
5936 zebra_ns_lookup(NS_DEFAULT
),
5937 svi_if_zif
->link_ifindex
);
5938 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
5940 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
5942 * If it is a vlan unaware bridge then svi is the bridge
5945 zvni
= zvni_from_svi(svi_if
, svi_if
);
5947 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
5948 struct zebra_if
*svi_if_zif
=
5949 NULL
; /* Zebra daemon specific info for SVI */
5950 struct interface
*svi_if_link
=
5951 NULL
; /* link info for the SVI = bridge info */
5953 svi_if_zif
= ifp
->info
;
5955 svi_if_link
= if_lookup_by_index_per_ns(
5956 zebra_ns_lookup(NS_DEFAULT
),
5957 svi_if_zif
->link_ifindex
);
5959 zvni
= zvni_from_svi(ifp
, svi_if_link
);
5961 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
5962 zvni
= zvni_from_svi(ifp
, ifp
);
5968 if (!zvni
->vxlan_if
) {
5969 zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
5975 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
5977 if (p
->family
== AF_INET
) {
5978 ip
.ipa_type
= IPADDR_V4
;
5979 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
5980 sizeof(struct in_addr
));
5981 } else if (p
->family
== AF_INET6
) {
5982 ip
.ipa_type
= IPADDR_V6
;
5983 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
5984 sizeof(struct in6_addr
));
5989 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
5991 zvni_gw_macip_del(ifp
, zvni
, &ip
);
5997 * Handle SVI interface going down.
5998 * SVI can be associated to either L3-VNI or L2-VNI.
5999 * For L2-VNI: At this point, this is a NOP since
6000 * the kernel deletes the neighbor entries on this SVI (if any).
6001 * We only need to update the vrf corresponding to zvni.
6002 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
6005 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
6007 zebra_l3vni_t
*zl3vni
= NULL
;
6009 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6012 /* process l3-vni down */
6013 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6015 /* remove association with svi-if */
6016 zl3vni
->svi_if
= NULL
;
6018 zebra_vni_t
*zvni
= NULL
;
6020 /* since we dont have svi corresponding to zvni, we associate it
6021 * to default vrf. Note: the corresponding neigh entries on the
6022 * SVI would have already been deleted */
6023 zvni
= zvni_from_svi(ifp
, link_if
);
6025 zvni
->vrf_id
= VRF_DEFAULT
;
6027 /* update the tenant vrf in BGP */
6028 zvni_send_add_to_client(zvni
);
6035 * Handle SVI interface coming up.
6036 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
6038 * For L2-VNI: we need to install any remote neighbors entried (used for
6040 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
6042 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
6044 zebra_vni_t
*zvni
= NULL
;
6045 zebra_l3vni_t
*zl3vni
= NULL
;
6047 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6050 /* associate with svi */
6051 zl3vni
->svi_if
= ifp
;
6053 /* process oper-up */
6054 if (is_l3vni_oper_up(zl3vni
))
6055 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6058 /* process SVI up for l2-vni */
6059 struct neigh_walk_ctx n_wctx
;
6061 zvni
= zvni_from_svi(ifp
, link_if
);
6065 if (!zvni
->vxlan_if
) {
6066 zlog_err("VNI %u hash %p doesn't have intf upon SVI up",
6071 if (IS_ZEBRA_DEBUG_VXLAN
)
6073 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
6074 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
6075 vrf_id_to_name(ifp
->vrf_id
));
6077 /* update the vrf information for l2-vni and inform bgp */
6078 zvni
->vrf_id
= ifp
->vrf_id
;
6079 zvni_send_add_to_client(zvni
);
6081 /* Install any remote neighbors for this VNI. */
6082 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6084 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6092 * Handle VxLAN interface down
6094 int zebra_vxlan_if_down(struct interface
*ifp
)
6097 struct zebra_if
*zif
= NULL
;
6098 struct zebra_l2info_vxlan
*vxl
= NULL
;
6099 zebra_l3vni_t
*zl3vni
= NULL
;
6102 /* Check if EVPN is enabled. */
6103 if (!is_evpn_enabled())
6108 vxl
= &zif
->l2info
.vxl
;
6111 zl3vni
= zl3vni_lookup(vni
);
6113 /* process-if-down for l3-vni */
6114 if (IS_ZEBRA_DEBUG_VXLAN
)
6115 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
6118 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6120 /* process if-down for l2-vni */
6121 if (IS_ZEBRA_DEBUG_VXLAN
)
6122 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
6125 /* Locate hash entry; it is expected to exist. */
6126 zvni
= zvni_lookup(vni
);
6129 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
6130 ifp
->name
, ifp
->ifindex
, vni
);
6134 assert(zvni
->vxlan_if
== ifp
);
6136 /* Delete this VNI from BGP. */
6137 zvni_send_del_to_client(zvni
->vni
);
6139 /* Free up all neighbors and MACs, if any. */
6140 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6141 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6143 /* Free up all remote VTEPs, if any. */
6144 zvni_vtep_del_all(zvni
, 1);
6150 * Handle VxLAN interface up - update BGP if required.
6152 int zebra_vxlan_if_up(struct interface
*ifp
)
6155 struct zebra_if
*zif
= NULL
;
6156 struct zebra_l2info_vxlan
*vxl
= NULL
;
6157 zebra_vni_t
*zvni
= NULL
;
6158 zebra_l3vni_t
*zl3vni
= NULL
;
6160 /* Check if EVPN is enabled. */
6161 if (!is_evpn_enabled())
6166 vxl
= &zif
->l2info
.vxl
;
6169 zl3vni
= zl3vni_lookup(vni
);
6172 if (IS_ZEBRA_DEBUG_VXLAN
)
6173 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
6176 /* we need to associate with SVI, if any, we can associate with
6177 * svi-if only after association with vxlan-intf is complete
6179 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6181 if (is_l3vni_oper_up(zl3vni
))
6182 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6184 /* Handle L2-VNI add */
6185 struct interface
*vlan_if
= NULL
;
6187 if (IS_ZEBRA_DEBUG_VXLAN
)
6188 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
6191 /* Locate hash entry; it is expected to exist. */
6192 zvni
= zvni_lookup(vni
);
6195 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
6196 ifp
->name
, ifp
->ifindex
, vni
);
6200 assert(zvni
->vxlan_if
== ifp
);
6201 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6202 zif
->brslave_info
.br_if
);
6204 zvni
->vrf_id
= vlan_if
->vrf_id
;
6205 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6207 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6210 /* If part of a bridge, inform BGP about this VNI. */
6211 /* Also, read and populate local MACs and neighbors. */
6212 if (zif
->brslave_info
.br_if
) {
6213 zvni_send_add_to_client(zvni
);
6214 zvni_read_mac_neigh(zvni
, ifp
);
6222 * Handle VxLAN interface delete. Locate and remove entry in hash table
6223 * and update BGP, if required.
6225 int zebra_vxlan_if_del(struct interface
*ifp
)
6228 struct zebra_if
*zif
= NULL
;
6229 struct zebra_l2info_vxlan
*vxl
= NULL
;
6230 zebra_vni_t
*zvni
= NULL
;
6231 zebra_l3vni_t
*zl3vni
= NULL
;
6233 /* Check if EVPN is enabled. */
6234 if (!is_evpn_enabled())
6239 vxl
= &zif
->l2info
.vxl
;
6242 zl3vni
= zl3vni_lookup(vni
);
6245 if (IS_ZEBRA_DEBUG_VXLAN
)
6246 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
6249 /* process oper-down for l3-vni */
6250 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6252 /* remove the association with vxlan_if */
6253 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
6254 zl3vni
->vxlan_if
= NULL
;
6257 /* process if-del for l2-vni*/
6258 if (IS_ZEBRA_DEBUG_VXLAN
)
6259 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
6262 /* Locate hash entry; it is expected to exist. */
6263 zvni
= zvni_lookup(vni
);
6266 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6267 ifp
->name
, ifp
->ifindex
, vni
);
6271 /* remove from l3-vni list */
6272 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
6274 listnode_delete(zl3vni
->l2vnis
, zvni
);
6276 /* Delete VNI from BGP. */
6277 zvni_send_del_to_client(zvni
->vni
);
6279 /* Free up all neighbors and MAC, if any. */
6280 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
6281 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
6283 /* Free up all remote VTEPs, if any. */
6284 zvni_vtep_del_all(zvni
, 0);
6286 /* Delete the hash entry. */
6287 if (zvni_del(zvni
)) {
6288 zlog_err("Failed to del VNI hash %p, IF %s(%u) VNI %u",
6289 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
6297 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6299 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
6302 struct zebra_if
*zif
= NULL
;
6303 struct zebra_l2info_vxlan
*vxl
= NULL
;
6304 zebra_vni_t
*zvni
= NULL
;
6305 zebra_l3vni_t
*zl3vni
= NULL
;
6307 /* Check if EVPN is enabled. */
6308 if (!is_evpn_enabled())
6313 vxl
= &zif
->l2info
.vxl
;
6316 zl3vni
= zl3vni_lookup(vni
);
6319 if (IS_ZEBRA_DEBUG_VXLAN
)
6321 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6322 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6323 inet_ntoa(vxl
->vtep_ip
),
6324 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6326 /* Removed from bridge? Cleanup and return */
6327 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6328 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6329 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6333 /* access-vlan change - process oper down, associate with new
6334 * svi_if and then process oper up again
6336 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6337 if (if_is_operative(ifp
)) {
6338 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6339 zl3vni
->svi_if
= NULL
;
6340 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6341 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6342 if (is_l3vni_oper_up(zl3vni
))
6343 zebra_vxlan_process_l3vni_oper_up(
6349 * local-ip change - process oper down, associate with new
6350 * local-ip and then process oper up again
6352 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
6353 if (if_is_operative(ifp
)) {
6354 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6355 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6356 if (is_l3vni_oper_up(zl3vni
))
6357 zebra_vxlan_process_l3vni_oper_up(
6362 /* Update local tunnel IP. */
6363 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6365 /* if we have a valid new master, process l3-vni oper up */
6366 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
6367 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
6368 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6372 /* Update VNI hash. */
6373 zvni
= zvni_lookup(vni
);
6376 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6377 ifp
->name
, ifp
->ifindex
, vni
);
6381 if (IS_ZEBRA_DEBUG_VXLAN
)
6383 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6384 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6385 inet_ntoa(vxl
->vtep_ip
),
6386 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6388 /* Removed from bridge? Cleanup and return */
6389 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6390 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6391 /* Delete from client, remove all remote VTEPs */
6392 /* Also, free up all MACs and neighbors. */
6393 zvni_send_del_to_client(zvni
->vni
);
6394 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6395 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6396 zvni_vtep_del_all(zvni
, 1);
6400 /* Handle other changes. */
6401 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6402 /* Remove all existing local neigh and MACs for this VNI
6403 * (including from BGP)
6405 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6406 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6409 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6410 zvni
->vxlan_if
= ifp
;
6412 /* Take further actions needed.
6413 * Note that if we are here, there is a change of interest.
6415 /* If down or not mapped to a bridge, we're done. */
6416 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6419 /* Inform BGP, if there is a change of interest. */
6421 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
6422 zvni_send_add_to_client(zvni
);
6424 /* If there is a valid new master or a VLAN mapping change,
6425 * read and populate local MACs and neighbors.
6426 * Also, reinstall any remote MACs and neighbors
6427 * for this VNI (based on new VLAN).
6429 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6430 zvni_read_mac_neigh(zvni
, ifp
);
6431 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6432 struct mac_walk_ctx m_wctx
;
6433 struct neigh_walk_ctx n_wctx
;
6435 zvni_read_mac_neigh(zvni
, ifp
);
6437 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6439 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
6442 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6444 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6453 * Handle VxLAN interface add.
6455 int zebra_vxlan_if_add(struct interface
*ifp
)
6458 struct zebra_if
*zif
= NULL
;
6459 struct zebra_l2info_vxlan
*vxl
= NULL
;
6460 zebra_vni_t
*zvni
= NULL
;
6461 zebra_l3vni_t
*zl3vni
= NULL
;
6463 /* Check if EVPN is enabled. */
6464 if (!is_evpn_enabled())
6469 vxl
= &zif
->l2info
.vxl
;
6472 zl3vni
= zl3vni_lookup(vni
);
6475 /* process if-add for l3-vni*/
6476 if (IS_ZEBRA_DEBUG_VXLAN
)
6478 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6479 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6480 inet_ntoa(vxl
->vtep_ip
),
6481 zif
->brslave_info
.bridge_ifindex
);
6483 /* associate with vxlan_if */
6484 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6485 zl3vni
->vxlan_if
= ifp
;
6487 /* Associate with SVI, if any. We can associate with svi-if only
6488 * after association with vxlan_if is complete */
6489 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6491 if (is_l3vni_oper_up(zl3vni
))
6492 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6495 /* process if-add for l2-vni */
6496 struct interface
*vlan_if
= NULL
;
6498 /* Create or update VNI hash. */
6499 zvni
= zvni_lookup(vni
);
6501 zvni
= zvni_add(vni
);
6504 "Failed to add VNI hash, IF %s(%u) VNI %u",
6505 ifp
->name
, ifp
->ifindex
, vni
);
6510 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6511 zvni
->vxlan_if
= ifp
;
6512 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6513 zif
->brslave_info
.br_if
);
6515 zvni
->vrf_id
= vlan_if
->vrf_id
;
6516 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6518 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6521 if (IS_ZEBRA_DEBUG_VXLAN
)
6523 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6525 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
6527 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6528 inet_ntoa(vxl
->vtep_ip
),
6529 zif
->brslave_info
.bridge_ifindex
);
6531 /* If down or not mapped to a bridge, we're done. */
6532 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6536 zvni_send_add_to_client(zvni
);
6538 /* Read and populate local MACs and neighbors */
6539 zvni_read_mac_neigh(zvni
, ifp
);
6545 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
6546 char *err
, int err_str_sz
, int filter
,
6549 zebra_l3vni_t
*zl3vni
= NULL
;
6550 struct zebra_vrf
*zvrf_default
= NULL
;
6552 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
6556 if (IS_ZEBRA_DEBUG_VXLAN
)
6557 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
6558 add
? "ADD" : "DEL");
6562 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6564 /* check if the vni is already present under zvrf */
6566 snprintf(err
, err_str_sz
,
6567 "VNI is already configured under the vrf");
6571 /* check if this VNI is already present in the system */
6572 zl3vni
= zl3vni_lookup(vni
);
6574 snprintf(err
, err_str_sz
,
6575 "VNI is already configured as L3-VNI");
6579 /* add the L3-VNI to the global table */
6580 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
6582 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
6586 /* associate the vrf with vni */
6589 /* set the filter in l3vni to denote if we are using l3vni only
6593 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
6595 /* associate with vxlan-intf;
6596 * we need to associate with the vxlan-intf first
6598 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
6600 /* associate with corresponding SVI interface, we can associate
6601 * with svi-if only after vxlan interface association is
6604 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6606 /* formulate l2vni list */
6607 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
6610 if (is_l3vni_oper_up(zl3vni
))
6611 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6614 zl3vni
= zl3vni_lookup(vni
);
6616 snprintf(err
, err_str_sz
, "VNI doesn't exist");
6620 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
6621 snprintf(err
, ERR_STR_SZ
,
6622 "prefix-routes-only is not set for the vni");
6626 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6628 /* delete and uninstall all rmacs */
6629 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
6632 /* delete and uninstall all next-hops */
6633 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
6639 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6644 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
6646 zebra_l3vni_t
*zl3vni
= NULL
;
6649 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6653 zl3vni
->vrf_id
= zvrf_id(zvrf
);
6654 if (is_l3vni_oper_up(zl3vni
))
6655 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6659 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
6661 zebra_l3vni_t
*zl3vni
= NULL
;
6664 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6668 zl3vni
->vrf_id
= VRF_UNKNOWN
;
6669 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6673 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
6675 zebra_l3vni_t
*zl3vni
= NULL
;
6679 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6685 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
6691 * Handle message from client to enable/disable advertisement of g/w macip
6694 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
6699 zebra_vni_t
*zvni
= NULL
;
6700 struct interface
*ifp
= NULL
;
6701 struct zebra_if
*zif
= NULL
;
6702 struct zebra_l2info_vxlan zl2_info
;
6703 struct interface
*vlan_if
= NULL
;
6705 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6706 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6712 STREAM_GETC(s
, advertise
);
6713 vni
= stream_get3(s
);
6715 zvni
= zvni_lookup(vni
);
6719 if (zvni
->advertise_subnet
== advertise
)
6722 if (IS_ZEBRA_DEBUG_VXLAN
)
6723 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
6724 advertise
? "enabled" : "disabled", vni
,
6725 zvni
->advertise_subnet
? "enabled" : "disabled");
6728 zvni
->advertise_subnet
= advertise
;
6730 ifp
= zvni
->vxlan_if
;
6736 /* If down or not mapped to a bridge, we're done. */
6737 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6740 zl2_info
= zif
->l2info
.vxl
;
6743 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
6747 if (zvni
->advertise_subnet
)
6748 zvni_advertise_subnet(zvni
, vlan_if
, 1);
6750 zvni_advertise_subnet(zvni
, vlan_if
, 0);
6757 * Handle message from client to enable/disable advertisement of g/w macip
6760 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
6765 zebra_vni_t
*zvni
= NULL
;
6766 struct interface
*ifp
= NULL
;
6768 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6769 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6775 STREAM_GETC(s
, advertise
);
6776 STREAM_GETL(s
, vni
);
6779 if (IS_ZEBRA_DEBUG_VXLAN
)
6780 zlog_debug("EVPN gateway macip Adv %s, currently %s",
6781 advertise
? "enabled" : "disabled",
6782 advertise_gw_macip_enabled(NULL
)
6786 if (zvrf
->advertise_gw_macip
== advertise
)
6789 zvrf
->advertise_gw_macip
= advertise
;
6791 if (advertise_gw_macip_enabled(zvni
))
6792 hash_iterate(zvrf
->vni_table
,
6793 zvni_gw_macip_add_for_vni_hash
, NULL
);
6795 hash_iterate(zvrf
->vni_table
,
6796 zvni_gw_macip_del_for_vni_hash
, NULL
);
6799 struct zebra_if
*zif
= NULL
;
6800 struct zebra_l2info_vxlan zl2_info
;
6801 struct interface
*vlan_if
= NULL
;
6802 struct interface
*vrr_if
= NULL
;
6804 zvni
= zvni_lookup(vni
);
6808 if (IS_ZEBRA_DEBUG_VXLAN
)
6810 "EVPN gateway macip Adv %s on VNI %d , currently %s",
6811 advertise
? "enabled" : "disabled", vni
,
6812 advertise_gw_macip_enabled(zvni
) ? "enabled"
6815 if (zvni
->advertise_gw_macip
== advertise
)
6818 zvni
->advertise_gw_macip
= advertise
;
6820 ifp
= zvni
->vxlan_if
;
6826 /* If down or not mapped to a bridge, we're done. */
6827 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6830 zl2_info
= zif
->l2info
.vxl
;
6832 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
6833 zif
->brslave_info
.br_if
);
6837 if (advertise_gw_macip_enabled(zvni
)) {
6838 /* Add primary SVI MAC-IP */
6839 zvni_add_macip_for_intf(vlan_if
, zvni
);
6841 /* Add VRR MAC-IP - if any*/
6842 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6844 zvni_add_macip_for_intf(vrr_if
, zvni
);
6846 /* Del primary MAC-IP */
6847 zvni_del_macip_for_intf(vlan_if
, zvni
);
6849 /* Del VRR MAC-IP - if any*/
6850 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6852 zvni_del_macip_for_intf(vrr_if
, zvni
);
6862 * Handle message from client to learn (or stop learning) about VNIs and MACs.
6863 * When enabled, the VNI hash table will be built and MAC FDB table read;
6864 * when disabled, the entries should be deleted and remote VTEPs and MACs
6865 * uninstalled from the kernel.
6867 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
6869 struct stream
*s
= NULL
;
6871 struct zebra_ns
*zns
= NULL
;
6873 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6874 zlog_err("EVPN VNI Adv for non-default VRF %u", zvrf_id(zvrf
));
6879 STREAM_GETC(s
, advertise
);
6881 if (IS_ZEBRA_DEBUG_VXLAN
)
6882 zlog_debug("EVPN VNI Adv %s, currently %s",
6883 advertise
? "enabled" : "disabled",
6884 is_evpn_enabled() ? "enabled" : "disabled");
6886 if (zvrf
->advertise_all_vni
== advertise
)
6889 zvrf
->advertise_all_vni
= advertise
;
6890 if (is_evpn_enabled()) {
6891 /* Build VNI hash table and inform BGP. */
6892 zvni_build_hash_table();
6894 /* Add all SVI (L3 GW) MACs to BGP*/
6895 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
6898 /* Read the MAC FDB */
6899 macfdb_read(zvrf
->zns
);
6901 /* Read neighbors */
6902 neigh_read(zvrf
->zns
);
6904 /* Cleanup VTEPs for all VNIs - uninstall from
6905 * kernel and free entries.
6907 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6909 /* cleanup all l3vnis */
6910 zns
= zebra_ns_lookup(NS_DEFAULT
);
6914 hash_iterate(zns
->l3vni_table
, zl3vni_cleanup_all
, NULL
);
6922 * Allocate VNI hash table for this VRF and do other initialization.
6923 * NOTE: Currently supported only for default VRF.
6925 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
6929 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
6930 "Zebra VRF VNI Table");
6933 /* Cleanup VNI info, but don't free the table. */
6934 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
6938 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6941 /* Close all VNI handling */
6942 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
6946 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6947 hash_free(zvrf
->vni_table
);
6950 /* init the l3vni table */
6951 void zebra_vxlan_ns_init(struct zebra_ns
*zns
)
6953 zns
->l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
6954 "Zebra VRF L3 VNI table");
6957 /* free l3vni table */
6958 void zebra_vxlan_ns_disable(struct zebra_ns
*zns
)
6960 hash_free(zns
->l3vni_table
);
6963 /* get the l3vni svi ifindex */
6964 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
6966 zebra_l3vni_t
*zl3vni
= NULL
;
6968 zl3vni
= zl3vni_from_vrf(vrf_id
);
6969 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
6972 return zl3vni
->svi_if
->ifindex
;