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_AUTO
))
255 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
257 struct zebra_vrf
*zvrf
;
259 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
260 if (zvrf
&& zvrf
->advertise_gw_macip
)
263 if (zvni
&& zvni
->advertise_gw_macip
)
270 * Helper function to determine maximum width of neighbor IP address for
271 * display - just because we're dealing with IPv6 addresses that can
274 static void zvni_find_neigh_addr_width(struct hash_backet
*backet
, void *ctxt
)
277 char buf
[INET6_ADDRSTRLEN
];
278 struct neigh_walk_ctx
*wctx
= ctxt
;
281 n
= (zebra_neigh_t
*)backet
->data
;
285 ipaddr2str(&n
->ip
, buf
, sizeof(buf
)), width
= strlen(buf
);
286 if (width
> wctx
->addr_width
)
287 wctx
->addr_width
= width
;
292 * Print a specific neighbor entry.
294 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
297 char buf1
[ETHER_ADDR_STRLEN
];
298 char buf2
[INET6_ADDRSTRLEN
];
300 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
301 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
302 vty
= (struct vty
*)ctxt
;
304 vty_out(vty
, "IP: %s\n",
305 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
306 vty_out(vty
, " MAC: %s",
307 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
309 json_object_string_add(json
, "ip", buf2
);
310 json_object_string_add(json
, "mac", buf1
);
312 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
314 vty_out(vty
, " Remote VTEP: %s",
315 inet_ntoa(n
->r_vtep_ip
));
317 json_object_string_add(json
, "remoteVtep",
318 inet_ntoa(n
->r_vtep_ip
));
320 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
323 vty_out(vty
, " State: %s",
324 IS_ZEBRA_NEIGH_ACTIVE(n
) ? "Active"
328 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
330 vty_out(vty
, " Default-gateway");
332 json_object_boolean_true_add(json
, "defaultGateway");
334 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
336 vty_out(vty
, " Router");
343 * Print neighbor hash entry - called for display of all neighbors.
345 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
348 json_object
*json_vni
= NULL
, *json_row
= NULL
;
350 char buf1
[ETHER_ADDR_STRLEN
];
351 char buf2
[INET6_ADDRSTRLEN
];
352 struct neigh_walk_ctx
*wctx
= ctxt
;
355 json_vni
= wctx
->json
;
356 n
= (zebra_neigh_t
*)backet
->data
;
361 json_row
= json_object_new_object();
363 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
364 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
365 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)
366 && !(wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)) {
367 if (json_vni
== NULL
) {
368 vty_out(vty
, "%*s %-6s %-17s\n", -wctx
->addr_width
,
369 buf2
, "local", buf1
);
371 json_object_string_add(json_row
, "type", "local");
372 json_object_string_add(json_row
, "mac", buf1
);
376 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) {
377 if (IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
)) {
378 if (json_vni
== NULL
) {
379 if (wctx
->count
== 0)
381 "%*s %-6s %-17s %-21s\n",
384 "MAC", "Remote VTEP");
385 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
386 -wctx
->addr_width
, buf2
,
388 inet_ntoa(n
->r_vtep_ip
));
390 json_object_string_add(json_row
, "type",
392 json_object_string_add(json_row
, "mac",
394 json_object_string_add(
395 json_row
, "remoteVtep",
396 inet_ntoa(n
->r_vtep_ip
));
401 if (json_vni
== NULL
) {
402 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
403 -wctx
->addr_width
, buf2
, "remote", buf1
,
404 inet_ntoa(n
->r_vtep_ip
));
406 json_object_string_add(json_row
, "type",
408 json_object_string_add(json_row
, "mac", buf1
);
409 json_object_string_add(json_row
, "remoteVtep",
410 inet_ntoa(n
->r_vtep_ip
));
417 json_object_object_add(json_vni
, buf2
, json_row
);
421 * Print neighbors for all VNI.
423 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
427 json_object
*json
= NULL
, *json_vni
= NULL
;
430 struct neigh_walk_ctx wctx
;
431 char vni_str
[VNI_STR_LEN
];
433 vty
= (struct vty
*)args
[0];
434 json
= (json_object
*)args
[1];
436 zvni
= (zebra_vni_t
*)backet
->data
;
439 vty_out(vty
, "{}\n");
442 num_neigh
= hashcount(zvni
->neigh_table
);
445 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
446 zvni
->vni
, num_neigh
);
448 json_vni
= json_object_new_object();
449 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
450 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
454 json_object_object_add(json
, vni_str
, json_vni
);
458 /* Since we have IPv6 addresses to deal with which can vary widely in
459 * size, we try to be a bit more elegant in display by first computing
462 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
465 wctx
.addr_width
= 15;
466 wctx
.json
= json_vni
;
467 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
470 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
471 "Type", "MAC", "Remote VTEP");
473 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
476 json_object_object_add(json
, vni_str
, json_vni
);
479 /* print a specific next hop for an l3vni */
480 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
483 char buf1
[ETHER_ADDR_STRLEN
];
484 char buf2
[INET6_ADDRSTRLEN
];
485 json_object
*json_hosts
= NULL
;
486 struct host_rb_entry
*hle
;
489 vty_out(vty
, "Ip: %s\n",
490 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
491 vty_out(vty
, " RMAC: %s\n",
492 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
493 vty_out(vty
, " Refcount: %d\n",
494 rb_host_count(&n
->host_rb
));
495 vty_out(vty
, " Prefixes:\n");
496 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
497 vty_out(vty
, " %s\n",
498 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
500 json_hosts
= json_object_new_array();
501 json_object_string_add(
502 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
503 json_object_string_add(
505 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
506 json_object_int_add(json
, "refCount",
507 rb_host_count(&n
->host_rb
));
508 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
509 json_object_array_add(json_hosts
,
510 json_object_new_string(prefix2str(
511 &hle
->p
, buf2
, sizeof(buf2
))));
512 json_object_object_add(json
, "prefixList", json_hosts
);
516 /* Print a specific RMAC entry */
517 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
520 char buf1
[ETHER_ADDR_STRLEN
];
521 char buf2
[PREFIX_STRLEN
];
522 json_object
*json_hosts
= NULL
;
523 struct host_rb_entry
*hle
;
526 vty_out(vty
, "MAC: %s\n",
527 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
528 vty_out(vty
, " Remote VTEP: %s\n",
529 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
530 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
531 vty_out(vty
, " Prefixes:\n");
532 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
533 vty_out(vty
, " %s\n",
534 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
536 json_hosts
= json_object_new_array();
537 json_object_string_add(
539 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
540 json_object_string_add(json
, "vtepIp",
541 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
542 json_object_int_add(json
, "refCount",
543 rb_host_count(&zrmac
->host_rb
));
544 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
545 json_object_array_add(
547 json_object_new_string(prefix2str(
548 &hle
->p
, buf2
, sizeof(buf2
))));
549 json_object_object_add(json
, "prefixList", json_hosts
);
554 * Print a specific MAC entry.
556 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
)
559 zebra_neigh_t
*n
= NULL
;
560 struct listnode
*node
= NULL
;
562 char buf2
[INET6_ADDRSTRLEN
];
564 vty
= (struct vty
*)ctxt
;
565 vty_out(vty
, "MAC: %s",
566 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
)));
567 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
568 struct zebra_ns
*zns
;
569 struct interface
*ifp
;
572 ifindex
= mac
->fwd_info
.local
.ifindex
;
573 zns
= zebra_ns_lookup(NS_DEFAULT
);
574 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
575 if (!ifp
) // unexpected
577 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
578 if (mac
->fwd_info
.local
.vid
)
579 vty_out(vty
, " VLAN: %u", mac
->fwd_info
.local
.vid
);
580 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
581 vty_out(vty
, " Remote VTEP: %s",
582 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
583 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
584 vty_out(vty
, " Auto Mac ");
587 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
588 vty_out(vty
, " Sticky Mac ");
590 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
591 vty_out(vty
, " Default-gateway Mac ");
593 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
594 vty_out(vty
, " Remote-gateway Mac ");
597 /* print all the associated neigh */
598 vty_out(vty
, " Neighbors:\n");
599 if (!listcount(mac
->neigh_list
))
600 vty_out(vty
, " No Neighbors\n");
602 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
603 vty_out(vty
, " %s %s\n",
604 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
605 CHECK_FLAG(n
->flags
, ZEBRA_MAC_LOCAL
)
606 ? (IS_ZEBRA_NEIGH_ACTIVE(n
)
617 * Print MAC hash entry - called for display of all MACs.
619 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
622 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
625 struct mac_walk_ctx
*wctx
= ctxt
;
628 json_mac_hdr
= wctx
->json
;
629 mac
= (zebra_mac_t
*)backet
->data
;
633 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
636 json_mac
= json_object_new_object();
638 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
639 && !(wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)) {
640 struct zebra_ns
*zns
;
642 struct interface
*ifp
;
645 zns
= zebra_ns_lookup(NS_DEFAULT
);
646 ifindex
= mac
->fwd_info
.local
.ifindex
;
647 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
648 if (!ifp
) // unexpected
650 vid
= mac
->fwd_info
.local
.vid
;
651 if (json_mac_hdr
== NULL
)
652 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
655 json_object_string_add(json_mac
, "type", "local");
656 json_object_string_add(json_mac
, "intf", ifp
->name
);
659 if (json_mac_hdr
== NULL
)
660 vty_out(vty
, " %-5u", vid
);
662 json_object_int_add(json_mac
, "vlan", vid
);
664 if (json_mac_hdr
== NULL
)
667 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
669 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
670 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) {
671 if (IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
673 if (wctx
->count
== 0) {
674 if (json_mac_hdr
== NULL
) {
675 vty_out(vty
, "\nVNI %u\n\n",
678 "%-17s %-6s %-21s %-5s\n",
684 if (json_mac_hdr
== NULL
)
685 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
687 inet_ntoa(mac
->fwd_info
690 json_object_string_add(json_mac
, "type",
692 json_object_string_add(
693 json_mac
, "remoteVtep",
694 inet_ntoa(mac
->fwd_info
696 json_object_object_add(json_mac_hdr
,
702 if (json_mac_hdr
== NULL
)
703 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
705 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
707 json_object_string_add(json_mac
, "type",
709 json_object_string_add(
710 json_mac
, "remoteVtep",
711 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
712 json_object_object_add(json_mac_hdr
, buf1
,
721 * Print MACs for all VNI.
723 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
726 json_object
*json
= NULL
, *json_vni
= NULL
;
727 json_object
*json_mac
= NULL
;
730 struct mac_walk_ctx
*wctx
= ctxt
;
731 char vni_str
[VNI_STR_LEN
];
733 vty
= (struct vty
*)wctx
->vty
;
734 json
= (struct json_object
*)wctx
->json
;
736 zvni
= (zebra_vni_t
*)backet
->data
;
739 vty_out(vty
, "{}\n");
744 /*We are iterating over a new VNI, set the count to 0*/
747 num_macs
= num_valid_macs(zvni
);
752 json_vni
= json_object_new_object();
753 json_mac
= json_object_new_object();
754 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
757 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
759 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
760 zvni
->vni
, num_macs
);
761 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
762 "Intf/Remote VTEP", "VLAN");
764 json_object_int_add(json_vni
, "numMacs", num_macs
);
766 /* assign per-vni to wctx->json object to fill macs
767 * under the vni. Re-assign primary json object to fill
768 * next vni information.
770 wctx
->json
= json_mac
;
771 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
775 json_object_object_add(json_vni
, "macs", json_mac
);
776 json_object_object_add(json
, vni_str
, json_vni
);
780 static void zl3vni_print_nh_hash(struct hash_backet
*backet
, void *ctx
)
782 struct nh_walk_ctx
*wctx
= NULL
;
783 struct vty
*vty
= NULL
;
784 struct json_object
*json_vni
= NULL
;
785 struct json_object
*json_nh
= NULL
;
786 zebra_neigh_t
*n
= NULL
;
787 char buf1
[ETHER_ADDR_STRLEN
];
788 char buf2
[INET6_ADDRSTRLEN
];
790 wctx
= (struct nh_walk_ctx
*)ctx
;
792 json_vni
= wctx
->json
;
794 json_nh
= json_object_new_object();
795 n
= (zebra_neigh_t
*)backet
->data
;
800 vty_out(vty
, "%-15s %-17s\n",
801 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
802 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
804 json_object_string_add(json_nh
, "nexthopIp",
805 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
806 json_object_string_add(
807 json_nh
, "routerMac",
808 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
809 json_object_object_add(json_vni
,
810 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
815 static void zl3vni_print_nh_hash_all_vni(struct hash_backet
*backet
,
818 struct vty
*vty
= NULL
;
819 json_object
*json
= NULL
;
820 json_object
*json_vni
= NULL
;
821 zebra_l3vni_t
*zl3vni
= NULL
;
823 struct nh_walk_ctx wctx
;
824 char vni_str
[VNI_STR_LEN
];
826 vty
= (struct vty
*)args
[0];
827 json
= (struct json_object
*)args
[1];
829 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
832 vty_out(vty
, "{}\n");
836 num_nh
= hashcount(zl3vni
->nh_table
);
841 json_vni
= json_object_new_object();
842 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
846 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
847 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
849 json_object_int_add(json_vni
, "numNextHops", num_nh
);
851 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
853 wctx
.json
= json_vni
;
854 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
856 json_object_object_add(json
, vni_str
, json_vni
);
859 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet
*backet
,
862 struct vty
*vty
= NULL
;
863 json_object
*json
= NULL
;
864 json_object
*json_vni
= NULL
;
865 zebra_l3vni_t
*zl3vni
= NULL
;
867 struct rmac_walk_ctx wctx
;
868 char vni_str
[VNI_STR_LEN
];
870 vty
= (struct vty
*)args
[0];
871 json
= (struct json_object
*)args
[1];
873 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
876 vty_out(vty
, "{}\n");
880 num_rmacs
= hashcount(zl3vni
->rmac_table
);
885 json_vni
= json_object_new_object();
886 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
890 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
891 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
893 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
895 /* assign per-vni to wctx->json object to fill macs
896 * under the vni. Re-assign primary json object to fill
897 * next vni information.
899 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
901 wctx
.json
= json_vni
;
902 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
904 json_object_object_add(json
, vni_str
, json_vni
);
907 static void zl3vni_print_rmac_hash(struct hash_backet
*backet
, void *ctx
)
909 zebra_mac_t
*zrmac
= NULL
;
910 struct rmac_walk_ctx
*wctx
= NULL
;
911 struct vty
*vty
= NULL
;
912 struct json_object
*json
= NULL
;
913 struct json_object
*json_rmac
= NULL
;
914 char buf
[ETHER_ADDR_STRLEN
];
916 wctx
= (struct rmac_walk_ctx
*)ctx
;
920 json_rmac
= json_object_new_object();
921 zrmac
= (zebra_mac_t
*)backet
->data
;
926 vty_out(vty
, "%-17s %-21s\n",
927 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
928 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
930 json_object_string_add(
931 json_rmac
, "routerMac",
932 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
933 json_object_string_add(json_rmac
, "vtepIp",
934 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
935 json_object_object_add(
936 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
941 /* print a specific L3 VNI entry */
942 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
944 char buf
[ETHER_ADDR_STRLEN
];
945 struct vty
*vty
= NULL
;
946 json_object
*json
= NULL
;
947 zebra_vni_t
*zvni
= NULL
;
948 json_object
*json_vni_list
= NULL
;
949 struct listnode
*node
= NULL
, *nnode
= NULL
;
955 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
956 vty_out(vty
, " Type: %s\n", "L3");
957 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
958 vty_out(vty
, " Local Vtep Ip: %s\n",
959 inet_ntoa(zl3vni
->local_vtep_ip
));
960 vty_out(vty
, " Vxlan-Intf: %s\n",
961 zl3vni_vxlan_if_name(zl3vni
));
962 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
963 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
964 vty_out(vty
, " VNI Filter: %s\n",
965 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
966 ? "prefix-routes-only"
968 vty_out(vty
, " Router MAC: %s\n",
969 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
970 vty_out(vty
, " L2 VNIs: ");
971 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
972 vty_out(vty
, "%u ", zvni
->vni
);
975 json_vni_list
= json_object_new_array();
976 json_object_int_add(json
, "vni", zl3vni
->vni
);
977 json_object_string_add(json
, "type", "L3");
978 json_object_string_add(json
, "localVtepIp",
979 inet_ntoa(zl3vni
->local_vtep_ip
));
980 json_object_string_add(json
, "vxlanIntf",
981 zl3vni_vxlan_if_name(zl3vni
));
982 json_object_string_add(json
, "sviIntf",
983 zl3vni_svi_if_name(zl3vni
));
984 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
985 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
986 json_object_string_add(
988 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
989 json_object_string_add(
991 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
992 ? "prefix-routes-only"
994 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
995 json_object_array_add(json_vni_list
,
996 json_object_new_int(zvni
->vni
));
998 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1003 * Print a specific VNI entry.
1005 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1008 zebra_vtep_t
*zvtep
;
1011 json_object
*json
= NULL
;
1012 json_object
*json_vtep_list
= NULL
;
1013 json_object
*json_ip_str
= NULL
;
1019 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1020 vty_out(vty
, " Type: %s\n", "L2");
1021 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1023 json_object_int_add(json
, "vni", zvni
->vni
);
1024 json_object_string_add(json
, "type", "L2");
1025 json_object_string_add(json
, "vrf",
1026 vrf_id_to_name(zvni
->vrf_id
));
1029 if (!zvni
->vxlan_if
) { // unexpected
1031 vty_out(vty
, " VxLAN interface: unknown\n");
1034 num_macs
= num_valid_macs(zvni
);
1035 num_neigh
= hashcount(zvni
->neigh_table
);
1037 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1038 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1039 vty_out(vty
, " Local VTEP IP: %s\n",
1040 inet_ntoa(zvni
->local_vtep_ip
));
1042 json_object_string_add(json
, "vxlanInterface",
1043 zvni
->vxlan_if
->name
);
1044 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1045 json_object_string_add(json
, "vtepIp",
1046 inet_ntoa(zvni
->local_vtep_ip
));
1047 json_object_string_add(json
, "advertiseGatewayMacip",
1048 zvni
->advertise_gw_macip
? "Yes" : "No");
1049 json_object_int_add(json
, "numMacs", num_macs
);
1050 json_object_int_add(json
, "numArpNd", num_neigh
);
1054 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1057 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1059 json_vtep_list
= json_object_new_array();
1060 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1062 vty_out(vty
, " %s\n",
1063 inet_ntoa(zvtep
->vtep_ip
));
1065 json_ip_str
= json_object_new_string(
1066 inet_ntoa(zvtep
->vtep_ip
));
1067 json_object_array_add(json_vtep_list
,
1072 json_object_object_add(json
, "numRemoteVteps",
1077 " Number of MACs (local and remote) known for this VNI: %u\n",
1080 " Number of ARPs (IPv4 and IPv6, local and remote) "
1081 "known for this VNI: %u\n",
1083 vty_out(vty
, " Advertise-gw-macip: %s\n",
1084 zvni
->advertise_gw_macip
? "Yes" : "No");
1088 /* print a L3 VNI hash entry */
1089 static void zl3vni_print_hash(struct hash_backet
*backet
, void *ctx
[])
1091 struct vty
*vty
= NULL
;
1092 json_object
*json
= NULL
;
1093 json_object
*json_vni
= NULL
;
1094 zebra_l3vni_t
*zl3vni
= NULL
;
1096 vty
= (struct vty
*)ctx
[0];
1097 json
= (json_object
*)ctx
[1];
1099 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1104 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1105 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1106 hashcount(zl3vni
->rmac_table
),
1107 hashcount(zl3vni
->nh_table
), "n/a",
1108 zl3vni_vrf_name(zl3vni
));
1110 char vni_str
[VNI_STR_LEN
];
1112 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1113 json_vni
= json_object_new_object();
1114 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1115 json_object_string_add(json_vni
, "vxlanIf",
1116 zl3vni_vxlan_if_name(zl3vni
));
1117 json_object_int_add(json_vni
, "numMacs",
1118 hashcount(zl3vni
->rmac_table
));
1119 json_object_int_add(json_vni
, "numArpNd",
1120 hashcount(zl3vni
->nh_table
));
1121 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1122 json_object_string_add(json_vni
, "type", "L3");
1123 json_object_string_add(json_vni
, "tenantVrf",
1124 zl3vni_vrf_name(zl3vni
));
1125 json_object_object_add(json
, vni_str
, json_vni
);
1130 * Print a VNI hash entry - called for display of all VNIs.
1132 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1136 zebra_vtep_t
*zvtep
;
1137 uint32_t num_vteps
= 0;
1138 uint32_t num_macs
= 0;
1139 uint32_t num_neigh
= 0;
1140 json_object
*json
= NULL
;
1141 json_object
*json_vni
= NULL
;
1142 json_object
*json_ip_str
= NULL
;
1143 json_object
*json_vtep_list
= NULL
;
1148 zvni
= (zebra_vni_t
*)backet
->data
;
1152 zvtep
= zvni
->vteps
;
1155 zvtep
= zvtep
->next
;
1158 num_macs
= num_valid_macs(zvni
);
1159 num_neigh
= hashcount(zvni
->neigh_table
);
1161 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1163 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1164 num_macs
, num_neigh
, num_vteps
,
1165 vrf_id_to_name(zvni
->vrf_id
));
1167 char vni_str
[VNI_STR_LEN
];
1168 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1169 json_vni
= json_object_new_object();
1170 json_object_int_add(json_vni
, "vni", zvni
->vni
);
1171 json_object_string_add(json_vni
, "type", "L2");
1172 json_object_string_add(json_vni
, "vxlanIf",
1173 zvni
->vxlan_if
? zvni
->vxlan_if
->name
1175 json_object_int_add(json_vni
, "numMacs", num_macs
);
1176 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1177 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
1178 json_object_string_add(json_vni
, "tenantVrf",
1179 vrf_id_to_name(zvni
->vrf_id
));
1181 json_vtep_list
= json_object_new_array();
1182 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1183 json_ip_str
= json_object_new_string(
1184 inet_ntoa(zvtep
->vtep_ip
));
1185 json_object_array_add(json_vtep_list
,
1188 json_object_object_add(json_vni
, "remoteVteps",
1191 json_object_object_add(json
, vni_str
, json_vni
);
1196 * Inform BGP about local MACIP.
1198 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
1199 struct ipaddr
*ip
, uint8_t flags
,
1202 char buf
[ETHER_ADDR_STRLEN
];
1203 char buf2
[INET6_ADDRSTRLEN
];
1205 struct zserv
*client
= NULL
;
1206 struct stream
*s
= NULL
;
1208 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
1209 /* BGP may not be running. */
1213 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
1215 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
1216 stream_putl(s
, vni
);
1217 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
1220 if (IS_IPADDR_V4(ip
))
1221 ipa_len
= IPV4_MAX_BYTELEN
;
1222 else if (IS_IPADDR_V6(ip
))
1223 ipa_len
= IPV6_MAX_BYTELEN
;
1225 stream_putl(s
, ipa_len
); /* IP address length */
1227 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
1229 stream_putl(s
, 0); /* Just MAC. */
1231 stream_putc(s
, flags
); /* sticky mac/gateway mac */
1234 /* Write packet size. */
1235 stream_putw_at(s
, 0, stream_get_endp(s
));
1237 if (IS_ZEBRA_DEBUG_VXLAN
)
1239 "Send MACIP %s flags 0x%x MAC %s IP %s L2-VNI %u to %s",
1240 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
1241 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1242 ipaddr2str(ip
, buf2
, sizeof(buf2
)), vni
,
1243 zebra_route_string(client
->proto
));
1245 if (cmd
== ZEBRA_MACIP_ADD
)
1246 client
->macipadd_cnt
++;
1248 client
->macipdel_cnt
++;
1250 return zserv_send_message(client
, s
);
1254 * Make hash key for neighbors.
1256 static unsigned int neigh_hash_keymake(void *p
)
1258 zebra_neigh_t
*n
= p
;
1259 struct ipaddr
*ip
= &n
->ip
;
1261 if (IS_IPADDR_V4(ip
))
1262 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
1264 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
1265 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
1269 * Compare two neighbor hash structures.
1271 static int neigh_cmp(const void *p1
, const void *p2
)
1273 const zebra_neigh_t
*n1
= p1
;
1274 const zebra_neigh_t
*n2
= p2
;
1276 if (n1
== NULL
&& n2
== NULL
)
1279 if (n1
== NULL
|| n2
== NULL
)
1282 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
1286 * Callback to allocate neighbor hash entry.
1288 static void *zvni_neigh_alloc(void *p
)
1290 const zebra_neigh_t
*tmp_n
= p
;
1293 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
1300 * Add neighbor entry.
1302 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
1303 struct ethaddr
*mac
)
1305 zebra_neigh_t tmp_n
;
1306 zebra_neigh_t
*n
= NULL
;
1307 zebra_mac_t
*zmac
= NULL
;
1309 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
1310 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1311 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
1314 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1315 n
->state
= ZEBRA_NEIGH_INACTIVE
;
1317 /* Associate the neigh to mac */
1318 zmac
= zvni_mac_lookup(zvni
, mac
);
1320 listnode_add_sort(zmac
->neigh_list
, n
);
1326 * Delete neighbor entry.
1328 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1330 zebra_neigh_t
*tmp_n
;
1331 zebra_mac_t
*zmac
= NULL
;
1333 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
1335 listnode_delete(zmac
->neigh_list
, n
);
1337 /* Free the VNI hash entry and allocated memory. */
1338 tmp_n
= hash_release(zvni
->neigh_table
, n
);
1340 XFREE(MTYPE_NEIGH
, tmp_n
);
1346 * Free neighbor hash entry (callback)
1348 static void zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
1350 struct neigh_walk_ctx
*wctx
= arg
;
1351 zebra_neigh_t
*n
= backet
->data
;
1353 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1354 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
1355 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
1356 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
1357 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
1358 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
1359 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1360 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
1363 if (wctx
->uninstall
)
1364 zvni_neigh_uninstall(wctx
->zvni
, n
);
1366 zvni_neigh_del(wctx
->zvni
, n
);
1373 * Delete all neighbor entries from specific VTEP for a particular VNI.
1375 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
1376 struct in_addr
*r_vtep_ip
)
1378 struct neigh_walk_ctx wctx
;
1380 if (!zvni
->neigh_table
)
1383 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1385 wctx
.uninstall
= uninstall
;
1386 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
1387 wctx
.r_vtep_ip
= *r_vtep_ip
;
1389 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1393 * Delete all neighbor entries for this VNI.
1395 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
1398 struct neigh_walk_ctx wctx
;
1400 if (!zvni
->neigh_table
)
1403 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1405 wctx
.uninstall
= uninstall
;
1406 wctx
.upd_client
= upd_client
;
1409 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1413 * Look up neighbor hash entry.
1415 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
1420 memset(&tmp
, 0, sizeof(tmp
));
1421 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
1422 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
1427 /* Process all neigh associated to a mac upon local mac add event */
1428 static void zvni_process_neigh_on_local_mac_add(zebra_vni_t
*zvni
,
1431 zebra_neigh_t
*n
= NULL
;
1432 struct listnode
*node
= NULL
;
1433 char buf
[ETHER_ADDR_STRLEN
];
1434 char buf2
[INET6_ADDRSTRLEN
];
1436 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1437 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1438 /* MAC is learnt locally, program all inactive neigh
1439 * pointing to this mac */
1440 if (IS_ZEBRA_NEIGH_INACTIVE(n
)) {
1441 if (IS_ZEBRA_DEBUG_VXLAN
)
1443 "neigh %s (MAC %s) on L2-VNI %u is now ACTIVE",
1444 ipaddr2str(&n
->ip
, buf2
,
1446 prefix_mac2str(&n
->emac
, buf
,
1450 ZEBRA_NEIGH_SET_ACTIVE(n
);
1451 zvni_neigh_send_add_to_client(
1452 zvni
->vni
, &n
->ip
, &n
->emac
, n
->flags
);
1454 if (IS_ZEBRA_DEBUG_VXLAN
)
1456 "neigh %s (MAC %s) on VNI %u should NOT be ACTIVE",
1457 ipaddr2str(&n
->ip
, buf2
,
1459 prefix_mac2str(&n
->emac
, buf
,
1463 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1464 /* TODO: assume the neigh has moved too ?? */
1469 /* Process all neigh associated to a mac upon local mac del event */
1470 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
1473 zebra_neigh_t
*n
= NULL
;
1474 struct listnode
*node
= NULL
;
1475 char buf
[ETHER_ADDR_STRLEN
];
1476 char buf2
[INET6_ADDRSTRLEN
];
1478 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1479 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1480 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1481 if (IS_ZEBRA_DEBUG_VXLAN
)
1483 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1484 ipaddr2str(&n
->ip
, buf2
,
1486 prefix_mac2str(&n
->emac
, buf
,
1490 ZEBRA_NEIGH_SET_INACTIVE(n
);
1491 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1494 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1495 if (IS_ZEBRA_DEBUG_VXLAN
)
1497 "local MAC %s getting deleted on VNI %u has remote neigh %s",
1498 prefix_mac2str(&n
->emac
, buf
,
1501 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1506 /* process all neigh associated to a mac entry upon remote mac add */
1507 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
1510 zebra_neigh_t
*n
= NULL
;
1511 struct listnode
*node
= NULL
;
1512 char buf
[ETHER_ADDR_STRLEN
];
1513 char buf2
[INET6_ADDRSTRLEN
];
1515 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1516 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1517 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1518 if (IS_ZEBRA_DEBUG_VXLAN
)
1520 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1521 ipaddr2str(&n
->ip
, buf2
,
1523 prefix_mac2str(&n
->emac
, buf
,
1527 ZEBRA_NEIGH_SET_INACTIVE(n
);
1528 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1535 /* process all neigh associated to mac entry upon remote mac del */
1536 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
1539 zebra_neigh_t
*n
= NULL
;
1540 struct listnode
*node
= NULL
;
1541 char buf
[ETHER_ADDR_STRLEN
];
1542 char buf2
[INET6_ADDRSTRLEN
];
1544 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1545 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1546 if (IS_ZEBRA_DEBUG_VXLAN
)
1548 "remote MAC %s getting deleted on VNI %u has local neigh %s",
1549 prefix_mac2str(&n
->emac
, buf
,
1552 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1558 * Inform BGP about local neighbor addition.
1560 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
1561 struct ethaddr
*macaddr
,
1562 uint8_t neigh_flags
)
1566 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
1567 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
1568 /* Set router flag (R-bit) based on local neigh entry add */
1569 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
1570 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
1572 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1577 * Inform BGP about local neighbor deletion.
1579 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
1580 struct ethaddr
*macaddr
, uint8_t flags
)
1582 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1587 * Install remote neighbor into the kernel.
1589 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1591 struct zebra_if
*zif
;
1592 struct zebra_l2info_vxlan
*vxl
;
1593 struct interface
*vlan_if
;
1597 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1600 zif
= zvni
->vxlan_if
->info
;
1603 vxl
= &zif
->l2info
.vxl
;
1605 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1609 flags
= NTF_EXT_LEARNED
;
1610 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
1611 flags
|= NTF_ROUTER
;
1612 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
1618 * Uninstall remote neighbor from the kernel.
1620 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1622 struct zebra_if
*zif
;
1623 struct zebra_l2info_vxlan
*vxl
;
1624 struct interface
*vlan_if
;
1626 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1629 if (!zvni
->vxlan_if
) {
1630 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
1635 zif
= zvni
->vxlan_if
->info
;
1638 vxl
= &zif
->l2info
.vxl
;
1639 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1643 return kernel_del_neigh(vlan_if
, &n
->ip
);
1647 * Install neighbor hash entry - called upon access VLAN change.
1649 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
1652 struct neigh_walk_ctx
*wctx
= ctxt
;
1654 n
= (zebra_neigh_t
*)backet
->data
;
1658 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
1659 zvni_neigh_install(wctx
->zvni
, n
);
1662 /* Get the VRR interface for SVI if any */
1663 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
1665 struct zebra_vrf
*zvrf
= NULL
;
1666 struct interface
*tmp_if
= NULL
;
1667 struct zebra_if
*zif
= NULL
;
1669 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1672 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
1677 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
1680 if (zif
->link
== ifp
)
1687 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1689 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1690 struct connected
*c
= NULL
;
1691 struct ethaddr macaddr
;
1693 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1695 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1698 memset(&ip
, 0, sizeof(struct ipaddr
));
1699 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1702 if (c
->address
->family
== AF_INET
) {
1703 ip
.ipa_type
= IPADDR_V4
;
1704 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1705 sizeof(struct in_addr
));
1706 } else if (c
->address
->family
== AF_INET6
) {
1707 ip
.ipa_type
= IPADDR_V6
;
1708 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1709 sizeof(struct in6_addr
));
1714 zvni_gw_macip_del(ifp
, zvni
, &ip
);
1720 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1722 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1723 struct connected
*c
= NULL
;
1724 struct ethaddr macaddr
;
1726 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1728 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1731 memset(&ip
, 0, sizeof(struct ipaddr
));
1732 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1735 if (c
->address
->family
== AF_INET
) {
1736 ip
.ipa_type
= IPADDR_V4
;
1737 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1738 sizeof(struct in_addr
));
1739 } else if (c
->address
->family
== AF_INET6
) {
1740 ip
.ipa_type
= IPADDR_V6
;
1741 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1742 sizeof(struct in6_addr
));
1747 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
1753 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
1756 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1757 struct connected
*c
= NULL
;
1758 struct ethaddr macaddr
;
1760 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1762 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1765 memcpy(&p
, c
->address
, sizeof(struct prefix
));
1767 /* skip link local address */
1768 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
1773 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1774 ZEBRA_IP_PREFIX_ROUTE_ADD
);
1776 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1777 ZEBRA_IP_PREFIX_ROUTE_DEL
);
1783 * zvni_gw_macip_add_to_client
1785 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
1786 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
1788 char buf
[ETHER_ADDR_STRLEN
];
1789 char buf2
[INET6_ADDRSTRLEN
];
1790 zebra_neigh_t
*n
= NULL
;
1791 zebra_mac_t
*mac
= NULL
;
1792 struct zebra_if
*zif
= NULL
;
1793 struct zebra_l2info_vxlan
*vxl
= NULL
;
1795 zif
= zvni
->vxlan_if
->info
;
1799 vxl
= &zif
->l2info
.vxl
;
1801 mac
= zvni_mac_lookup(zvni
, macaddr
);
1803 mac
= zvni_mac_add(zvni
, macaddr
);
1805 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
1806 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1807 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
1812 /* Set "local" forwarding info. */
1813 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
1814 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
1815 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
1816 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
1817 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
1818 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
1820 n
= zvni_neigh_lookup(zvni
, ip
);
1822 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
1825 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1826 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
1827 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1828 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
1833 /* Set "local" forwarding info. */
1834 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
1835 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
1836 /* Set Router flag (R-bit) */
1837 if (ip
->ipa_type
== IPADDR_V6
)
1838 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
1839 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
1840 n
->ifindex
= ifp
->ifindex
;
1842 /* Only advertise in BGP if the knob is enabled */
1843 if (!advertise_gw_macip_enabled(zvni
))
1846 if (IS_ZEBRA_DEBUG_VXLAN
)
1848 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
1849 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1850 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1851 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
1853 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, n
->flags
);
1859 * zvni_gw_macip_del_from_client
1861 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
1864 char buf1
[ETHER_ADDR_STRLEN
];
1865 char buf2
[INET6_ADDRSTRLEN
];
1866 zebra_neigh_t
*n
= NULL
;
1867 zebra_mac_t
*mac
= NULL
;
1869 /* If the neigh entry is not present nothing to do*/
1870 n
= zvni_neigh_lookup(zvni
, ip
);
1874 /* mac entry should be present */
1875 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
1877 zlog_err("MAC %s doesnt exists for neigh %s on VNI %u",
1878 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
1879 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1883 /* If the entry is not local nothing to do*/
1884 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
1887 /* only need to delete the entry from bgp if we sent it before */
1888 if (IS_ZEBRA_DEBUG_VXLAN
)
1890 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
1891 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1892 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
1893 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1895 /* Remove neighbor from BGP. */
1896 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
1897 ZEBRA_MACIP_TYPE_GW
);
1899 /* Delete this neighbor entry. */
1900 zvni_neigh_del(zvni
, n
);
1902 /* see if the mac needs to be deleted as well*/
1904 zvni_deref_ip2mac(zvni
, mac
, 0);
1909 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
1912 zebra_vni_t
*zvni
= NULL
;
1913 struct zebra_if
*zif
= NULL
;
1914 struct zebra_l2info_vxlan zl2_info
;
1915 struct interface
*vlan_if
= NULL
;
1916 struct interface
*vrr_if
= NULL
;
1917 struct interface
*ifp
;
1919 /* Add primary SVI MAC*/
1920 zvni
= (zebra_vni_t
*)backet
->data
;
1924 ifp
= zvni
->vxlan_if
;
1929 /* If down or not mapped to a bridge, we're done. */
1930 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1933 zl2_info
= zif
->l2info
.vxl
;
1936 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1940 /* Del primary MAC-IP */
1941 zvni_del_macip_for_intf(vlan_if
, zvni
);
1943 /* Del VRR MAC-IP - if any*/
1944 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1946 zvni_del_macip_for_intf(vrr_if
, zvni
);
1951 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
1954 zebra_vni_t
*zvni
= NULL
;
1955 struct zebra_if
*zif
= NULL
;
1956 struct zebra_l2info_vxlan zl2_info
;
1957 struct interface
*vlan_if
= NULL
;
1958 struct interface
*vrr_if
= NULL
;
1959 struct interface
*ifp
= NULL
;
1961 zvni
= (zebra_vni_t
*)backet
->data
;
1965 ifp
= zvni
->vxlan_if
;
1970 /* If down or not mapped to a bridge, we're done. */
1971 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1973 zl2_info
= zif
->l2info
.vxl
;
1976 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1980 /* Add primary SVI MAC-IP */
1981 zvni_add_macip_for_intf(vlan_if
, zvni
);
1983 /* Add VRR MAC-IP - if any*/
1984 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1986 zvni_add_macip_for_intf(vrr_if
, zvni
);
1991 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
1992 struct interface
*ifp
,
1994 struct ethaddr
*macaddr
,
1995 uint8_t router_flag
)
1997 char buf
[ETHER_ADDR_STRLEN
];
1998 char buf2
[INET6_ADDRSTRLEN
];
1999 zebra_neigh_t
*n
= NULL
;
2000 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2002 /* create a dummy MAC if the MAC is not already present */
2003 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2005 if (IS_ZEBRA_DEBUG_VXLAN
)
2007 "AUTO MAC %s created for neigh %s on VNI %u",
2008 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2009 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2011 zmac
= zvni_mac_add(zvni
, macaddr
);
2013 zlog_warn("Failed to add MAC %s VNI %u",
2014 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2019 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
2020 memset(&zmac
->flags
, 0, sizeof(uint32_t));
2021 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2024 /* If same entry already exists, it might be a change or it might be a
2025 * move from remote to local.
2027 n
= zvni_neigh_lookup(zvni
, ip
);
2029 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2030 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2032 /* Update any params and return - client doesn't
2033 * care about a purely local change.
2035 n
->ifindex
= ifp
->ifindex
;
2039 /* If the MAC has changed,
2040 * need to issue a delete first
2041 * as this means a different MACIP route.
2042 * Also, need to do some unlinking/relinking.
2044 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2046 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2048 listnode_delete(old_zmac
->neigh_list
, n
);
2049 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
2052 /* Update the forwarding info. */
2053 n
->ifindex
= ifp
->ifindex
;
2054 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2056 /* Link to new MAC */
2057 listnode_add_sort(zmac
->neigh_list
, n
);
2060 /* Neighbor has moved from remote to local. */
2062 /* If MAC has changed, do the unlink/link */
2063 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2065 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2067 listnode_delete(old_zmac
->neigh_list
,
2069 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
2072 /* Link to new MAC */
2073 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2074 listnode_add_sort(zmac
->neigh_list
, n
);
2077 /* Mark appropriately */
2078 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2079 n
->r_vtep_ip
.s_addr
= 0;
2080 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2081 n
->ifindex
= ifp
->ifindex
;
2084 /* New neighbor - create */
2085 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2088 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2089 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2090 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2091 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2094 /* Set "local" forwarding info. */
2095 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2096 n
->ifindex
= ifp
->ifindex
;
2099 /* Before we program this in BGP, we need to check if MAC is locally
2102 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
2103 if (IS_ZEBRA_DEBUG_VXLAN
)
2105 "Skipping neigh %s add to client as MAC %s is not local on VNI %u",
2106 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2107 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2113 /*Set router flag (R-bit) */
2115 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2118 if (IS_ZEBRA_DEBUG_VXLAN
)
2119 zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u with flags 0x%x",
2120 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2121 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2122 zvni
->vni
, n
->flags
);
2123 ZEBRA_NEIGH_SET_ACTIVE(n
);
2125 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, n
->flags
);
2128 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
2129 struct interface
*ifp
,
2131 struct ethaddr
*macaddr
,
2134 char buf
[ETHER_ADDR_STRLEN
];
2135 char buf2
[INET6_ADDRSTRLEN
];
2136 zebra_neigh_t
*n
= NULL
;
2137 zebra_mac_t
*zmac
= NULL
;
2139 /* If the neighbor is unknown, there is no further action. */
2140 n
= zvni_neigh_lookup(zvni
, ip
);
2144 /* If a remote entry, see if it needs to be refreshed */
2145 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2147 if (state
& NUD_STALE
)
2148 zvni_neigh_install(zvni
, n
);
2151 /* We got a "remote" neighbor notification for an entry
2152 * we think is local. This can happen in a multihoming
2153 * scenario - but only if the MAC is already "remote".
2154 * Just mark our entry as "remote".
2156 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2157 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2158 zlog_err("Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
2159 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
2160 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2165 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2166 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2167 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
2174 * Make hash key for MAC.
2176 static unsigned int mac_hash_keymake(void *p
)
2178 zebra_mac_t
*pmac
= p
;
2179 const void *pnt
= (void *)pmac
->macaddr
.octet
;
2181 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
2185 * Compare two MAC addresses.
2187 static int mac_cmp(const void *p1
, const void *p2
)
2189 const zebra_mac_t
*pmac1
= p1
;
2190 const zebra_mac_t
*pmac2
= p2
;
2192 if (pmac1
== NULL
&& pmac2
== NULL
)
2195 if (pmac1
== NULL
|| pmac2
== NULL
)
2198 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
2203 * Callback to allocate MAC hash entry.
2205 static void *zvni_mac_alloc(void *p
)
2207 const zebra_mac_t
*tmp_mac
= p
;
2210 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2213 return ((void *)mac
);
2219 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
2221 zebra_mac_t tmp_mac
;
2222 zebra_mac_t
*mac
= NULL
;
2224 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
2225 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
2226 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
2229 mac
->neigh_list
= list_new();
2230 mac
->neigh_list
->cmp
= (int (*)(void *, void *))neigh_cmp
;
2238 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2240 zebra_mac_t
*tmp_mac
;
2242 list_delete_and_null(&mac
->neigh_list
);
2244 /* Free the VNI hash entry and allocated memory. */
2245 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
2247 XFREE(MTYPE_MAC
, tmp_mac
);
2253 * Free MAC hash entry (callback)
2255 static void zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2257 struct mac_walk_ctx
*wctx
= arg
;
2258 zebra_mac_t
*mac
= backet
->data
;
2260 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
2261 || ((wctx
->flags
& DEL_REMOTE_MAC
)
2262 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
2263 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
2264 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
2265 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
2266 &wctx
->r_vtep_ip
))) {
2267 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
2268 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
2269 &mac
->macaddr
, mac
->flags
);
2272 if (wctx
->uninstall
)
2273 zvni_mac_uninstall(wctx
->zvni
, mac
, 0);
2275 zvni_mac_del(wctx
->zvni
, mac
);
2282 * Delete all MAC entries from specific VTEP for a particular VNI.
2284 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2285 struct in_addr
*r_vtep_ip
)
2287 struct mac_walk_ctx wctx
;
2289 if (!zvni
->mac_table
)
2292 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2294 wctx
.uninstall
= uninstall
;
2295 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
2296 wctx
.r_vtep_ip
= *r_vtep_ip
;
2298 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2302 * Delete all MAC entries for this VNI.
2304 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2307 struct mac_walk_ctx wctx
;
2309 if (!zvni
->mac_table
)
2312 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2314 wctx
.uninstall
= uninstall
;
2315 wctx
.upd_client
= upd_client
;
2318 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2322 * Look up MAC hash entry.
2324 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
2329 memset(&tmp
, 0, sizeof(tmp
));
2330 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
2331 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
2337 * Inform BGP about local MAC addition.
2339 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2344 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2345 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2346 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2347 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2349 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2354 * Inform BGP about local MAC deletion.
2356 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2361 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2362 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2363 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2364 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2366 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2371 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2372 * notifications, to see if they are of interest.
2374 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
2375 struct interface
*br_if
, vlanid_t vid
)
2377 struct zebra_ns
*zns
;
2378 struct route_node
*rn
;
2379 struct interface
*tmp_if
= NULL
;
2380 struct zebra_if
*zif
;
2381 struct zebra_l2info_bridge
*br
;
2382 struct zebra_l2info_vxlan
*vxl
= NULL
;
2383 uint8_t bridge_vlan_aware
;
2387 /* Determine if bridge is VLAN-aware or not */
2390 br
= &zif
->l2info
.br
;
2391 bridge_vlan_aware
= br
->vlan_aware
;
2393 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2394 /* TODO: Optimize with a hash. */
2395 zns
= zebra_ns_lookup(NS_DEFAULT
);
2396 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2397 tmp_if
= (struct interface
*)rn
->info
;
2401 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2403 if (!if_is_operative(tmp_if
))
2405 vxl
= &zif
->l2info
.vxl
;
2407 if (zif
->brslave_info
.br_if
!= br_if
)
2410 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2419 zvni
= zvni_lookup(vxl
->vni
);
2424 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2425 * neighbor notifications, to see if they are of interest.
2427 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
2428 struct interface
*br_if
)
2430 struct zebra_ns
*zns
;
2431 struct route_node
*rn
;
2432 struct interface
*tmp_if
= NULL
;
2433 struct zebra_if
*zif
;
2434 struct zebra_l2info_bridge
*br
;
2435 struct zebra_l2info_vxlan
*vxl
= NULL
;
2436 uint8_t bridge_vlan_aware
;
2444 /* Make sure the linked interface is a bridge. */
2445 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
2448 /* Determine if bridge is VLAN-aware or not */
2451 br
= &zif
->l2info
.br
;
2452 bridge_vlan_aware
= br
->vlan_aware
;
2453 if (bridge_vlan_aware
) {
2454 struct zebra_l2info_vlan
*vl
;
2456 if (!IS_ZEBRA_IF_VLAN(ifp
))
2461 vl
= &zif
->l2info
.vl
;
2465 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2466 /* TODO: Optimize with a hash. */
2467 zns
= zebra_ns_lookup(NS_DEFAULT
);
2468 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2469 tmp_if
= (struct interface
*)rn
->info
;
2473 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2475 if (!if_is_operative(tmp_if
))
2477 vxl
= &zif
->l2info
.vxl
;
2479 if (zif
->brslave_info
.br_if
!= br_if
)
2482 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2491 zvni
= zvni_lookup(vxl
->vni
);
2495 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
2497 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
2498 * linked to the bridge
2499 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
2502 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
2504 struct zebra_ns
*zns
;
2505 struct route_node
*rn
;
2506 struct interface
*tmp_if
= NULL
;
2507 struct zebra_if
*zif
;
2508 struct zebra_l2info_bridge
*br
;
2509 struct zebra_l2info_vlan
*vl
;
2510 uint8_t bridge_vlan_aware
;
2513 /* Defensive check, caller expected to invoke only with valid bridge. */
2517 /* Determine if bridge is VLAN-aware or not */
2520 br
= &zif
->l2info
.br
;
2521 bridge_vlan_aware
= br
->vlan_aware
;
2523 /* Check oper status of the SVI. */
2524 if (!bridge_vlan_aware
)
2525 return if_is_operative(br_if
) ? br_if
: NULL
;
2527 /* Identify corresponding VLAN interface. */
2528 /* TODO: Optimize with a hash. */
2529 zns
= zebra_ns_lookup(NS_DEFAULT
);
2530 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2531 tmp_if
= (struct interface
*)rn
->info
;
2532 /* Check oper status of the SVI. */
2533 if (!tmp_if
|| !if_is_operative(tmp_if
))
2536 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
2537 || zif
->link
!= br_if
)
2539 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
2541 if (vl
->vid
== vid
) {
2547 return found
? tmp_if
: NULL
;
2551 * Install remote MAC into the kernel.
2553 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2555 struct zebra_if
*zif
;
2556 struct zebra_l2info_vxlan
*vxl
;
2559 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2562 zif
= zvni
->vxlan_if
->info
;
2565 vxl
= &zif
->l2info
.vxl
;
2567 sticky
= CHECK_FLAG(mac
->flags
,
2568 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
)) ? 1 : 0;
2570 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
2571 mac
->fwd_info
.r_vtep_ip
, sticky
);
2575 * Uninstall remote MAC from the kernel. In the scenario where the MAC
2576 * moves to remote, we have to uninstall any existing local entry first.
2578 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
)
2580 struct zebra_if
*zif
;
2581 struct zebra_l2info_vxlan
*vxl
;
2582 struct in_addr vtep_ip
= {.s_addr
= 0};
2583 struct zebra_ns
*zns
;
2584 struct interface
*ifp
;
2586 if (!local
&& !(mac
->flags
& ZEBRA_MAC_REMOTE
))
2589 if (!zvni
->vxlan_if
) {
2590 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2595 zif
= zvni
->vxlan_if
->info
;
2598 vxl
= &zif
->l2info
.vxl
;
2601 zns
= zebra_ns_lookup(NS_DEFAULT
);
2602 ifp
= if_lookup_by_index_per_ns(zns
,
2603 mac
->fwd_info
.local
.ifindex
);
2604 if (!ifp
) // unexpected
2607 ifp
= zvni
->vxlan_if
;
2608 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
2611 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
,
2616 * Install MAC hash entry - called upon access VLAN change.
2618 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
2621 struct mac_walk_ctx
*wctx
= ctxt
;
2623 mac
= (zebra_mac_t
*)backet
->data
;
2627 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
2628 zvni_mac_install(wctx
->zvni
, mac
);
2632 * Decrement neighbor refcount of MAC; uninstall and free it if
2635 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
2638 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)
2639 || !list_isempty(mac
->neigh_list
))
2643 zvni_mac_uninstall(zvni
, mac
, 0);
2645 zvni_mac_del(zvni
, mac
);
2649 * Read and populate local MACs and neighbors corresponding to this VNI.
2651 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
2653 struct zebra_ns
*zns
;
2654 struct zebra_if
*zif
;
2655 struct interface
*vlan_if
;
2656 struct zebra_l2info_vxlan
*vxl
;
2657 struct interface
*vrr_if
;
2660 vxl
= &zif
->l2info
.vxl
;
2661 zns
= zebra_ns_lookup(NS_DEFAULT
);
2663 if (IS_ZEBRA_DEBUG_VXLAN
)
2665 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2666 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2667 zif
->brslave_info
.bridge_ifindex
);
2669 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
2670 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2673 /* Add SVI MAC-IP */
2674 zvni_add_macip_for_intf(vlan_if
, zvni
);
2676 /* Add VRR MAC-IP - if any*/
2677 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2679 zvni_add_macip_for_intf(vrr_if
, zvni
);
2681 neigh_read_for_vlan(zns
, vlan_if
);
2686 * Hash function for VNI.
2688 static unsigned int vni_hash_keymake(void *p
)
2690 const zebra_vni_t
*zvni
= p
;
2692 return (jhash_1word(zvni
->vni
, 0));
2696 * Compare 2 VNI hash entries.
2698 static int vni_hash_cmp(const void *p1
, const void *p2
)
2700 const zebra_vni_t
*zvni1
= p1
;
2701 const zebra_vni_t
*zvni2
= p2
;
2703 return (zvni1
->vni
== zvni2
->vni
);
2707 * Callback to allocate VNI hash entry.
2709 static void *zvni_alloc(void *p
)
2711 const zebra_vni_t
*tmp_vni
= p
;
2714 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
2715 zvni
->vni
= tmp_vni
->vni
;
2716 return ((void *)zvni
);
2720 * Look up VNI hash entry.
2722 static zebra_vni_t
*zvni_lookup(vni_t vni
)
2724 struct zebra_vrf
*zvrf
;
2725 zebra_vni_t tmp_vni
;
2726 zebra_vni_t
*zvni
= NULL
;
2728 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2730 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
2732 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
2738 * Add VNI hash entry.
2740 static zebra_vni_t
*zvni_add(vni_t vni
)
2742 struct zebra_vrf
*zvrf
;
2743 zebra_vni_t tmp_zvni
;
2744 zebra_vni_t
*zvni
= NULL
;
2746 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2748 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
2750 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
2753 /* Create hash table for MAC */
2755 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
2757 /* Create hash table for neighbors */
2758 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
2759 "Zebra VNI Neighbor Table");
2765 * Delete VNI hash entry.
2767 static int zvni_del(zebra_vni_t
*zvni
)
2769 struct zebra_vrf
*zvrf
;
2770 zebra_vni_t
*tmp_zvni
;
2772 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2775 zvni
->vxlan_if
= NULL
;
2777 /* Free the neighbor hash table. */
2778 hash_free(zvni
->neigh_table
);
2779 zvni
->neigh_table
= NULL
;
2781 /* Free the MAC hash table. */
2782 hash_free(zvni
->mac_table
);
2783 zvni
->mac_table
= NULL
;
2785 /* Free the VNI hash entry and allocated memory. */
2786 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
2788 XFREE(MTYPE_ZVNI
, tmp_zvni
);
2794 * Inform BGP about local VNI addition.
2796 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
2798 struct zserv
*client
;
2801 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2802 /* BGP may not be running. */
2806 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2808 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
2809 stream_putl(s
, zvni
->vni
);
2810 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
2811 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
2813 /* Write packet size. */
2814 stream_putw_at(s
, 0, stream_get_endp(s
));
2816 if (IS_ZEBRA_DEBUG_VXLAN
)
2817 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
2818 inet_ntoa(zvni
->local_vtep_ip
),
2819 vrf_id_to_name(zvni
->vrf_id
),
2820 zebra_route_string(client
->proto
));
2822 client
->vniadd_cnt
++;
2823 return zserv_send_message(client
, s
);
2827 * Inform BGP about local VNI deletion.
2829 static int zvni_send_del_to_client(vni_t vni
)
2831 struct zserv
*client
;
2834 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2835 /* BGP may not be running. */
2839 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2842 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
2843 stream_putl(s
, vni
);
2845 /* Write packet size. */
2846 stream_putw_at(s
, 0, stream_get_endp(s
));
2848 if (IS_ZEBRA_DEBUG_VXLAN
)
2849 zlog_debug("Send VNI_DEL %u to %s", vni
,
2850 zebra_route_string(client
->proto
));
2852 client
->vnidel_cnt
++;
2853 return zserv_send_message(client
, s
);
2857 * Build the VNI hash table by going over the VxLAN interfaces. This
2858 * is called when EVPN (advertise-all-vni) is enabled.
2860 static void zvni_build_hash_table()
2862 struct zebra_ns
*zns
;
2863 struct route_node
*rn
;
2864 struct interface
*ifp
;
2866 /* Walk VxLAN interfaces and create VNI hash. */
2867 zns
= zebra_ns_lookup(NS_DEFAULT
);
2868 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2870 zebra_vni_t
*zvni
= NULL
;
2871 zebra_l3vni_t
*zl3vni
= NULL
;
2872 struct zebra_if
*zif
;
2873 struct zebra_l2info_vxlan
*vxl
;
2875 ifp
= (struct interface
*)rn
->info
;
2879 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2882 vxl
= &zif
->l2info
.vxl
;
2885 /* L3-VNI and L2-VNI are handled seperately */
2886 zl3vni
= zl3vni_lookup(vni
);
2889 if (IS_ZEBRA_DEBUG_VXLAN
)
2891 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
2892 ifp
->name
, ifp
->ifindex
, vni
);
2894 /* associate with vxlan_if */
2895 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
2896 zl3vni
->vxlan_if
= ifp
;
2899 * we need to associate with SVI.
2900 * we can associate with svi-if only after association
2901 * with vxlan-intf is complete
2903 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
2905 if (is_l3vni_oper_up(zl3vni
))
2906 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
2909 struct interface
*vlan_if
= NULL
;
2911 if (IS_ZEBRA_DEBUG_VXLAN
)
2913 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
2914 ifp
->name
, ifp
->ifindex
, vni
,
2915 inet_ntoa(vxl
->vtep_ip
));
2917 /* VNI hash entry is not expected to exist. */
2918 zvni
= zvni_lookup(vni
);
2921 "VNI hash already present for IF %s(%u) L2-VNI %u",
2922 ifp
->name
, ifp
->ifindex
, vni
);
2926 zvni
= zvni_add(vni
);
2929 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
2930 ifp
->name
, ifp
->ifindex
, vni
);
2934 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
2935 zvni
->vxlan_if
= ifp
;
2936 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
2937 zif
->brslave_info
.br_if
);
2939 zvni
->vrf_id
= vlan_if
->vrf_id
;
2940 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
2942 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
2946 /* Inform BGP if intf is up and mapped to bridge. */
2947 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
2948 zvni_send_add_to_client(zvni
);
2954 * See if remote VTEP matches with prefix.
2956 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
2958 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
2962 * Locate remote VTEP in VNI hash table.
2964 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2966 zebra_vtep_t
*zvtep
;
2971 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2972 if (zvni_vtep_match(vtep_ip
, zvtep
))
2980 * Add remote VTEP to VNI hash table.
2982 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2984 zebra_vtep_t
*zvtep
;
2986 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
2988 zlog_err("Failed to alloc VTEP entry, VNI %u", zvni
->vni
);
2992 zvtep
->vtep_ip
= *vtep_ip
;
2995 zvni
->vteps
->prev
= zvtep
;
2996 zvtep
->next
= zvni
->vteps
;
2997 zvni
->vteps
= zvtep
;
3003 * Remove remote VTEP from VNI hash table.
3005 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
3008 zvtep
->next
->prev
= zvtep
->prev
;
3010 zvtep
->prev
->next
= zvtep
->next
;
3012 zvni
->vteps
= zvtep
->next
;
3014 zvtep
->prev
= zvtep
->next
= NULL
;
3015 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
3021 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
3022 * uninstall from kernel if asked to.
3024 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
3026 zebra_vtep_t
*zvtep
, *zvtep_next
;
3031 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
3032 zvtep_next
= zvtep
->next
;
3034 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
3035 zvni_vtep_del(zvni
, zvtep
);
3042 * Install remote VTEP into the kernel.
3044 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3046 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3050 * Uninstall remote VTEP from the kernel.
3052 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3054 if (!zvni
->vxlan_if
) {
3055 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
3060 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3064 * Cleanup VNI/VTEP and update kernel
3066 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
3068 zebra_vni_t
*zvni
= NULL
;
3069 zebra_l3vni_t
*zl3vni
= NULL
;
3070 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
3072 zvni
= (zebra_vni_t
*)backet
->data
;
3076 /* remove from l3-vni list */
3078 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
3080 listnode_delete(zl3vni
->l2vnis
, zvni
);
3082 /* Free up all neighbors and MACs, if any. */
3083 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
3084 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
3086 /* Free up all remote VTEPs, if any. */
3087 zvni_vtep_del_all(zvni
, 1);
3089 /* Delete the hash entry. */
3094 static void zl3vni_cleanup_all(struct hash_backet
*backet
, void *args
)
3096 zebra_l3vni_t
*zl3vni
= NULL
;
3098 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
3102 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
3105 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
3106 struct prefix
*host
)
3108 struct host_rb_entry lookup
;
3109 struct host_rb_entry
*hle
;
3111 memset(&lookup
, 0, sizeof(lookup
));
3112 memcpy(&lookup
.p
, host
, sizeof(*host
));
3114 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3118 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
3119 memcpy(hle
, &lookup
, sizeof(lookup
));
3121 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
3124 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
3126 struct host_rb_entry lookup
;
3127 struct host_rb_entry
*hle
;
3129 memset(&lookup
, 0, sizeof(lookup
));
3130 memcpy(&lookup
.p
, host
, sizeof(*host
));
3132 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3134 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
3135 XFREE(MTYPE_HOST_PREFIX
, hle
);
3142 * Look up MAC hash entry.
3144 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
3145 struct ethaddr
*rmac
)
3150 memset(&tmp
, 0, sizeof(tmp
));
3151 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
3152 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
3158 * Callback to allocate RMAC hash entry.
3160 static void *zl3vni_rmac_alloc(void *p
)
3162 const zebra_mac_t
*tmp_rmac
= p
;
3165 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3168 return ((void *)zrmac
);
3172 * Add RMAC entry to l3-vni
3174 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
3176 zebra_mac_t tmp_rmac
;
3177 zebra_mac_t
*zrmac
= NULL
;
3179 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
3180 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
3181 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
3184 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
3186 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
3187 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
3195 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3197 zebra_mac_t
*tmp_rmac
;
3198 struct host_rb_entry
*hle
;
3200 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3201 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
3203 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
3204 XFREE(MTYPE_HOST_PREFIX
, hle
);
3207 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
3209 XFREE(MTYPE_MAC
, tmp_rmac
);
3215 * Install remote RMAC into the kernel.
3217 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3219 struct zebra_if
*zif
= NULL
;
3220 struct zebra_l2info_vxlan
*vxl
= NULL
;
3222 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3223 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3226 zif
= zl3vni
->vxlan_if
->info
;
3230 vxl
= &zif
->l2info
.vxl
;
3232 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3233 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3237 * Uninstall remote RMAC from the kernel.
3239 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3241 char buf
[ETHER_ADDR_STRLEN
];
3242 struct zebra_if
*zif
= NULL
;
3243 struct zebra_l2info_vxlan
*vxl
= NULL
;
3245 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3246 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3249 if (!zl3vni
->vxlan_if
) {
3251 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
3252 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
3253 zl3vni
->vni
, zl3vni
);
3257 zif
= zl3vni
->vxlan_if
->info
;
3261 vxl
= &zif
->l2info
.vxl
;
3263 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3264 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3267 /* handle rmac add */
3268 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
3269 struct ipaddr
*vtep_ip
,
3270 struct prefix
*host_prefix
)
3272 char buf
[ETHER_ADDR_STRLEN
];
3273 char buf1
[INET6_ADDRSTRLEN
];
3274 zebra_mac_t
*zrmac
= NULL
;
3276 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3279 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
3282 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
3283 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3285 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
3288 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
3289 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
3291 /* install rmac in kernel */
3292 zl3vni_rmac_install(zl3vni
, zrmac
);
3295 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
3301 /* handle rmac delete */
3302 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
3303 struct prefix
*host_prefix
)
3305 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
3307 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3308 /* uninstall from kernel */
3309 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3311 /* del the rmac entry */
3312 zl3vni_rmac_del(zl3vni
, zrmac
);
3317 * Look up nh hash entry on a l3-vni.
3319 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3324 memset(&tmp
, 0, sizeof(tmp
));
3325 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
3326 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
3333 * Callback to allocate NH hash entry on L3-VNI.
3335 static void *zl3vni_nh_alloc(void *p
)
3337 const zebra_neigh_t
*tmp_n
= p
;
3340 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
3347 * Add neighbor entry.
3349 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3350 struct ethaddr
*mac
)
3352 zebra_neigh_t tmp_n
;
3353 zebra_neigh_t
*n
= NULL
;
3355 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
3356 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
3357 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
3360 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
3362 memcpy(&n
->emac
, mac
, ETH_ALEN
);
3363 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3364 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
3370 * Delete neighbor entry.
3372 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3374 zebra_neigh_t
*tmp_n
;
3375 struct host_rb_entry
*hle
;
3377 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
3378 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
3380 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
3381 XFREE(MTYPE_HOST_PREFIX
, hle
);
3384 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
3386 XFREE(MTYPE_NEIGH
, tmp_n
);
3392 * Install remote nh as neigh into the kernel.
3394 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3399 if (!is_l3vni_oper_up(zl3vni
))
3402 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3403 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3406 flags
= NTF_EXT_LEARNED
;
3407 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
3408 flags
|= NTF_ROUTER
;
3409 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
3415 * Uninstall remote nh from the kernel.
3417 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3419 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3420 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3423 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
3426 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
3429 /* add remote vtep as a neigh entry */
3430 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
3431 struct ethaddr
*rmac
,
3432 struct prefix
*host_prefix
)
3434 char buf
[ETHER_ADDR_STRLEN
];
3435 char buf1
[INET6_ADDRSTRLEN
];
3436 zebra_neigh_t
*nh
= NULL
;
3438 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3440 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
3444 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
3445 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
3446 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3451 /* install the nh neigh in kernel */
3452 zl3vni_nh_install(zl3vni
, nh
);
3455 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
3460 /* handle nh neigh delete */
3461 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
3462 struct prefix
*host_prefix
)
3464 rb_delete_host(&nh
->host_rb
, host_prefix
);
3466 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
3467 /* uninstall from kernel */
3468 zl3vni_nh_uninstall(zl3vni
, nh
);
3470 /* delete the nh entry */
3471 zl3vni_nh_del(zl3vni
, nh
);
3475 /* handle neigh update from kernel - the only thing of interest is to
3476 * readd stale entries.
3478 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3482 zebra_neigh_t
*n
= NULL
;
3484 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3488 /* all next hop neigh are remote and installed by frr.
3489 * If the kernel has aged this entry, re-install.
3491 if (state
& NUD_STALE
)
3492 zl3vni_nh_install(zl3vni
, n
);
3497 /* handle neigh delete from kernel */
3498 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3500 zebra_neigh_t
*n
= NULL
;
3502 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3506 /* all next hop neigh are remote and installed by frr.
3507 * If we get an age out notification for these neigh entries, we have to
3510 zl3vni_nh_install(zl3vni
, n
);
3516 * Hash function for L3 VNI.
3518 static unsigned int l3vni_hash_keymake(void *p
)
3520 const zebra_l3vni_t
*zl3vni
= p
;
3522 return jhash_1word(zl3vni
->vni
, 0);
3526 * Compare 2 L3 VNI hash entries.
3528 static int l3vni_hash_cmp(const void *p1
, const void *p2
)
3530 const zebra_l3vni_t
*zl3vni1
= p1
;
3531 const zebra_l3vni_t
*zl3vni2
= p2
;
3533 return (zl3vni1
->vni
== zl3vni2
->vni
);
3537 * Callback to allocate L3 VNI hash entry.
3539 static void *zl3vni_alloc(void *p
)
3541 zebra_l3vni_t
*zl3vni
= NULL
;
3542 const zebra_l3vni_t
*tmp_l3vni
= p
;
3544 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
3545 zl3vni
->vni
= tmp_l3vni
->vni
;
3546 return ((void *)zl3vni
);
3550 * Look up L3 VNI hash entry.
3552 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
3554 struct zebra_ns
*zns
;
3555 zebra_l3vni_t tmp_l3vni
;
3556 zebra_l3vni_t
*zl3vni
= NULL
;
3558 zns
= zebra_ns_lookup(NS_DEFAULT
);
3560 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
3561 tmp_l3vni
.vni
= vni
;
3562 zl3vni
= hash_lookup(zns
->l3vni_table
, &tmp_l3vni
);
3568 * Add L3 VNI hash entry.
3570 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
3572 zebra_l3vni_t tmp_zl3vni
;
3573 struct zebra_ns
*zns
= NULL
;
3574 zebra_l3vni_t
*zl3vni
= NULL
;
3576 zns
= zebra_ns_lookup(NS_DEFAULT
);
3579 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
3580 tmp_zl3vni
.vni
= vni
;
3582 zl3vni
= hash_get(zns
->l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
3585 zl3vni
->vrf_id
= vrf_id
;
3586 zl3vni
->svi_if
= NULL
;
3587 zl3vni
->vxlan_if
= NULL
;
3588 zl3vni
->l2vnis
= list_new();
3589 zl3vni
->l2vnis
->cmp
= (int (*)(void *, void *))vni_hash_cmp
;
3591 /* Create hash table for remote RMAC */
3592 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
3593 "Zebra L3-VNI RMAC-Table");
3595 /* Create hash table for neighbors */
3596 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3597 "Zebra L3-VNI next-hop table");
3603 * Delete L3 VNI hash entry.
3605 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
3607 struct zebra_ns
*zns
;
3608 zebra_l3vni_t
*tmp_zl3vni
;
3610 zns
= zebra_ns_lookup(NS_DEFAULT
);
3613 /* free the list of l2vnis */
3614 list_delete_and_null(&zl3vni
->l2vnis
);
3615 zl3vni
->l2vnis
= NULL
;
3617 /* Free the rmac table */
3618 hash_free(zl3vni
->rmac_table
);
3619 zl3vni
->rmac_table
= NULL
;
3621 /* Free the nh table */
3622 hash_free(zl3vni
->nh_table
);
3623 zl3vni
->nh_table
= NULL
;
3625 /* Free the VNI hash entry and allocated memory. */
3626 tmp_zl3vni
= hash_release(zns
->l3vni_table
, zl3vni
);
3628 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
3633 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
3635 struct zebra_ns
*zns
= NULL
;
3636 struct route_node
*rn
= NULL
;
3637 struct interface
*ifp
= NULL
;
3639 /* loop through all vxlan-interface */
3640 zns
= zebra_ns_lookup(NS_DEFAULT
);
3641 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3643 struct zebra_if
*zif
= NULL
;
3644 struct zebra_l2info_vxlan
*vxl
= NULL
;
3646 ifp
= (struct interface
*)rn
->info
;
3651 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3654 vxl
= &zif
->l2info
.vxl
;
3655 if (vxl
->vni
== zl3vni
->vni
) {
3656 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3664 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
3666 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
3667 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
3672 if (!zl3vni
->vxlan_if
)
3675 zif
= zl3vni
->vxlan_if
->info
;
3679 vxl
= &zif
->l2info
.vxl
;
3681 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3684 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
3686 struct zebra_vrf
*zvrf
= NULL
;
3688 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
3692 return zl3vni_lookup(zvrf
->l3vni
);
3696 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3697 * neighbor notifications, to see if they are of interest.
3699 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
3700 struct interface
*br_if
)
3704 uint8_t bridge_vlan_aware
= 0;
3705 zebra_l3vni_t
*zl3vni
= NULL
;
3706 struct zebra_ns
*zns
= NULL
;
3707 struct route_node
*rn
= NULL
;
3708 struct zebra_if
*zif
= NULL
;
3709 struct interface
*tmp_if
= NULL
;
3710 struct zebra_l2info_bridge
*br
= NULL
;
3711 struct zebra_l2info_vxlan
*vxl
= NULL
;
3716 /* Make sure the linked interface is a bridge. */
3717 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3720 /* Determine if bridge is VLAN-aware or not */
3723 br
= &zif
->l2info
.br
;
3724 bridge_vlan_aware
= br
->vlan_aware
;
3725 if (bridge_vlan_aware
) {
3726 struct zebra_l2info_vlan
*vl
;
3728 if (!IS_ZEBRA_IF_VLAN(ifp
))
3733 vl
= &zif
->l2info
.vl
;
3737 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3738 /* TODO: Optimize with a hash. */
3739 zns
= zebra_ns_lookup(NS_DEFAULT
);
3740 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3741 tmp_if
= (struct interface
*)rn
->info
;
3745 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3747 if (!if_is_operative(tmp_if
))
3749 vxl
= &zif
->l2info
.vxl
;
3751 if (zif
->brslave_info
.br_if
!= br_if
)
3754 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3763 zl3vni
= zl3vni_lookup(vxl
->vni
);
3768 * Inform BGP about l3-vni.
3770 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
3772 struct stream
*s
= NULL
;
3773 struct zserv
*client
= NULL
;
3774 struct ethaddr rmac
;
3775 char buf
[ETHER_ADDR_STRLEN
];
3777 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3778 /* BGP may not be running. */
3783 memset(&rmac
, 0, sizeof(struct ethaddr
));
3784 zl3vni_get_rmac(zl3vni
, &rmac
);
3786 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3788 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
3789 stream_putl(s
, zl3vni
->vni
);
3790 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
3791 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
3792 stream_put(s
, &zl3vni
->filter
, sizeof(int));
3794 /* Write packet size. */
3795 stream_putw_at(s
, 0, stream_get_endp(s
));
3797 if (IS_ZEBRA_DEBUG_VXLAN
)
3799 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
3800 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3801 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
3802 inet_ntoa(zl3vni
->local_vtep_ip
),
3803 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
3804 ? "prefix-routes-only"
3806 zebra_route_string(client
->proto
));
3808 client
->l3vniadd_cnt
++;
3809 return zserv_send_message(client
, s
);
3813 * Inform BGP about local l3-VNI deletion.
3815 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
3817 struct stream
*s
= NULL
;
3818 struct zserv
*client
= NULL
;
3820 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3821 /* BGP may not be running. */
3825 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3827 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
3828 stream_putl(s
, zl3vni
->vni
);
3830 /* Write packet size. */
3831 stream_putw_at(s
, 0, stream_get_endp(s
));
3833 if (IS_ZEBRA_DEBUG_VXLAN
)
3834 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
3835 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3836 zebra_route_string(client
->proto
));
3838 client
->l3vnidel_cnt
++;
3839 return zserv_send_message(client
, s
);
3842 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
3847 /* send l3vni add to BGP */
3848 zl3vni_send_add_to_client(zl3vni
);
3851 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
3856 /* send l3-vni del to BGP*/
3857 zl3vni_send_del_to_client(zl3vni
);
3860 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
, void *ctxt
)
3862 zebra_vni_t
*zvni
= (zebra_vni_t
*)backet
->data
;
3863 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
3865 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
3866 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3870 * handle transition of vni from l2 to l3 and vice versa
3872 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
3875 zebra_vni_t
*zvni
= NULL
;
3877 /* There is a possibility that VNI notification was already received
3878 * from kernel and we programmed it as L2-VNI
3879 * In such a case we need to delete this L2-VNI first, so
3880 * that it can be reprogrammed as L3-VNI in the system. It is also
3881 * possible that the vrf-vni mapping is removed from FRR while the vxlan
3882 * interface is still present in kernel. In this case to keep it
3883 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
3886 /* Locate hash entry */
3887 zvni
= zvni_lookup(vni
);
3891 if (IS_ZEBRA_DEBUG_VXLAN
)
3892 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
3894 /* Delete VNI from BGP. */
3895 zvni_send_del_to_client(zvni
->vni
);
3897 /* Free up all neighbors and MAC, if any. */
3898 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
3899 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
3901 /* Free up all remote VTEPs, if any. */
3902 zvni_vtep_del_all(zvni
, 0);
3904 /* Delete the hash entry. */
3905 if (zvni_del(zvni
)) {
3906 zlog_err("Failed to del VNI hash %p, VNI %u", zvni
,
3911 /* TODO_MITESH: This needs to be thought through. We don't have
3912 * enough information at this point to reprogram the vni as
3913 * l2-vni. One way is to store the required info in l3-vni and
3914 * used it solely for this purpose
3921 /* delete and uninstall rmac hash entry */
3922 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
, void *ctx
)
3924 zebra_mac_t
*zrmac
= NULL
;
3925 zebra_l3vni_t
*zl3vni
= NULL
;
3927 zrmac
= (zebra_mac_t
*)backet
->data
;
3928 zl3vni
= (zebra_l3vni_t
*)ctx
;
3929 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3930 zl3vni_rmac_del(zl3vni
, zrmac
);
3933 /* delete and uninstall nh hash entry */
3934 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
, void *ctx
)
3936 zebra_neigh_t
*n
= NULL
;
3937 zebra_l3vni_t
*zl3vni
= NULL
;
3939 n
= (zebra_neigh_t
*)backet
->data
;
3940 zl3vni
= (zebra_l3vni_t
*)ctx
;
3941 zl3vni_nh_uninstall(zl3vni
, n
);
3942 zl3vni_nh_del(zl3vni
, n
);
3945 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
3948 struct zserv
*client
= NULL
;
3949 struct stream
*s
= NULL
;
3950 char buf
[PREFIX_STRLEN
];
3952 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3953 /* BGP may not be running. */
3957 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3959 zclient_create_header(s
, cmd
, vrf_id
);
3960 stream_put(s
, p
, sizeof(struct prefix
));
3962 /* Write packet size. */
3963 stream_putw_at(s
, 0, stream_get_endp(s
));
3965 if (IS_ZEBRA_DEBUG_VXLAN
)
3966 zlog_debug("Send ip prefix %s %s on vrf %s",
3967 prefix2str(p
, buf
, sizeof(buf
)),
3968 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
3969 vrf_id_to_name(vrf_id
));
3971 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
3972 client
->prefixadd_cnt
++;
3974 client
->prefixdel_cnt
++;
3976 return zserv_send_message(client
, s
);
3979 /* re-add remote rmac if needed */
3980 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
3981 struct ethaddr
*rmac
)
3983 char buf
[ETHER_ADDR_STRLEN
];
3984 zebra_mac_t
*zrmac
= NULL
;
3986 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3990 if (IS_ZEBRA_DEBUG_VXLAN
)
3991 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
3992 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
3994 zl3vni_rmac_install(zl3vni
, zrmac
);
3998 /* Public functions */
4000 int is_l3vni_for_prefix_routes_only(vni_t vni
)
4002 zebra_l3vni_t
*zl3vni
= NULL
;
4004 zl3vni
= zl3vni_lookup(vni
);
4008 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
4011 /* handle evpn route in vrf table */
4012 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
4013 struct ipaddr
*vtep_ip
,
4014 struct prefix
*host_prefix
)
4016 zebra_l3vni_t
*zl3vni
= NULL
;
4017 struct ipaddr ipv4_vtep
;
4019 zl3vni
= zl3vni_from_vrf(vrf_id
);
4020 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
4024 * add the next hop neighbor -
4025 * neigh to be installed is the ipv6 nexthop neigh
4027 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
4030 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
4031 * address. Rmac is programmed against the ipv4 vtep because we only
4032 * support ipv4 tunnels in the h/w right now
4034 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
4035 ipv4_vtep
.ipa_type
= IPADDR_V4
;
4036 if (vtep_ip
->ipa_type
== IPADDR_V6
)
4037 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
4038 &(ipv4_vtep
.ipaddr_v4
));
4040 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
4041 sizeof(struct in_addr
));
4044 * add the rmac - remote rmac to be installed is against the ipv4
4047 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
4050 /* handle evpn vrf route delete */
4051 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
4052 struct ipaddr
*vtep_ip
,
4053 struct prefix
*host_prefix
)
4055 zebra_l3vni_t
*zl3vni
= NULL
;
4056 zebra_neigh_t
*nh
= NULL
;
4057 zebra_mac_t
*zrmac
= NULL
;
4059 zl3vni
= zl3vni_from_vrf(vrf_id
);
4063 /* find the next hop entry and rmac entry */
4064 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4067 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
4069 /* delete the next hop entry */
4070 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
4072 /* delete the rmac entry */
4074 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
4078 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
4079 struct ethaddr
*rmac
,
4082 zebra_l3vni_t
*zl3vni
= NULL
;
4083 zebra_mac_t
*zrmac
= NULL
;
4084 json_object
*json
= NULL
;
4086 if (!is_evpn_enabled()) {
4088 vty_out(vty
, "{}\n");
4093 json
= json_object_new_object();
4095 zl3vni
= zl3vni_lookup(l3vni
);
4098 vty_out(vty
, "{}\n");
4100 vty_out(vty
, "%% L3-VNI %u doesnt exist\n", l3vni
);
4104 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4107 vty_out(vty
, "{}\n");
4110 "%% Requested RMAC doesnt exist in L3-VNI %u",
4115 zl3vni_print_rmac(zrmac
, vty
, json
);
4118 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4119 json
, JSON_C_TO_STRING_PRETTY
));
4120 json_object_free(json
);
4124 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
,
4127 zebra_l3vni_t
*zl3vni
;
4129 struct rmac_walk_ctx wctx
;
4130 json_object
*json
= NULL
;
4132 if (!is_evpn_enabled())
4135 zl3vni
= zl3vni_lookup(l3vni
);
4138 vty_out(vty
, "{}\n");
4140 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4143 num_rmacs
= hashcount(zl3vni
->rmac_table
);
4148 json
= json_object_new_object();
4150 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
4154 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
4156 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
4158 json_object_int_add(json
, "numRmacs", num_rmacs
);
4160 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
4163 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4164 json
, JSON_C_TO_STRING_PRETTY
));
4165 json_object_free(json
);
4169 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, uint8_t use_json
)
4171 struct zebra_ns
*zns
= NULL
;
4172 json_object
*json
= NULL
;
4175 if (!is_evpn_enabled()) {
4177 vty_out(vty
, "{}\n");
4181 zns
= zebra_ns_lookup(NS_DEFAULT
);
4184 vty_out(vty
, "{}\n");
4189 json
= json_object_new_object();
4193 hash_iterate(zns
->l3vni_table
,
4194 (void (*)(struct hash_backet
*,
4195 void *))zl3vni_print_rmac_hash_all_vni
,
4199 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4200 json
, JSON_C_TO_STRING_PRETTY
));
4201 json_object_free(json
);
4205 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
4206 struct ipaddr
*ip
, uint8_t use_json
)
4208 zebra_l3vni_t
*zl3vni
= NULL
;
4209 zebra_neigh_t
*n
= NULL
;
4210 json_object
*json
= NULL
;
4212 if (!is_evpn_enabled()) {
4214 vty_out(vty
, "{}\n");
4219 json
= json_object_new_object();
4221 zl3vni
= zl3vni_lookup(l3vni
);
4224 vty_out(vty
, "{}\n");
4226 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4230 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4233 vty_out(vty
, "{}\n");
4236 "%% Requested next-hop not present for L3-VNI %u",
4241 zl3vni_print_nh(n
, vty
, json
);
4244 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4245 json
, JSON_C_TO_STRING_PRETTY
));
4246 json_object_free(json
);
4250 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, uint8_t use_json
)
4253 struct nh_walk_ctx wctx
;
4254 json_object
*json
= NULL
;
4255 zebra_l3vni_t
*zl3vni
= NULL
;
4257 if (!is_evpn_enabled())
4260 zl3vni
= zl3vni_lookup(l3vni
);
4263 vty_out(vty
, "{}\n");
4265 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4269 num_nh
= hashcount(zl3vni
->nh_table
);
4274 json
= json_object_new_object();
4279 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
4281 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
4283 json_object_int_add(json
, "numNextHops", num_nh
);
4285 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
4288 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4289 json
, JSON_C_TO_STRING_PRETTY
));
4290 json_object_free(json
);
4294 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, uint8_t use_json
)
4296 struct zebra_ns
*zns
= NULL
;
4297 json_object
*json
= NULL
;
4300 if (!is_evpn_enabled()) {
4302 vty_out(vty
, "{}\n");
4306 zns
= zebra_ns_lookup(NS_DEFAULT
);
4311 json
= json_object_new_object();
4315 hash_iterate(zns
->l3vni_table
,
4316 (void (*)(struct hash_backet
*,
4317 void *))zl3vni_print_nh_hash_all_vni
,
4321 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4322 json
, JSON_C_TO_STRING_PRETTY
));
4323 json_object_free(json
);
4329 * Display L3 VNI information (VTY command handler).
4331 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, uint8_t use_json
)
4334 json_object
*json
= NULL
;
4335 zebra_l3vni_t
*zl3vni
= NULL
;
4337 if (!is_evpn_enabled()) {
4339 vty_out(vty
, "{}\n");
4343 zl3vni
= zl3vni_lookup(vni
);
4346 vty_out(vty
, "{}\n");
4348 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4353 json
= json_object_new_object();
4357 zl3vni_print(zl3vni
, (void *)args
);
4360 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4361 json
, JSON_C_TO_STRING_PRETTY
));
4362 json_object_free(json
);
4366 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4367 json_object
*json_vrfs
)
4369 char buf
[ETHER_ADDR_STRLEN
];
4370 zebra_l3vni_t
*zl3vni
= NULL
;
4372 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4377 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
4378 zvrf_name(zvrf
), zl3vni
->vni
,
4379 zl3vni_vxlan_if_name(zl3vni
),
4380 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
4381 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4383 json_object
*json_vrf
= NULL
;
4384 json_vrf
= json_object_new_object();
4385 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
4386 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
4387 json_object_string_add(json_vrf
, "vxlanIntf",
4388 zl3vni_vxlan_if_name(zl3vni
));
4389 json_object_string_add(json_vrf
, "sviIntf",
4390 zl3vni_svi_if_name(zl3vni
));
4391 json_object_string_add(json_vrf
, "state",
4392 zl3vni_state2str(zl3vni
));
4393 json_object_string_add(
4394 json_vrf
, "routerMac",
4395 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4396 json_object_array_add(json_vrfs
, json_vrf
);
4401 * Display Neighbors for a VNI (VTY command handler).
4403 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4404 vni_t vni
, uint8_t use_json
)
4408 struct neigh_walk_ctx wctx
;
4409 json_object
*json
= NULL
;
4411 if (!is_evpn_enabled())
4413 zvni
= zvni_lookup(vni
);
4416 vty_out(vty
, "{}\n");
4418 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4421 num_neigh
= hashcount(zvni
->neigh_table
);
4426 json
= json_object_new_object();
4428 /* Since we have IPv6 addresses to deal with which can vary widely in
4429 * size, we try to be a bit more elegant in display by first computing
4430 * the maximum width.
4432 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4435 wctx
.addr_width
= 15;
4437 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4441 "Number of ARPs (local and remote) known for this VNI: %u\n",
4443 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
4444 "Type", "MAC", "Remote VTEP");
4446 json_object_int_add(json
, "numArpNd", num_neigh
);
4448 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4450 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4451 json
, JSON_C_TO_STRING_PRETTY
));
4452 json_object_free(json
);
4457 * Display neighbors across all VNIs (VTY command handler).
4459 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4462 json_object
*json
= NULL
;
4465 if (!is_evpn_enabled())
4469 json
= json_object_new_object();
4473 hash_iterate(zvrf
->vni_table
,
4474 (void (*)(struct hash_backet
*,
4475 void *))zvni_print_neigh_hash_all_vni
,
4478 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4479 json
, JSON_C_TO_STRING_PRETTY
));
4480 json_object_free(json
);
4485 * Display specific neighbor for a VNI, if present (VTY command handler).
4487 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
4488 struct zebra_vrf
*zvrf
, vni_t vni
,
4489 struct ipaddr
*ip
, uint8_t use_json
)
4493 json_object
*json
= NULL
;
4495 if (!is_evpn_enabled())
4497 zvni
= zvni_lookup(vni
);
4500 vty_out(vty
, "{}\n");
4502 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4505 n
= zvni_neigh_lookup(zvni
, ip
);
4509 "%% Requested neighbor does not exist in VNI %u\n",
4514 json
= json_object_new_object();
4516 zvni_print_neigh(n
, vty
, json
);
4519 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4520 json
, JSON_C_TO_STRING_PRETTY
));
4521 json_object_free(json
);
4526 * Display neighbors for a VNI from specific VTEP (VTY command handler).
4527 * By definition, these are remote neighbors.
4529 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4530 vni_t vni
, struct in_addr vtep_ip
,
4535 struct neigh_walk_ctx wctx
;
4536 json_object
*json
= NULL
;
4538 if (!is_evpn_enabled())
4540 zvni
= zvni_lookup(vni
);
4543 vty_out(vty
, "{}\n");
4545 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4548 num_neigh
= hashcount(zvni
->neigh_table
);
4552 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4555 wctx
.addr_width
= 15;
4556 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
4557 wctx
.r_vtep_ip
= vtep_ip
;
4559 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4560 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4563 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4564 json
, JSON_C_TO_STRING_PRETTY
));
4565 json_object_free(json
);
4570 * Display MACs for a VNI (VTY command handler).
4572 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4573 vni_t vni
, uint8_t use_json
)
4577 struct mac_walk_ctx wctx
;
4578 json_object
*json
= NULL
;
4579 json_object
*json_mac
= NULL
;
4581 if (!is_evpn_enabled())
4583 zvni
= zvni_lookup(vni
);
4586 vty_out(vty
, "{}\n");
4588 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4591 num_macs
= num_valid_macs(zvni
);
4596 json
= json_object_new_object();
4597 json_mac
= json_object_new_object();
4600 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4603 wctx
.json
= json_mac
;
4607 "Number of MACs (local and remote) known for this VNI: %u\n",
4609 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
4610 "Intf/Remote VTEP", "VLAN");
4612 json_object_int_add(json
, "numMacs", num_macs
);
4614 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4617 json_object_object_add(json
, "macs", json_mac
);
4618 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4619 json
, JSON_C_TO_STRING_PRETTY
));
4620 json_object_free(json
);
4625 * Display MACs for all VNIs (VTY command handler).
4627 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4630 struct mac_walk_ctx wctx
;
4631 json_object
*json
= NULL
;
4633 if (!is_evpn_enabled()) {
4635 vty_out(vty
, "{}\n");
4639 json
= json_object_new_object();
4641 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4644 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4647 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4648 json
, JSON_C_TO_STRING_PRETTY
));
4649 json_object_free(json
);
4654 * Display MACs for all VNIs (VTY command handler).
4656 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
4657 struct zebra_vrf
*zvrf
,
4658 struct in_addr vtep_ip
,
4661 struct mac_walk_ctx wctx
;
4662 json_object
*json
= NULL
;
4664 if (!is_evpn_enabled())
4668 json
= json_object_new_object();
4670 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4672 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4673 wctx
.r_vtep_ip
= vtep_ip
;
4675 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4678 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4679 json
, JSON_C_TO_STRING_PRETTY
));
4680 json_object_free(json
);
4685 * Display specific MAC for a VNI, if present (VTY command handler).
4687 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4688 vni_t vni
, struct ethaddr
*macaddr
)
4693 if (!is_evpn_enabled())
4695 zvni
= zvni_lookup(vni
);
4697 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4700 mac
= zvni_mac_lookup(zvni
, macaddr
);
4702 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
4707 zvni_print_mac(mac
, vty
);
4711 * Display MACs for a VNI from specific VTEP (VTY command handler).
4713 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4714 vni_t vni
, struct in_addr vtep_ip
,
4719 struct mac_walk_ctx wctx
;
4720 json_object
*json
= NULL
;
4721 json_object
*json_mac
= NULL
;
4723 if (!is_evpn_enabled())
4725 zvni
= zvni_lookup(vni
);
4728 vty_out(vty
, "{}\n");
4730 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4733 num_macs
= num_valid_macs(zvni
);
4738 json
= json_object_new_object();
4739 json_mac
= json_object_new_object();
4742 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4745 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4746 wctx
.r_vtep_ip
= vtep_ip
;
4747 wctx
.json
= json_mac
;
4748 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4751 json_object_int_add(json
, "numMacs", wctx
.count
);
4753 json_object_object_add(json
, "macs", json_mac
);
4754 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4755 json
, JSON_C_TO_STRING_PRETTY
));
4756 json_object_free(json
);
4762 * Display VNI information (VTY command handler).
4764 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
4767 json_object
*json
= NULL
;
4769 zebra_l3vni_t
*zl3vni
= NULL
;
4770 zebra_vni_t
*zvni
= NULL
;
4772 if (!is_evpn_enabled())
4776 json
= json_object_new_object();
4780 zl3vni
= zl3vni_lookup(vni
);
4782 zl3vni_print(zl3vni
, (void *)args
);
4784 zvni
= zvni_lookup(vni
);
4787 vty_out(vty
, "{}\n");
4789 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4793 zvni_print(zvni
, (void *)args
);
4797 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4798 json
, JSON_C_TO_STRING_PRETTY
));
4799 json_object_free(json
);
4803 /* Display all global details for EVPN */
4804 void zebra_vxlan_print_evpn(struct vty
*vty
, uint8_t uj
)
4809 json_object
*json
= NULL
;
4810 struct zebra_ns
*zns
= NULL
;
4811 struct zebra_vrf
*zvrf
= NULL
;
4813 if (!is_evpn_enabled())
4816 zns
= zebra_ns_lookup(NS_DEFAULT
);
4820 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
4824 num_l3vnis
= hashcount(zns
->l3vni_table
);
4825 num_l2vnis
= hashcount(zvrf
->vni_table
);
4826 num_vnis
= num_l2vnis
+ num_l3vnis
;
4829 json
= json_object_new_object();
4830 json_object_string_add(json
, "advertiseGatewayMacip",
4831 zvrf
->advertise_gw_macip
? "Yes" : "No");
4832 json_object_int_add(json
, "numVnis", num_vnis
);
4833 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4834 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4836 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
4837 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
4838 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
4839 zvrf
->advertise_gw_macip
? "Yes" : "No");
4843 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4844 json
, JSON_C_TO_STRING_PRETTY
));
4845 json_object_free(json
);
4850 * Display VNI hash table (VTY command handler).
4852 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4855 json_object
*json
= NULL
;
4856 struct zebra_ns
*zns
= NULL
;
4859 if (!is_evpn_enabled())
4862 zns
= zebra_ns_lookup(NS_DEFAULT
);
4868 json
= json_object_new_object();
4870 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
4871 "Type", "VxLAN IF", "# MACs", "# ARPs",
4872 "# Remote VTEPs", "Tenant VRF");
4877 /* Display all L2-VNIs */
4878 hash_iterate(zvrf
->vni_table
,
4879 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
4882 /* Display all L3-VNIs */
4883 hash_iterate(zns
->l3vni_table
,
4884 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
4888 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4889 json
, JSON_C_TO_STRING_PRETTY
));
4890 json_object_free(json
);
4895 * Handle neighbor delete notification from the kernel (on a VLAN device
4896 * / L3 interface). This may result in either the neighbor getting deleted
4897 * from our database or being re-added to the kernel (if it is a valid
4900 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
4901 struct interface
*link_if
,
4904 char buf
[INET6_ADDRSTRLEN
];
4905 char buf2
[ETHER_ADDR_STRLEN
];
4906 zebra_neigh_t
*n
= NULL
;
4907 zebra_vni_t
*zvni
= NULL
;
4908 zebra_mac_t
*zmac
= NULL
;
4909 zebra_l3vni_t
*zl3vni
= NULL
;
4911 /* check if this is a remote neigh entry corresponding to remote
4914 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4916 return zl3vni_local_nh_del(zl3vni
, ip
);
4918 /* We are only interested in neighbors on an SVI that resides on top
4919 * of a VxLAN bridge.
4921 zvni
= zvni_from_svi(ifp
, link_if
);
4925 if (!zvni
->vxlan_if
) {
4927 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
4932 if (IS_ZEBRA_DEBUG_VXLAN
)
4933 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
4934 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
4935 ifp
->ifindex
, zvni
->vni
);
4937 /* If entry doesn't exist, nothing to do. */
4938 n
= zvni_neigh_lookup(zvni
, ip
);
4942 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
4944 if (IS_ZEBRA_DEBUG_VXLAN
)
4946 "Trying to del a neigh %s without a mac %s on VNI %u",
4947 ipaddr2str(ip
, buf
, sizeof(buf
)),
4948 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
4954 /* If it is a remote entry, the kernel has aged this out or someone has
4955 * deleted it, it needs to be re-installed as Quagga is the owner.
4957 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
4958 zvni_neigh_install(zvni
, n
);
4962 /* Remove neighbor from BGP. */
4963 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
4964 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0);
4966 /* Delete this neighbor entry. */
4967 zvni_neigh_del(zvni
, n
);
4969 /* see if the AUTO mac needs to be deleted */
4970 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
4971 && !listcount(zmac
->neigh_list
))
4972 zvni_mac_del(zvni
, zmac
);
4978 * Handle neighbor add or update notification from the kernel (on a VLAN
4979 * device / L3 interface). This is typically for a local neighbor but can
4980 * also be for a remote neighbor (e.g., ageout notification). It could
4981 * also be a "move" scenario.
4983 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
4984 struct interface
*link_if
,
4986 struct ethaddr
*macaddr
,
4988 uint8_t ext_learned
,
4989 uint8_t router_flag
)
4991 char buf
[ETHER_ADDR_STRLEN
];
4992 char buf2
[INET6_ADDRSTRLEN
];
4993 zebra_vni_t
*zvni
= NULL
;
4994 zebra_l3vni_t
*zl3vni
= NULL
;
4996 /* check if this is a remote neigh entry corresponding to remote
4999 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5001 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
5003 /* We are only interested in neighbors on an SVI that resides on top
5004 * of a VxLAN bridge.
5006 zvni
= zvni_from_svi(ifp
, link_if
);
5010 if (IS_ZEBRA_DEBUG_VXLAN
)
5012 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u",
5013 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
5014 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5015 ifp
->ifindex
, state
, ext_learned
? "ext-learned " : "",
5018 /* Is this about a local neighbor or a remote one? */
5020 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
5023 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
5028 * Handle message from client to delete a remote MACIP for a VNI.
5030 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
5034 struct ethaddr macaddr
;
5036 struct in_addr vtep_ip
;
5040 unsigned short l
= 0, ipa_len
;
5041 char buf
[ETHER_ADDR_STRLEN
];
5042 char buf1
[INET6_ADDRSTRLEN
];
5043 struct interface
*ifp
= NULL
;
5044 struct zebra_if
*zif
= NULL
;
5046 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5047 memset(&ip
, 0, sizeof(struct ipaddr
));
5048 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5052 while (l
< hdr
->length
) {
5053 /* Obtain each remote MACIP and process. */
5054 /* Message contains VNI, followed by MAC followed by IP (if any)
5055 * followed by remote VTEP IP.
5059 memset(&ip
, 0, sizeof(ip
));
5060 STREAM_GETL(s
, vni
);
5061 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5062 STREAM_GETL(s
, ipa_len
);
5064 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5066 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5068 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5069 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5070 l
+= IPV4_MAX_BYTELEN
;
5072 if (IS_ZEBRA_DEBUG_VXLAN
)
5074 "Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
5075 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5076 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5078 zebra_route_string(client
->proto
));
5080 /* Locate VNI hash entry - expected to exist. */
5081 zvni
= zvni_lookup(vni
);
5083 if (IS_ZEBRA_DEBUG_VXLAN
)
5085 "Failed to locate VNI hash upon remote MACIP DEL, "
5090 ifp
= zvni
->vxlan_if
;
5093 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
5099 /* If down or not mapped to a bridge, we're done. */
5100 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5103 /* The remote VTEP specified is normally expected to exist, but
5105 * possible that the peer may delete the VTEP before deleting
5107 * referring to the VTEP, in which case the handler (see
5109 * would have already deleted the MACs.
5111 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5114 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5116 n
= zvni_neigh_lookup(zvni
, &ip
);
5119 zlog_err("Failed to locate MAC %s for neigh %s VNI %u",
5120 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5121 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5125 /* If the remote mac or neighbor doesn't exist there is nothing
5127 * to do. Otherwise, uninstall the entry and then remove it.
5132 /* Ignore the delete if this mac is a gateway mac-ip */
5133 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5134 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5136 "%u: Ignore Del for MAC %s neigh %s on VNI %u as it is configured as a default gateway",
5138 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5139 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5143 /* Uninstall remote neighbor or MAC. */
5145 /* When the MAC changes for an IP, it is possible the
5147 * update the new MAC before trying to delete the "old"
5149 * (as these are two different MACIP routes). Do the
5151 * if the MAC matches.
5153 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5154 && (memcmp(n
->emac
.octet
, macaddr
.octet
, ETH_ALEN
)
5156 zvni_neigh_uninstall(zvni
, n
);
5157 zvni_neigh_del(zvni
, n
);
5158 zvni_deref_ip2mac(zvni
, mac
, 1);
5161 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5162 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5164 if (list_isempty(mac
->neigh_list
)) {
5165 zvni_mac_uninstall(zvni
, mac
, 0);
5166 zvni_mac_del(zvni
, mac
);
5168 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5178 * Handle message from client to add a remote MACIP for a VNI. This
5179 * could be just the add of a MAC address or the add of a neighbor
5182 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
5186 struct ethaddr macaddr
;
5188 struct in_addr vtep_ip
;
5190 zebra_vtep_t
*zvtep
;
5191 zebra_mac_t
*mac
, *old_mac
;
5193 unsigned short l
= 0, ipa_len
;
5194 int update_mac
= 0, update_neigh
= 0;
5195 char buf
[ETHER_ADDR_STRLEN
];
5196 char buf1
[INET6_ADDRSTRLEN
];
5198 u_char remote_gw
= 0;
5200 struct interface
*ifp
= NULL
;
5201 struct zebra_if
*zif
= NULL
;
5203 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5204 memset(&ip
, 0, sizeof(struct ipaddr
));
5205 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5207 if (!EVPN_ENABLED(zvrf
)) {
5209 "%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
5210 __PRETTY_FUNCTION__
);
5216 while (l
< hdr
->length
) {
5217 /* Obtain each remote MACIP and process. */
5218 /* Message contains VNI, followed by MAC followed by IP (if any)
5219 * followed by remote VTEP IP.
5221 update_mac
= update_neigh
= 0;
5224 memset(&ip
, 0, sizeof(ip
));
5225 STREAM_GETL(s
, vni
);
5226 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5227 STREAM_GETL(s
, ipa_len
);
5229 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5231 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5233 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5234 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5235 l
+= IPV4_MAX_BYTELEN
;
5237 /* Get flags - sticky mac and/or gateway mac */
5238 STREAM_GETC(s
, flags
);
5239 sticky
= CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5240 remote_gw
= CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5243 if (IS_ZEBRA_DEBUG_VXLAN
)
5245 "Recv MACIP Add MAC %s IP %s VNI %u Remote VTEP %s with flags 0x%x from %s",
5246 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5247 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5248 inet_ntoa(vtep_ip
), flags
,
5249 zebra_route_string(client
->proto
));
5251 /* Locate VNI hash entry - expected to exist. */
5252 zvni
= zvni_lookup(vni
);
5255 "Failed to locate VNI hash upon remote MACIP ADD, VNI %u",
5259 ifp
= zvni
->vxlan_if
;
5262 "VNI %u hash %p doesn't have intf upon remote MACIP add",
5268 /* If down or not mapped to a bridge, we're done. */
5269 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5272 /* The remote VTEP specified should normally exist, but it is
5274 * that when peering comes up, peer may advertise MACIP routes
5276 * advertising type-3 routes.
5278 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5280 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5282 "Failed to add remote VTEP, VNI %u zvni %p",
5287 zvni_vtep_install(zvni
, &vtep_ip
);
5290 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5292 /* Ignore the update if the mac is already present
5294 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)
5295 && CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5296 if (IS_ZEBRA_DEBUG_VXLAN
)
5298 "%u:Ignore MAC %s IP %s on VNI %u as MAC is already configured as gateway mac",
5300 prefix_mac2str(&macaddr
, buf
,
5302 ipaddr2str(&ip
, buf1
, sizeof(buf1
)),
5307 /* check if the remote MAC is unknown or has a change.
5308 * If so, that needs to be updated first. Note that client could
5309 * install MAC and MACIP separately or just install the latter.
5311 if (!mac
|| !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5312 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0)
5314 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
) ? 1 : 0)
5316 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
))
5321 mac
= zvni_mac_add(zvni
, &macaddr
);
5324 "Failed to add MAC %s VNI %u Remote VTEP %s",
5325 prefix_mac2str(&macaddr
, buf
,
5327 vni
, inet_ntoa(vtep_ip
));
5331 /* Is this MAC created for a MACIP? */
5333 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5336 /* Set "auto" and "remote" forwarding info. */
5337 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5338 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5339 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5340 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5343 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5345 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5348 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5350 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5352 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5354 /* Install the entry. */
5355 zvni_mac_install(zvni
, mac
);
5358 /* If there is no IP, continue - after clearing AUTO flag of
5361 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5365 /* Check if the remote neighbor itself is unknown or has a
5367 * If so, create or update and then install the entry.
5369 n
= zvni_neigh_lookup(zvni
, &ip
);
5370 if (!n
|| !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5371 || (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
)) != 0)
5372 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
))
5377 n
= zvni_neigh_add(zvni
, &ip
, &macaddr
);
5380 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5381 ipaddr2str(&ip
, buf1
,
5383 prefix_mac2str(&macaddr
, buf
,
5385 vni
, inet_ntoa(vtep_ip
));
5389 } else if (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
))
5391 /* MAC change, update neigh list for old and new
5393 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5395 listnode_delete(old_mac
->neigh_list
, n
);
5396 zvni_deref_ip2mac(zvni
, old_mac
, 1);
5398 listnode_add_sort(mac
->neigh_list
, n
);
5399 memcpy(&n
->emac
, &macaddr
, ETH_ALEN
);
5402 /* Set "remote" forwarding info. */
5403 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5404 /* TODO: Handle MAC change. */
5405 n
->r_vtep_ip
= vtep_ip
;
5406 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5408 /* Set router flag (R-bit) to this Neighbor entry */
5409 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5410 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5412 /* Install the entry. */
5413 zvni_neigh_install(zvni
, n
);
5422 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5423 * us, this must involve a multihoming scenario. Treat this as implicit delete
5424 * of any prior local MAC.
5426 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
5427 struct interface
*br_if
,
5428 struct ethaddr
*macaddr
, vlanid_t vid
)
5430 struct zebra_if
*zif
;
5431 struct zebra_l2info_vxlan
*vxl
;
5435 char buf
[ETHER_ADDR_STRLEN
];
5439 vxl
= &zif
->l2info
.vxl
;
5442 /* Check if EVPN is enabled. */
5443 if (!is_evpn_enabled())
5446 /* Locate hash entry; it is expected to exist. */
5447 zvni
= zvni_lookup(vni
);
5451 /* If entry doesn't exist, nothing to do. */
5452 mac
= zvni_mac_lookup(zvni
, macaddr
);
5456 /* Is it a local entry? */
5457 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5460 if (IS_ZEBRA_DEBUG_VXLAN
)
5462 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5463 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5466 /* Remove MAC from BGP. */
5467 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5470 * If there are no neigh associated with the mac delete the mac
5471 * else mark it as AUTO for forward reference
5473 if (!listcount(mac
->neigh_list
)) {
5474 zvni_mac_del(zvni
, mac
);
5476 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5477 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5484 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5485 * This can happen because the remote MAC entries are also added as "dynamic",
5486 * so the kernel can ageout the entry.
5488 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
5489 struct interface
*br_if
,
5490 struct ethaddr
*macaddr
, vlanid_t vid
)
5492 struct zebra_if
*zif
= NULL
;
5493 struct zebra_l2info_vxlan
*vxl
= NULL
;
5495 zebra_vni_t
*zvni
= NULL
;
5496 zebra_l3vni_t
*zl3vni
= NULL
;
5497 zebra_mac_t
*mac
= NULL
;
5498 char buf
[ETHER_ADDR_STRLEN
];
5502 vxl
= &zif
->l2info
.vxl
;
5505 /* Check if EVPN is enabled. */
5506 if (!is_evpn_enabled())
5509 /* check if this is a remote RMAC and readd simillar to remote macs */
5510 zl3vni
= zl3vni_lookup(vni
);
5512 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
5514 /* Locate hash entry; it is expected to exist. */
5515 zvni
= zvni_lookup(vni
);
5519 /* If entry doesn't exist, nothing to do. */
5520 mac
= zvni_mac_lookup(zvni
, macaddr
);
5524 /* Is it a remote entry? */
5525 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
5528 if (IS_ZEBRA_DEBUG_VXLAN
)
5529 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
5530 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5533 zvni_mac_install(zvni
, mac
);
5538 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
5540 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
5541 struct ethaddr
*macaddr
, vlanid_t vid
)
5545 char buf
[ETHER_ADDR_STRLEN
];
5547 /* We are interested in MACs only on ports or (port, VLAN) that
5550 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5553 if (!zvni
->vxlan_if
) {
5554 zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL",
5559 if (IS_ZEBRA_DEBUG_VXLAN
)
5560 zlog_debug("Del MAC %s intf %s(%u) VID %u -> VNI %u",
5561 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5562 ifp
->ifindex
, vid
, zvni
->vni
);
5564 /* If entry doesn't exist, nothing to do. */
5565 mac
= zvni_mac_lookup(zvni
, macaddr
);
5569 /* Is it a local entry? */
5570 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5573 /* Remove MAC from BGP. */
5574 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5576 /* Update all the neigh entries associated with this mac */
5577 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
5580 * If there are no neigh associated with the mac delete the mac
5581 * else mark it as AUTO for forward reference
5583 if (!listcount(mac
->neigh_list
)) {
5584 zvni_mac_del(zvni
, mac
);
5586 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5587 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5594 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
5596 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
5597 struct interface
*br_if
,
5598 struct ethaddr
*macaddr
, vlanid_t vid
,
5603 char buf
[ETHER_ADDR_STRLEN
];
5607 /* We are interested in MACs only on ports or (port, VLAN) that
5610 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5612 if (IS_ZEBRA_DEBUG_VXLAN
)
5614 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5615 sticky
? "sticky " : "",
5616 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5617 ifp
->name
, ifp
->ifindex
, vid
);
5621 if (!zvni
->vxlan_if
) {
5622 zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD",
5627 if (IS_ZEBRA_DEBUG_VXLAN
)
5628 zlog_debug("Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
5629 sticky
? "sticky " : "",
5630 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5631 ifp
->ifindex
, vid
, zvni
->vni
);
5633 /* If same entry already exists, nothing to do. */
5634 mac
= zvni_mac_lookup(zvni
, macaddr
);
5636 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5637 mac_sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5643 * return if nothing has changed.
5644 * inform bgp if sticky flag has changed
5645 * update locally and do not inform bgp if local
5646 * parameters like interface has changed
5648 if (mac_sticky
== sticky
5649 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
5650 && mac
->fwd_info
.local
.vid
== vid
) {
5651 if (IS_ZEBRA_DEBUG_VXLAN
)
5653 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
5654 "entry exists and has not changed ",
5655 sticky
? "sticky " : "",
5656 prefix_mac2str(macaddr
, buf
,
5658 ifp
->name
, ifp
->ifindex
, vid
,
5661 } else if (mac_sticky
!= sticky
) {
5664 add
= 0; /* This is an update of local
5667 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5669 * If we have already learned the MAC as a remote sticky
5671 * this is a operator error and we must log a warning
5673 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
5675 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
5676 prefix_mac2str(macaddr
, buf
,
5678 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
5686 mac
= zvni_mac_add(zvni
, macaddr
);
5688 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
5689 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5690 ifp
->name
, ifp
->ifindex
, vid
);
5695 /* Set "local" forwarding info. */
5696 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5697 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5698 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5699 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5700 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
5701 mac
->fwd_info
.local
.vid
= vid
;
5704 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5706 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5708 /* Inform BGP if required. */
5710 zvni_process_neigh_on_local_mac_add(zvni
, mac
);
5711 return zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
5719 * Handle message from client to delete a remote VTEP for a VNI.
5721 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
5724 unsigned short l
= 0;
5726 struct in_addr vtep_ip
;
5728 zebra_vtep_t
*zvtep
;
5729 struct interface
*ifp
;
5730 struct zebra_if
*zif
;
5732 if (!is_evpn_enabled()) {
5734 "%s: EVPN is not enabled yet we have received a vtep del command",
5735 __PRETTY_FUNCTION__
);
5739 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5740 zlog_err("Recv MACIP DEL for non-default VRF %u",
5747 while (l
< hdr
->length
) {
5748 /* Obtain each remote VTEP and process. */
5749 STREAM_GETL(s
, vni
);
5751 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5752 l
+= IPV4_MAX_BYTELEN
;
5754 if (IS_ZEBRA_DEBUG_VXLAN
)
5755 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
5756 inet_ntoa(vtep_ip
), vni
,
5757 zebra_route_string(client
->proto
));
5759 /* Locate VNI hash entry - expected to exist. */
5760 zvni
= zvni_lookup(vni
);
5762 if (IS_ZEBRA_DEBUG_VXLAN
)
5764 "Failed to locate VNI hash upon remote VTEP DEL, "
5770 ifp
= zvni
->vxlan_if
;
5773 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
5779 /* If down or not mapped to a bridge, we're done. */
5780 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5783 /* If the remote VTEP does not exist, there's nothing more to
5785 * Otherwise, uninstall any remote MACs pointing to this VTEP
5787 * then, the VTEP entry itself and remove it.
5789 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5793 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
5794 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
5795 zvni_vtep_uninstall(zvni
, &vtep_ip
);
5796 zvni_vtep_del(zvni
, zvtep
);
5804 * Handle message from client to add a remote VTEP for a VNI.
5806 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
5809 unsigned short l
= 0;
5811 struct in_addr vtep_ip
;
5813 struct interface
*ifp
;
5814 struct zebra_if
*zif
;
5816 if (!is_evpn_enabled()) {
5818 "%s: EVPN not enabled yet we received a vtep_add zapi call",
5819 __PRETTY_FUNCTION__
);
5823 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5824 zlog_err("Recv MACIP ADD for non-default VRF %u",
5831 while (l
< hdr
->length
) {
5832 /* Obtain each remote VTEP and process. */
5833 STREAM_GETL(s
, vni
);
5835 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5836 l
+= IPV4_MAX_BYTELEN
;
5838 if (IS_ZEBRA_DEBUG_VXLAN
)
5839 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
5840 inet_ntoa(vtep_ip
), vni
,
5841 zebra_route_string(client
->proto
));
5843 /* Locate VNI hash entry - expected to exist. */
5844 zvni
= zvni_lookup(vni
);
5847 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
5852 ifp
= zvni
->vxlan_if
;
5855 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
5862 /* If down or not mapped to a bridge, we're done. */
5863 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5866 /* If the remote VTEP already exists,
5867 there's nothing more to do. */
5868 if (zvni_vtep_find(zvni
, &vtep_ip
))
5871 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5872 zlog_err("Failed to add remote VTEP, VNI %u zvni %p",
5877 zvni_vtep_install(zvni
, &vtep_ip
);
5885 * Add/Del gateway macip to evpn
5887 * 1. SVI interface on a vlan aware bridge
5888 * 2. SVI interface on a vlan unaware bridge
5889 * 3. vrr interface (MACVLAN) associated to a SVI
5890 * We advertise macip routes for an interface if it is associated to VxLan vlan
5892 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
5896 struct ethaddr macaddr
;
5897 zebra_vni_t
*zvni
= NULL
;
5899 memset(&ip
, 0, sizeof(struct ipaddr
));
5900 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5902 /* Check if EVPN is enabled. */
5903 if (!is_evpn_enabled())
5906 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
5907 struct interface
*svi_if
=
5908 NULL
; /* SVI corresponding to the MACVLAN */
5909 struct zebra_if
*ifp_zif
=
5910 NULL
; /* Zebra daemon specific info for MACVLAN */
5911 struct zebra_if
*svi_if_zif
=
5912 NULL
; /* Zebra daemon specific info for SVI*/
5914 ifp_zif
= ifp
->info
;
5919 * for a MACVLAN interface the link represents the svi_if
5921 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
5922 ifp_zif
->link_ifindex
);
5924 zlog_err("MACVLAN %s(%u) without link information",
5925 ifp
->name
, ifp
->ifindex
);
5929 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
5931 * If it is a vlan aware bridge then the link gives the
5932 * bridge information
5934 struct interface
*svi_if_link
= NULL
;
5936 svi_if_zif
= svi_if
->info
;
5938 svi_if_link
= if_lookup_by_index_per_ns(
5939 zebra_ns_lookup(NS_DEFAULT
),
5940 svi_if_zif
->link_ifindex
);
5941 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
5943 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
5945 * If it is a vlan unaware bridge then svi is the bridge
5948 zvni
= zvni_from_svi(svi_if
, svi_if
);
5950 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
5951 struct zebra_if
*svi_if_zif
=
5952 NULL
; /* Zebra daemon specific info for SVI */
5953 struct interface
*svi_if_link
=
5954 NULL
; /* link info for the SVI = bridge info */
5956 svi_if_zif
= ifp
->info
;
5958 svi_if_link
= if_lookup_by_index_per_ns(
5959 zebra_ns_lookup(NS_DEFAULT
),
5960 svi_if_zif
->link_ifindex
);
5962 zvni
= zvni_from_svi(ifp
, svi_if_link
);
5964 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
5965 zvni
= zvni_from_svi(ifp
, ifp
);
5971 if (!zvni
->vxlan_if
) {
5972 zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
5978 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
5980 if (p
->family
== AF_INET
) {
5981 ip
.ipa_type
= IPADDR_V4
;
5982 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
5983 sizeof(struct in_addr
));
5984 } else if (p
->family
== AF_INET6
) {
5985 ip
.ipa_type
= IPADDR_V6
;
5986 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
5987 sizeof(struct in6_addr
));
5992 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
5994 zvni_gw_macip_del(ifp
, zvni
, &ip
);
6000 * Handle SVI interface going down.
6001 * SVI can be associated to either L3-VNI or L2-VNI.
6002 * For L2-VNI: At this point, this is a NOP since
6003 * the kernel deletes the neighbor entries on this SVI (if any).
6004 * We only need to update the vrf corresponding to zvni.
6005 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
6008 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
6010 zebra_l3vni_t
*zl3vni
= NULL
;
6012 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6015 /* process l3-vni down */
6016 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6018 /* remove association with svi-if */
6019 zl3vni
->svi_if
= NULL
;
6021 zebra_vni_t
*zvni
= NULL
;
6023 /* since we dont have svi corresponding to zvni, we associate it
6024 * to default vrf. Note: the corresponding neigh entries on the
6025 * SVI would have already been deleted */
6026 zvni
= zvni_from_svi(ifp
, link_if
);
6028 zvni
->vrf_id
= VRF_DEFAULT
;
6030 /* update the tenant vrf in BGP */
6031 zvni_send_add_to_client(zvni
);
6038 * Handle SVI interface coming up.
6039 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
6041 * For L2-VNI: we need to install any remote neighbors entried (used for
6043 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
6045 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
6047 zebra_vni_t
*zvni
= NULL
;
6048 zebra_l3vni_t
*zl3vni
= NULL
;
6050 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6053 /* associate with svi */
6054 zl3vni
->svi_if
= ifp
;
6056 /* process oper-up */
6057 if (is_l3vni_oper_up(zl3vni
))
6058 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6061 /* process SVI up for l2-vni */
6062 struct neigh_walk_ctx n_wctx
;
6064 zvni
= zvni_from_svi(ifp
, link_if
);
6068 if (!zvni
->vxlan_if
) {
6069 zlog_err("VNI %u hash %p doesn't have intf upon SVI up",
6074 if (IS_ZEBRA_DEBUG_VXLAN
)
6076 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
6077 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
6078 vrf_id_to_name(ifp
->vrf_id
));
6080 /* update the vrf information for l2-vni and inform bgp */
6081 zvni
->vrf_id
= ifp
->vrf_id
;
6082 zvni_send_add_to_client(zvni
);
6084 /* Install any remote neighbors for this VNI. */
6085 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6087 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6095 * Handle VxLAN interface down
6097 int zebra_vxlan_if_down(struct interface
*ifp
)
6100 struct zebra_if
*zif
= NULL
;
6101 struct zebra_l2info_vxlan
*vxl
= NULL
;
6102 zebra_l3vni_t
*zl3vni
= NULL
;
6105 /* Check if EVPN is enabled. */
6106 if (!is_evpn_enabled())
6111 vxl
= &zif
->l2info
.vxl
;
6114 zl3vni
= zl3vni_lookup(vni
);
6116 /* process-if-down for l3-vni */
6117 if (IS_ZEBRA_DEBUG_VXLAN
)
6118 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
6121 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6123 /* process if-down for l2-vni */
6124 if (IS_ZEBRA_DEBUG_VXLAN
)
6125 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
6128 /* Locate hash entry; it is expected to exist. */
6129 zvni
= zvni_lookup(vni
);
6132 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
6133 ifp
->name
, ifp
->ifindex
, vni
);
6137 assert(zvni
->vxlan_if
== ifp
);
6139 /* Delete this VNI from BGP. */
6140 zvni_send_del_to_client(zvni
->vni
);
6142 /* Free up all neighbors and MACs, if any. */
6143 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6144 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6146 /* Free up all remote VTEPs, if any. */
6147 zvni_vtep_del_all(zvni
, 1);
6153 * Handle VxLAN interface up - update BGP if required.
6155 int zebra_vxlan_if_up(struct interface
*ifp
)
6158 struct zebra_if
*zif
= NULL
;
6159 struct zebra_l2info_vxlan
*vxl
= NULL
;
6160 zebra_vni_t
*zvni
= NULL
;
6161 zebra_l3vni_t
*zl3vni
= NULL
;
6163 /* Check if EVPN is enabled. */
6164 if (!is_evpn_enabled())
6169 vxl
= &zif
->l2info
.vxl
;
6172 zl3vni
= zl3vni_lookup(vni
);
6175 if (IS_ZEBRA_DEBUG_VXLAN
)
6176 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
6179 /* we need to associate with SVI, if any, we can associate with
6180 * svi-if only after association with vxlan-intf is complete
6182 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6184 if (is_l3vni_oper_up(zl3vni
))
6185 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6187 /* Handle L2-VNI add */
6188 struct interface
*vlan_if
= NULL
;
6190 if (IS_ZEBRA_DEBUG_VXLAN
)
6191 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
6194 /* Locate hash entry; it is expected to exist. */
6195 zvni
= zvni_lookup(vni
);
6198 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
6199 ifp
->name
, ifp
->ifindex
, vni
);
6203 assert(zvni
->vxlan_if
== ifp
);
6204 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6205 zif
->brslave_info
.br_if
);
6207 zvni
->vrf_id
= vlan_if
->vrf_id
;
6208 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6210 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6213 /* If part of a bridge, inform BGP about this VNI. */
6214 /* Also, read and populate local MACs and neighbors. */
6215 if (zif
->brslave_info
.br_if
) {
6216 zvni_send_add_to_client(zvni
);
6217 zvni_read_mac_neigh(zvni
, ifp
);
6225 * Handle VxLAN interface delete. Locate and remove entry in hash table
6226 * and update BGP, if required.
6228 int zebra_vxlan_if_del(struct interface
*ifp
)
6231 struct zebra_if
*zif
= NULL
;
6232 struct zebra_l2info_vxlan
*vxl
= NULL
;
6233 zebra_vni_t
*zvni
= NULL
;
6234 zebra_l3vni_t
*zl3vni
= NULL
;
6236 /* Check if EVPN is enabled. */
6237 if (!is_evpn_enabled())
6242 vxl
= &zif
->l2info
.vxl
;
6245 zl3vni
= zl3vni_lookup(vni
);
6248 if (IS_ZEBRA_DEBUG_VXLAN
)
6249 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
6252 /* process oper-down for l3-vni */
6253 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6255 /* remove the association with vxlan_if */
6256 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
6257 zl3vni
->vxlan_if
= NULL
;
6260 /* process if-del for l2-vni*/
6261 if (IS_ZEBRA_DEBUG_VXLAN
)
6262 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
6265 /* Locate hash entry; it is expected to exist. */
6266 zvni
= zvni_lookup(vni
);
6269 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6270 ifp
->name
, ifp
->ifindex
, vni
);
6274 /* remove from l3-vni list */
6275 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
6277 listnode_delete(zl3vni
->l2vnis
, zvni
);
6279 /* Delete VNI from BGP. */
6280 zvni_send_del_to_client(zvni
->vni
);
6282 /* Free up all neighbors and MAC, if any. */
6283 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
6284 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
6286 /* Free up all remote VTEPs, if any. */
6287 zvni_vtep_del_all(zvni
, 0);
6289 /* Delete the hash entry. */
6290 if (zvni_del(zvni
)) {
6291 zlog_err("Failed to del VNI hash %p, IF %s(%u) VNI %u",
6292 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
6300 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6302 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
6305 struct zebra_if
*zif
= NULL
;
6306 struct zebra_l2info_vxlan
*vxl
= NULL
;
6307 zebra_vni_t
*zvni
= NULL
;
6308 zebra_l3vni_t
*zl3vni
= NULL
;
6310 /* Check if EVPN is enabled. */
6311 if (!is_evpn_enabled())
6316 vxl
= &zif
->l2info
.vxl
;
6319 zl3vni
= zl3vni_lookup(vni
);
6322 if (IS_ZEBRA_DEBUG_VXLAN
)
6324 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6325 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6326 inet_ntoa(vxl
->vtep_ip
),
6327 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6329 /* Removed from bridge? Cleanup and return */
6330 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6331 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6332 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6336 /* access-vlan change - process oper down, associate with new
6337 * svi_if and then process oper up again
6339 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6340 if (if_is_operative(ifp
)) {
6341 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6342 zl3vni
->svi_if
= NULL
;
6343 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6344 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6345 if (is_l3vni_oper_up(zl3vni
))
6346 zebra_vxlan_process_l3vni_oper_up(
6352 * local-ip change - process oper down, associate with new
6353 * local-ip and then process oper up again
6355 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
6356 if (if_is_operative(ifp
)) {
6357 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6358 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6359 if (is_l3vni_oper_up(zl3vni
))
6360 zebra_vxlan_process_l3vni_oper_up(
6365 /* Update local tunnel IP. */
6366 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6368 /* if we have a valid new master, process l3-vni oper up */
6369 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
6370 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
6371 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6375 /* Update VNI hash. */
6376 zvni
= zvni_lookup(vni
);
6379 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6380 ifp
->name
, ifp
->ifindex
, vni
);
6384 if (IS_ZEBRA_DEBUG_VXLAN
)
6386 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6387 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6388 inet_ntoa(vxl
->vtep_ip
),
6389 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6391 /* Removed from bridge? Cleanup and return */
6392 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6393 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6394 /* Delete from client, remove all remote VTEPs */
6395 /* Also, free up all MACs and neighbors. */
6396 zvni_send_del_to_client(zvni
->vni
);
6397 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6398 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6399 zvni_vtep_del_all(zvni
, 1);
6403 /* Handle other changes. */
6404 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6405 /* Remove all existing local neigh and MACs for this VNI
6406 * (including from BGP)
6408 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6409 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6412 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6413 zvni
->vxlan_if
= ifp
;
6415 /* Take further actions needed.
6416 * Note that if we are here, there is a change of interest.
6418 /* If down or not mapped to a bridge, we're done. */
6419 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6422 /* Inform BGP, if there is a change of interest. */
6424 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
6425 zvni_send_add_to_client(zvni
);
6427 /* If there is a valid new master or a VLAN mapping change,
6428 * read and populate local MACs and neighbors.
6429 * Also, reinstall any remote MACs and neighbors
6430 * for this VNI (based on new VLAN).
6432 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6433 zvni_read_mac_neigh(zvni
, ifp
);
6434 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6435 struct mac_walk_ctx m_wctx
;
6436 struct neigh_walk_ctx n_wctx
;
6438 zvni_read_mac_neigh(zvni
, ifp
);
6440 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6442 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
6445 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6447 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6456 * Handle VxLAN interface add.
6458 int zebra_vxlan_if_add(struct interface
*ifp
)
6461 struct zebra_if
*zif
= NULL
;
6462 struct zebra_l2info_vxlan
*vxl
= NULL
;
6463 zebra_vni_t
*zvni
= NULL
;
6464 zebra_l3vni_t
*zl3vni
= NULL
;
6466 /* Check if EVPN is enabled. */
6467 if (!is_evpn_enabled())
6472 vxl
= &zif
->l2info
.vxl
;
6475 zl3vni
= zl3vni_lookup(vni
);
6478 /* process if-add for l3-vni*/
6479 if (IS_ZEBRA_DEBUG_VXLAN
)
6481 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6482 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6483 inet_ntoa(vxl
->vtep_ip
),
6484 zif
->brslave_info
.bridge_ifindex
);
6486 /* associate with vxlan_if */
6487 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6488 zl3vni
->vxlan_if
= ifp
;
6490 /* Associate with SVI, if any. We can associate with svi-if only
6491 * after association with vxlan_if is complete */
6492 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6494 if (is_l3vni_oper_up(zl3vni
))
6495 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6498 /* process if-add for l2-vni */
6499 struct interface
*vlan_if
= NULL
;
6501 /* Create or update VNI hash. */
6502 zvni
= zvni_lookup(vni
);
6504 zvni
= zvni_add(vni
);
6507 "Failed to add VNI hash, IF %s(%u) VNI %u",
6508 ifp
->name
, ifp
->ifindex
, vni
);
6513 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6514 zvni
->vxlan_if
= ifp
;
6515 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6516 zif
->brslave_info
.br_if
);
6518 zvni
->vrf_id
= vlan_if
->vrf_id
;
6519 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6521 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6524 if (IS_ZEBRA_DEBUG_VXLAN
)
6526 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6528 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
6530 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6531 inet_ntoa(vxl
->vtep_ip
),
6532 zif
->brslave_info
.bridge_ifindex
);
6534 /* If down or not mapped to a bridge, we're done. */
6535 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6539 zvni_send_add_to_client(zvni
);
6541 /* Read and populate local MACs and neighbors */
6542 zvni_read_mac_neigh(zvni
, ifp
);
6548 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
6549 char *err
, int err_str_sz
, int filter
,
6552 zebra_l3vni_t
*zl3vni
= NULL
;
6553 struct zebra_vrf
*zvrf_default
= NULL
;
6555 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
6559 if (IS_ZEBRA_DEBUG_VXLAN
)
6560 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
6561 add
? "ADD" : "DEL");
6565 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6567 /* check if the vni is already present under zvrf */
6569 snprintf(err
, err_str_sz
,
6570 "VNI is already configured under the vrf");
6574 /* check if this VNI is already present in the system */
6575 zl3vni
= zl3vni_lookup(vni
);
6577 snprintf(err
, err_str_sz
,
6578 "VNI is already configured as L3-VNI");
6582 /* add the L3-VNI to the global table */
6583 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
6585 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
6589 /* associate the vrf with vni */
6592 /* set the filter in l3vni to denote if we are using l3vni only
6596 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
6598 /* associate with vxlan-intf;
6599 * we need to associate with the vxlan-intf first
6601 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
6603 /* associate with corresponding SVI interface, we can associate
6604 * with svi-if only after vxlan interface association is
6607 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6609 /* formulate l2vni list */
6610 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
6613 if (is_l3vni_oper_up(zl3vni
))
6614 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6617 zl3vni
= zl3vni_lookup(vni
);
6619 snprintf(err
, err_str_sz
, "VNI doesn't exist");
6623 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
6624 snprintf(err
, ERR_STR_SZ
,
6625 "prefix-routes-only is not set for the vni");
6629 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6631 /* delete and uninstall all rmacs */
6632 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
6635 /* delete and uninstall all next-hops */
6636 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
6642 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6647 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
6649 zebra_l3vni_t
*zl3vni
= NULL
;
6652 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6656 zl3vni
->vrf_id
= zvrf_id(zvrf
);
6657 if (is_l3vni_oper_up(zl3vni
))
6658 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6662 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
6664 zebra_l3vni_t
*zl3vni
= NULL
;
6667 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6671 zl3vni
->vrf_id
= VRF_UNKNOWN
;
6672 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6676 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
6678 zebra_l3vni_t
*zl3vni
= NULL
;
6682 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6688 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
6694 * Handle message from client to enable/disable advertisement of g/w macip
6697 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
6702 zebra_vni_t
*zvni
= NULL
;
6703 struct interface
*ifp
= NULL
;
6704 struct zebra_if
*zif
= NULL
;
6705 struct zebra_l2info_vxlan zl2_info
;
6706 struct interface
*vlan_if
= NULL
;
6708 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6709 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6715 STREAM_GETC(s
, advertise
);
6716 vni
= stream_get3(s
);
6718 zvni
= zvni_lookup(vni
);
6722 if (zvni
->advertise_subnet
== advertise
)
6725 if (IS_ZEBRA_DEBUG_VXLAN
)
6726 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
6727 advertise
? "enabled" : "disabled", vni
,
6728 zvni
->advertise_subnet
? "enabled" : "disabled");
6731 zvni
->advertise_subnet
= advertise
;
6733 ifp
= zvni
->vxlan_if
;
6739 /* If down or not mapped to a bridge, we're done. */
6740 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6743 zl2_info
= zif
->l2info
.vxl
;
6746 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
6750 if (zvni
->advertise_subnet
)
6751 zvni_advertise_subnet(zvni
, vlan_if
, 1);
6753 zvni_advertise_subnet(zvni
, vlan_if
, 0);
6760 * Handle message from client to enable/disable advertisement of g/w macip
6763 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
6768 zebra_vni_t
*zvni
= NULL
;
6769 struct interface
*ifp
= NULL
;
6771 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6772 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6778 STREAM_GETC(s
, advertise
);
6779 STREAM_GETL(s
, vni
);
6782 if (IS_ZEBRA_DEBUG_VXLAN
)
6783 zlog_debug("EVPN gateway macip Adv %s, currently %s",
6784 advertise
? "enabled" : "disabled",
6785 advertise_gw_macip_enabled(NULL
)
6789 if (zvrf
->advertise_gw_macip
== advertise
)
6792 zvrf
->advertise_gw_macip
= advertise
;
6794 if (advertise_gw_macip_enabled(zvni
))
6795 hash_iterate(zvrf
->vni_table
,
6796 zvni_gw_macip_add_for_vni_hash
, NULL
);
6798 hash_iterate(zvrf
->vni_table
,
6799 zvni_gw_macip_del_for_vni_hash
, NULL
);
6802 struct zebra_if
*zif
= NULL
;
6803 struct zebra_l2info_vxlan zl2_info
;
6804 struct interface
*vlan_if
= NULL
;
6805 struct interface
*vrr_if
= NULL
;
6807 zvni
= zvni_lookup(vni
);
6811 if (IS_ZEBRA_DEBUG_VXLAN
)
6813 "EVPN gateway macip Adv %s on VNI %d , currently %s",
6814 advertise
? "enabled" : "disabled", vni
,
6815 advertise_gw_macip_enabled(zvni
) ? "enabled"
6818 if (zvni
->advertise_gw_macip
== advertise
)
6821 zvni
->advertise_gw_macip
= advertise
;
6823 ifp
= zvni
->vxlan_if
;
6829 /* If down or not mapped to a bridge, we're done. */
6830 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6833 zl2_info
= zif
->l2info
.vxl
;
6835 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
6836 zif
->brslave_info
.br_if
);
6840 if (advertise_gw_macip_enabled(zvni
)) {
6841 /* Add primary SVI MAC-IP */
6842 zvni_add_macip_for_intf(vlan_if
, zvni
);
6844 /* Add VRR MAC-IP - if any*/
6845 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6847 zvni_add_macip_for_intf(vrr_if
, zvni
);
6849 /* Del primary MAC-IP */
6850 zvni_del_macip_for_intf(vlan_if
, zvni
);
6852 /* Del VRR MAC-IP - if any*/
6853 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6855 zvni_del_macip_for_intf(vrr_if
, zvni
);
6865 * Handle message from client to learn (or stop learning) about VNIs and MACs.
6866 * When enabled, the VNI hash table will be built and MAC FDB table read;
6867 * when disabled, the entries should be deleted and remote VTEPs and MACs
6868 * uninstalled from the kernel.
6870 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
6872 struct stream
*s
= NULL
;
6874 struct zebra_ns
*zns
= NULL
;
6876 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6877 zlog_err("EVPN VNI Adv for non-default VRF %u", zvrf_id(zvrf
));
6882 STREAM_GETC(s
, advertise
);
6884 if (IS_ZEBRA_DEBUG_VXLAN
)
6885 zlog_debug("EVPN VNI Adv %s, currently %s",
6886 advertise
? "enabled" : "disabled",
6887 is_evpn_enabled() ? "enabled" : "disabled");
6889 if (zvrf
->advertise_all_vni
== advertise
)
6892 zvrf
->advertise_all_vni
= advertise
;
6893 if (is_evpn_enabled()) {
6894 /* Build VNI hash table and inform BGP. */
6895 zvni_build_hash_table();
6897 /* Add all SVI (L3 GW) MACs to BGP*/
6898 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
6901 /* Read the MAC FDB */
6902 macfdb_read(zvrf
->zns
);
6904 /* Read neighbors */
6905 neigh_read(zvrf
->zns
);
6907 /* Cleanup VTEPs for all VNIs - uninstall from
6908 * kernel and free entries.
6910 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6912 /* cleanup all l3vnis */
6913 zns
= zebra_ns_lookup(NS_DEFAULT
);
6917 hash_iterate(zns
->l3vni_table
, zl3vni_cleanup_all
, NULL
);
6925 * Allocate VNI hash table for this VRF and do other initialization.
6926 * NOTE: Currently supported only for default VRF.
6928 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
6932 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
6933 "Zebra VRF VNI Table");
6936 /* Cleanup VNI info, but don't free the table. */
6937 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
6941 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6944 /* Close all VNI handling */
6945 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
6949 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6950 hash_free(zvrf
->vni_table
);
6953 /* init the l3vni table */
6954 void zebra_vxlan_ns_init(struct zebra_ns
*zns
)
6956 zns
->l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
6957 "Zebra VRF L3 VNI table");
6960 /* free l3vni table */
6961 void zebra_vxlan_ns_disable(struct zebra_ns
*zns
)
6963 hash_free(zns
->l3vni_table
);
6966 /* get the l3vni svi ifindex */
6967 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
6969 zebra_l3vni_t
*zl3vni
= NULL
;
6971 zl3vni
= zl3vni_from_vrf(vrf_id
);
6972 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
6975 return zl3vni
->svi_if
->ifindex
;