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/debug.h"
41 #include "zebra/interface.h"
42 #include "zebra/rib.h"
44 #include "zebra/rt_netlink.h"
45 #include "zebra/zebra_errors.h"
46 #include "zebra/zebra_l2.h"
47 #include "zebra/zebra_memory.h"
48 #include "zebra/zebra_ns.h"
49 #include "zebra/zebra_vrf.h"
50 #include "zebra/zebra_vxlan.h"
51 #include "zebra/zebra_vxlan_private.h"
52 #include "zebra/zserv.h"
54 DEFINE_MTYPE_STATIC(ZEBRA
, HOST_PREFIX
, "host prefix");
55 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI
, "VNI hash");
56 DEFINE_MTYPE_STATIC(ZEBRA
, ZL3VNI
, "L3 VNI hash");
57 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI_VTEP
, "VNI remote VTEP");
58 DEFINE_MTYPE_STATIC(ZEBRA
, MAC
, "VNI MAC");
59 DEFINE_MTYPE_STATIC(ZEBRA
, NEIGH
, "VNI Neighbor");
63 /* static function declarations */
64 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
66 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
67 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
);
68 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
70 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
72 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
74 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
);
75 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
);
76 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
);
77 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
78 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[]);
80 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
81 struct ipaddr
*ip
, uint8_t flags
,
83 static unsigned int neigh_hash_keymake(void *p
);
84 static int neigh_cmp(const void *p1
, const void *p2
);
85 static void *zvni_neigh_alloc(void *p
);
86 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
88 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
89 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
90 struct in_addr
*r_vtep_ip
);
91 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
93 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
);
94 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
95 struct ethaddr
*macaddr
,
97 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
98 struct ethaddr
*macaddr
,
100 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
101 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
102 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
103 struct interface
*br_if
);
104 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
);
106 /* l3-vni next-hop neigh related APIs */
107 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
109 static void *zl3vni_nh_alloc(void *p
);
110 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
111 struct ipaddr
*vtep_ip
,
112 struct ethaddr
*rmac
);
113 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
114 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
115 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
117 /* l3-vni rmac related APIs */
118 static void zl3vni_print_rmac_hash(struct hash_backet
*, void *);
119 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
120 struct ethaddr
*rmac
);
121 static void *zl3vni_rmac_alloc(void *p
);
122 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
123 struct ethaddr
*rmac
);
124 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
125 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
126 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
128 /* l3-vni related APIs*/
129 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
);
130 static void *zl3vni_alloc(void *p
);
131 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
132 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
133 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t
);
134 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
);
135 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
);
136 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
137 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
139 static unsigned int mac_hash_keymake(void *p
);
140 static int mac_cmp(const void *p1
, const void *p2
);
141 static void *zvni_mac_alloc(void *p
);
142 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
143 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
144 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
145 struct in_addr
*r_vtep_ip
);
146 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
148 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
149 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
151 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
153 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
154 struct interface
*br_if
, vlanid_t vid
);
155 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
156 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
);
157 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
);
159 static unsigned int vni_hash_keymake(void *p
);
160 static int vni_hash_cmp(const void *p1
, const void *p2
);
161 static void *zvni_alloc(void *p
);
162 static zebra_vni_t
*zvni_lookup(vni_t vni
);
163 static zebra_vni_t
*zvni_add(vni_t vni
);
164 static int zvni_del(zebra_vni_t
*zvni
);
165 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
166 static int zvni_send_del_to_client(vni_t vni
);
167 static void zvni_build_hash_table();
168 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
169 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
170 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
171 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
172 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
173 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
174 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
175 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
176 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
177 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
178 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
179 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
181 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
182 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
183 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
186 /* Private functions */
187 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
188 const struct host_rb_entry
*hle2
)
190 if (hle1
->p
.family
< hle2
->p
.family
)
193 if (hle1
->p
.family
> hle2
->p
.family
)
196 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
199 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
202 if (hle1
->p
.family
== AF_INET
) {
203 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
206 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
211 zlog_warn("%s: Unexpected family type: %d", __PRETTY_FUNCTION__
,
216 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
218 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
220 struct host_rb_entry
*hle
;
223 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
230 * Return number of valid MACs in a VNI's MAC hash table - all
231 * remote MACs and non-internal (auto) local MACs count.
233 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
236 uint32_t num_macs
= 0;
238 struct hash_backet
*hb
;
241 hash
= zvni
->mac_table
;
244 for (i
= 0; i
< hash
->size
; i
++) {
245 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
246 mac
= (zebra_mac_t
*)hb
->data
;
247 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
248 || CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
249 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
257 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
259 struct zebra_vrf
*zvrf
;
261 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
262 if (zvrf
&& zvrf
->advertise_gw_macip
)
265 if (zvni
&& zvni
->advertise_gw_macip
)
272 * Helper function to determine maximum width of neighbor IP address for
273 * display - just because we're dealing with IPv6 addresses that can
276 static void zvni_find_neigh_addr_width(struct hash_backet
*backet
, void *ctxt
)
279 char buf
[INET6_ADDRSTRLEN
];
280 struct neigh_walk_ctx
*wctx
= ctxt
;
283 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
;
359 json_row
= json_object_new_object();
361 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
362 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
363 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)
364 && !(wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)) {
365 if (json_vni
== NULL
) {
366 vty_out(vty
, "%*s %-6s %-17s\n", -wctx
->addr_width
,
367 buf2
, "local", buf1
);
369 json_object_string_add(json_row
, "type", "local");
370 json_object_string_add(json_row
, "mac", buf1
);
374 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) {
375 if (IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
)) {
376 if (json_vni
== NULL
) {
377 if (wctx
->count
== 0)
379 "%*s %-6s %-17s %-21s\n",
382 "MAC", "Remote VTEP");
383 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
384 -wctx
->addr_width
, buf2
,
386 inet_ntoa(n
->r_vtep_ip
));
388 json_object_string_add(json_row
, "type",
390 json_object_string_add(json_row
, "mac",
392 json_object_string_add(
393 json_row
, "remoteVtep",
394 inet_ntoa(n
->r_vtep_ip
));
399 if (json_vni
== NULL
) {
400 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
401 -wctx
->addr_width
, buf2
, "remote", buf1
,
402 inet_ntoa(n
->r_vtep_ip
));
404 json_object_string_add(json_row
, "type",
406 json_object_string_add(json_row
, "mac", buf1
);
407 json_object_string_add(json_row
, "remoteVtep",
408 inet_ntoa(n
->r_vtep_ip
));
415 json_object_object_add(json_vni
, buf2
, json_row
);
419 * Print neighbors for all VNI.
421 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
425 json_object
*json
= NULL
, *json_vni
= NULL
;
428 struct neigh_walk_ctx wctx
;
429 char vni_str
[VNI_STR_LEN
];
431 vty
= (struct vty
*)args
[0];
432 json
= (json_object
*)args
[1];
434 zvni
= (zebra_vni_t
*)backet
->data
;
436 num_neigh
= hashcount(zvni
->neigh_table
);
439 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
440 zvni
->vni
, num_neigh
);
442 json_vni
= json_object_new_object();
443 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
444 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
448 json_object_object_add(json
, vni_str
, json_vni
);
452 /* Since we have IPv6 addresses to deal with which can vary widely in
453 * size, we try to be a bit more elegant in display by first computing
456 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
459 wctx
.addr_width
= 15;
460 wctx
.json
= json_vni
;
461 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
464 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
465 "Type", "MAC", "Remote VTEP");
467 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
470 json_object_object_add(json
, vni_str
, json_vni
);
473 /* print a specific next hop for an l3vni */
474 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
477 char buf1
[ETHER_ADDR_STRLEN
];
478 char buf2
[INET6_ADDRSTRLEN
];
479 json_object
*json_hosts
= NULL
;
480 struct host_rb_entry
*hle
;
483 vty_out(vty
, "Ip: %s\n",
484 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
485 vty_out(vty
, " RMAC: %s\n",
486 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
487 vty_out(vty
, " Refcount: %d\n",
488 rb_host_count(&n
->host_rb
));
489 vty_out(vty
, " Prefixes:\n");
490 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
491 vty_out(vty
, " %s\n",
492 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
494 json_hosts
= json_object_new_array();
495 json_object_string_add(
496 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
497 json_object_string_add(
499 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
500 json_object_int_add(json
, "refCount",
501 rb_host_count(&n
->host_rb
));
502 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
503 json_object_array_add(json_hosts
,
504 json_object_new_string(prefix2str(
505 &hle
->p
, buf2
, sizeof(buf2
))));
506 json_object_object_add(json
, "prefixList", json_hosts
);
510 /* Print a specific RMAC entry */
511 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
514 char buf1
[ETHER_ADDR_STRLEN
];
515 char buf2
[PREFIX_STRLEN
];
516 json_object
*json_hosts
= NULL
;
517 struct host_rb_entry
*hle
;
520 vty_out(vty
, "MAC: %s\n",
521 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
522 vty_out(vty
, " Remote VTEP: %s\n",
523 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
524 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
525 vty_out(vty
, " Prefixes:\n");
526 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
527 vty_out(vty
, " %s\n",
528 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
530 json_hosts
= json_object_new_array();
531 json_object_string_add(
533 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
534 json_object_string_add(json
, "vtepIp",
535 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
536 json_object_int_add(json
, "refCount",
537 rb_host_count(&zrmac
->host_rb
));
538 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
539 json_object_array_add(
541 json_object_new_string(prefix2str(
542 &hle
->p
, buf2
, sizeof(buf2
))));
543 json_object_object_add(json
, "prefixList", json_hosts
);
548 * Print a specific MAC entry.
550 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
)
553 zebra_neigh_t
*n
= NULL
;
554 struct listnode
*node
= NULL
;
556 char buf2
[INET6_ADDRSTRLEN
];
558 vty
= (struct vty
*)ctxt
;
559 vty_out(vty
, "MAC: %s",
560 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
)));
561 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
562 struct zebra_ns
*zns
;
563 struct interface
*ifp
;
566 ifindex
= mac
->fwd_info
.local
.ifindex
;
567 zns
= zebra_ns_lookup(NS_DEFAULT
);
568 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
569 if (!ifp
) // unexpected
571 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
572 if (mac
->fwd_info
.local
.vid
)
573 vty_out(vty
, " VLAN: %u", mac
->fwd_info
.local
.vid
);
574 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
575 vty_out(vty
, " Remote VTEP: %s",
576 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
577 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
578 vty_out(vty
, " Auto Mac ");
581 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
582 vty_out(vty
, " Sticky Mac ");
584 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
585 vty_out(vty
, " Default-gateway Mac ");
587 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
588 vty_out(vty
, " Remote-gateway Mac ");
591 /* print all the associated neigh */
592 vty_out(vty
, " Neighbors:\n");
593 if (!listcount(mac
->neigh_list
))
594 vty_out(vty
, " No Neighbors\n");
596 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
597 vty_out(vty
, " %s %s\n",
598 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
599 CHECK_FLAG(n
->flags
, ZEBRA_MAC_LOCAL
)
600 ? (IS_ZEBRA_NEIGH_ACTIVE(n
)
611 * Print MAC hash entry - called for display of all MACs.
613 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
616 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
619 struct mac_walk_ctx
*wctx
= ctxt
;
622 json_mac_hdr
= wctx
->json
;
623 mac
= (zebra_mac_t
*)backet
->data
;
625 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
628 json_mac
= json_object_new_object();
630 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
631 && !(wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)) {
632 struct zebra_ns
*zns
;
634 struct interface
*ifp
;
637 zns
= zebra_ns_lookup(NS_DEFAULT
);
638 ifindex
= mac
->fwd_info
.local
.ifindex
;
639 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
640 if (!ifp
) // unexpected
642 vid
= mac
->fwd_info
.local
.vid
;
643 if (json_mac_hdr
== NULL
)
644 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
647 json_object_string_add(json_mac
, "type", "local");
648 json_object_string_add(json_mac
, "intf", ifp
->name
);
651 if (json_mac_hdr
== NULL
)
652 vty_out(vty
, " %-5u", vid
);
654 json_object_int_add(json_mac
, "vlan", vid
);
656 if (json_mac_hdr
== NULL
)
659 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
661 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
662 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) {
663 if (IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
665 if (wctx
->count
== 0) {
666 if (json_mac_hdr
== NULL
) {
667 vty_out(vty
, "\nVNI %u\n\n",
670 "%-17s %-6s %-21s %-5s\n",
676 if (json_mac_hdr
== NULL
)
677 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
679 inet_ntoa(mac
->fwd_info
682 json_object_string_add(json_mac
, "type",
684 json_object_string_add(
685 json_mac
, "remoteVtep",
686 inet_ntoa(mac
->fwd_info
688 json_object_object_add(json_mac_hdr
,
694 if (json_mac_hdr
== NULL
)
695 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
697 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
699 json_object_string_add(json_mac
, "type",
701 json_object_string_add(
702 json_mac
, "remoteVtep",
703 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
704 json_object_object_add(json_mac_hdr
, buf1
,
713 * Print MACs for all VNI.
715 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
718 json_object
*json
= NULL
, *json_vni
= NULL
;
719 json_object
*json_mac
= NULL
;
722 struct mac_walk_ctx
*wctx
= ctxt
;
723 char vni_str
[VNI_STR_LEN
];
725 vty
= (struct vty
*)wctx
->vty
;
726 json
= (struct json_object
*)wctx
->json
;
728 zvni
= (zebra_vni_t
*)backet
->data
;
731 /*We are iterating over a new VNI, set the count to 0*/
734 num_macs
= num_valid_macs(zvni
);
739 json_vni
= json_object_new_object();
740 json_mac
= json_object_new_object();
741 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
744 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
746 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
747 zvni
->vni
, num_macs
);
748 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
749 "Intf/Remote VTEP", "VLAN");
751 json_object_int_add(json_vni
, "numMacs", num_macs
);
753 /* assign per-vni to wctx->json object to fill macs
754 * under the vni. Re-assign primary json object to fill
755 * next vni information.
757 wctx
->json
= json_mac
;
758 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
762 json_object_object_add(json_vni
, "macs", json_mac
);
763 json_object_object_add(json
, vni_str
, json_vni
);
767 static void zl3vni_print_nh_hash(struct hash_backet
*backet
, void *ctx
)
769 struct nh_walk_ctx
*wctx
= NULL
;
770 struct vty
*vty
= NULL
;
771 struct json_object
*json_vni
= NULL
;
772 struct json_object
*json_nh
= NULL
;
773 zebra_neigh_t
*n
= NULL
;
774 char buf1
[ETHER_ADDR_STRLEN
];
775 char buf2
[INET6_ADDRSTRLEN
];
777 wctx
= (struct nh_walk_ctx
*)ctx
;
779 json_vni
= wctx
->json
;
781 json_nh
= json_object_new_object();
782 n
= (zebra_neigh_t
*)backet
->data
;
785 vty_out(vty
, "%-15s %-17s\n",
786 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
787 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
789 json_object_string_add(json_nh
, "nexthopIp",
790 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
791 json_object_string_add(
792 json_nh
, "routerMac",
793 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
794 json_object_object_add(json_vni
,
795 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
800 static void zl3vni_print_nh_hash_all_vni(struct hash_backet
*backet
,
803 struct vty
*vty
= NULL
;
804 json_object
*json
= NULL
;
805 json_object
*json_vni
= NULL
;
806 zebra_l3vni_t
*zl3vni
= NULL
;
808 struct nh_walk_ctx wctx
;
809 char vni_str
[VNI_STR_LEN
];
811 vty
= (struct vty
*)args
[0];
812 json
= (struct json_object
*)args
[1];
814 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
816 num_nh
= hashcount(zl3vni
->nh_table
);
821 json_vni
= json_object_new_object();
822 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
826 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
827 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
829 json_object_int_add(json_vni
, "numNextHops", num_nh
);
831 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
833 wctx
.json
= json_vni
;
834 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
836 json_object_object_add(json
, vni_str
, json_vni
);
839 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet
*backet
,
842 struct vty
*vty
= NULL
;
843 json_object
*json
= NULL
;
844 json_object
*json_vni
= NULL
;
845 zebra_l3vni_t
*zl3vni
= NULL
;
847 struct rmac_walk_ctx wctx
;
848 char vni_str
[VNI_STR_LEN
];
850 vty
= (struct vty
*)args
[0];
851 json
= (struct json_object
*)args
[1];
853 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
855 num_rmacs
= hashcount(zl3vni
->rmac_table
);
860 json_vni
= json_object_new_object();
861 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
865 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
866 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
868 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
870 /* assign per-vni to wctx->json object to fill macs
871 * under the vni. Re-assign primary json object to fill
872 * next vni information.
874 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
876 wctx
.json
= json_vni
;
877 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
879 json_object_object_add(json
, vni_str
, json_vni
);
882 static void zl3vni_print_rmac_hash(struct hash_backet
*backet
, void *ctx
)
884 zebra_mac_t
*zrmac
= NULL
;
885 struct rmac_walk_ctx
*wctx
= NULL
;
886 struct vty
*vty
= NULL
;
887 struct json_object
*json
= NULL
;
888 struct json_object
*json_rmac
= NULL
;
889 char buf
[ETHER_ADDR_STRLEN
];
891 wctx
= (struct rmac_walk_ctx
*)ctx
;
895 json_rmac
= json_object_new_object();
896 zrmac
= (zebra_mac_t
*)backet
->data
;
899 vty_out(vty
, "%-17s %-21s\n",
900 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
901 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
903 json_object_string_add(
904 json_rmac
, "routerMac",
905 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
906 json_object_string_add(json_rmac
, "vtepIp",
907 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
908 json_object_object_add(
909 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
914 /* print a specific L3 VNI entry */
915 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
917 char buf
[ETHER_ADDR_STRLEN
];
918 struct vty
*vty
= NULL
;
919 json_object
*json
= NULL
;
920 zebra_vni_t
*zvni
= NULL
;
921 json_object
*json_vni_list
= NULL
;
922 struct listnode
*node
= NULL
, *nnode
= NULL
;
928 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
929 vty_out(vty
, " Type: %s\n", "L3");
930 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
931 vty_out(vty
, " Local Vtep Ip: %s\n",
932 inet_ntoa(zl3vni
->local_vtep_ip
));
933 vty_out(vty
, " Vxlan-Intf: %s\n",
934 zl3vni_vxlan_if_name(zl3vni
));
935 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
936 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
937 vty_out(vty
, " VNI Filter: %s\n",
938 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
939 ? "prefix-routes-only"
941 vty_out(vty
, " Router MAC: %s\n",
942 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
943 vty_out(vty
, " L2 VNIs: ");
944 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
945 vty_out(vty
, "%u ", zvni
->vni
);
948 json_vni_list
= json_object_new_array();
949 json_object_int_add(json
, "vni", zl3vni
->vni
);
950 json_object_string_add(json
, "type", "L3");
951 json_object_string_add(json
, "localVtepIp",
952 inet_ntoa(zl3vni
->local_vtep_ip
));
953 json_object_string_add(json
, "vxlanIntf",
954 zl3vni_vxlan_if_name(zl3vni
));
955 json_object_string_add(json
, "sviIntf",
956 zl3vni_svi_if_name(zl3vni
));
957 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
958 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
959 json_object_string_add(
961 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
962 json_object_string_add(
964 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
965 ? "prefix-routes-only"
967 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
968 json_object_array_add(json_vni_list
,
969 json_object_new_int(zvni
->vni
));
971 json_object_object_add(json
, "l2Vnis", json_vni_list
);
976 * Print a specific VNI entry.
978 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
984 json_object
*json
= NULL
;
985 json_object
*json_vtep_list
= NULL
;
986 json_object
*json_ip_str
= NULL
;
992 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
993 vty_out(vty
, " Type: %s\n", "L2");
994 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
996 json_object_int_add(json
, "vni", zvni
->vni
);
997 json_object_string_add(json
, "type", "L2");
998 json_object_string_add(json
, "vrf",
999 vrf_id_to_name(zvni
->vrf_id
));
1002 if (!zvni
->vxlan_if
) { // unexpected
1004 vty_out(vty
, " VxLAN interface: unknown\n");
1007 num_macs
= num_valid_macs(zvni
);
1008 num_neigh
= hashcount(zvni
->neigh_table
);
1010 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1011 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1012 vty_out(vty
, " Local VTEP IP: %s\n",
1013 inet_ntoa(zvni
->local_vtep_ip
));
1015 json_object_string_add(json
, "vxlanInterface",
1016 zvni
->vxlan_if
->name
);
1017 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1018 json_object_string_add(json
, "vtepIp",
1019 inet_ntoa(zvni
->local_vtep_ip
));
1020 json_object_string_add(json
, "advertiseGatewayMacip",
1021 zvni
->advertise_gw_macip
? "Yes" : "No");
1022 json_object_int_add(json
, "numMacs", num_macs
);
1023 json_object_int_add(json
, "numArpNd", num_neigh
);
1027 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1030 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1032 json_vtep_list
= json_object_new_array();
1033 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1035 vty_out(vty
, " %s\n",
1036 inet_ntoa(zvtep
->vtep_ip
));
1038 json_ip_str
= json_object_new_string(
1039 inet_ntoa(zvtep
->vtep_ip
));
1040 json_object_array_add(json_vtep_list
,
1045 json_object_object_add(json
, "numRemoteVteps",
1050 " Number of MACs (local and remote) known for this VNI: %u\n",
1053 " Number of ARPs (IPv4 and IPv6, local and remote) "
1054 "known for this VNI: %u\n",
1056 vty_out(vty
, " Advertise-gw-macip: %s\n",
1057 zvni
->advertise_gw_macip
? "Yes" : "No");
1061 /* print a L3 VNI hash entry */
1062 static void zl3vni_print_hash(struct hash_backet
*backet
, void *ctx
[])
1064 struct vty
*vty
= NULL
;
1065 json_object
*json
= NULL
;
1066 json_object
*json_vni
= NULL
;
1067 zebra_l3vni_t
*zl3vni
= NULL
;
1069 vty
= (struct vty
*)ctx
[0];
1070 json
= (json_object
*)ctx
[1];
1072 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1075 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1076 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1077 hashcount(zl3vni
->rmac_table
),
1078 hashcount(zl3vni
->nh_table
), "n/a",
1079 zl3vni_vrf_name(zl3vni
));
1081 char vni_str
[VNI_STR_LEN
];
1083 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1084 json_vni
= json_object_new_object();
1085 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1086 json_object_string_add(json_vni
, "vxlanIf",
1087 zl3vni_vxlan_if_name(zl3vni
));
1088 json_object_int_add(json_vni
, "numMacs",
1089 hashcount(zl3vni
->rmac_table
));
1090 json_object_int_add(json_vni
, "numArpNd",
1091 hashcount(zl3vni
->nh_table
));
1092 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1093 json_object_string_add(json_vni
, "type", "L3");
1094 json_object_string_add(json_vni
, "tenantVrf",
1095 zl3vni_vrf_name(zl3vni
));
1096 json_object_object_add(json
, vni_str
, json_vni
);
1101 * Print a VNI hash entry - called for display of all VNIs.
1103 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1107 zebra_vtep_t
*zvtep
;
1108 uint32_t num_vteps
= 0;
1109 uint32_t num_macs
= 0;
1110 uint32_t num_neigh
= 0;
1111 json_object
*json
= NULL
;
1112 json_object
*json_vni
= NULL
;
1113 json_object
*json_ip_str
= NULL
;
1114 json_object
*json_vtep_list
= NULL
;
1119 zvni
= (zebra_vni_t
*)backet
->data
;
1121 zvtep
= zvni
->vteps
;
1124 zvtep
= zvtep
->next
;
1127 num_macs
= num_valid_macs(zvni
);
1128 num_neigh
= hashcount(zvni
->neigh_table
);
1130 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1132 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1133 num_macs
, num_neigh
, num_vteps
,
1134 vrf_id_to_name(zvni
->vrf_id
));
1136 char vni_str
[VNI_STR_LEN
];
1137 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1138 json_vni
= json_object_new_object();
1139 json_object_int_add(json_vni
, "vni", zvni
->vni
);
1140 json_object_string_add(json_vni
, "type", "L2");
1141 json_object_string_add(json_vni
, "vxlanIf",
1142 zvni
->vxlan_if
? zvni
->vxlan_if
->name
1144 json_object_int_add(json_vni
, "numMacs", num_macs
);
1145 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1146 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
1147 json_object_string_add(json_vni
, "tenantVrf",
1148 vrf_id_to_name(zvni
->vrf_id
));
1150 json_vtep_list
= json_object_new_array();
1151 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1152 json_ip_str
= json_object_new_string(
1153 inet_ntoa(zvtep
->vtep_ip
));
1154 json_object_array_add(json_vtep_list
,
1157 json_object_object_add(json_vni
, "remoteVteps",
1160 json_object_object_add(json
, vni_str
, json_vni
);
1165 * Inform BGP about local MACIP.
1167 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
1168 struct ipaddr
*ip
, uint8_t flags
,
1171 char buf
[ETHER_ADDR_STRLEN
];
1172 char buf2
[INET6_ADDRSTRLEN
];
1174 struct zserv
*client
= NULL
;
1175 struct stream
*s
= NULL
;
1177 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
1178 /* BGP may not be running. */
1182 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
1184 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
1185 stream_putl(s
, vni
);
1186 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
1189 if (IS_IPADDR_V4(ip
))
1190 ipa_len
= IPV4_MAX_BYTELEN
;
1191 else if (IS_IPADDR_V6(ip
))
1192 ipa_len
= IPV6_MAX_BYTELEN
;
1194 stream_putl(s
, ipa_len
); /* IP address length */
1196 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
1198 stream_putl(s
, 0); /* Just MAC. */
1200 stream_putc(s
, flags
); /* sticky mac/gateway mac */
1203 /* Write packet size. */
1204 stream_putw_at(s
, 0, stream_get_endp(s
));
1206 if (IS_ZEBRA_DEBUG_VXLAN
)
1208 "Send MACIP %s flags 0x%x MAC %s IP %s L2-VNI %u to %s",
1209 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
1210 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1211 ipaddr2str(ip
, buf2
, sizeof(buf2
)), vni
,
1212 zebra_route_string(client
->proto
));
1214 if (cmd
== ZEBRA_MACIP_ADD
)
1215 client
->macipadd_cnt
++;
1217 client
->macipdel_cnt
++;
1219 return zserv_send_message(client
, s
);
1223 * Make hash key for neighbors.
1225 static unsigned int neigh_hash_keymake(void *p
)
1227 zebra_neigh_t
*n
= p
;
1228 struct ipaddr
*ip
= &n
->ip
;
1230 if (IS_IPADDR_V4(ip
))
1231 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
1233 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
1234 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
1238 * Compare two neighbor hash structures.
1240 static int neigh_cmp(const void *p1
, const void *p2
)
1242 const zebra_neigh_t
*n1
= p1
;
1243 const zebra_neigh_t
*n2
= p2
;
1245 if (n1
== NULL
&& n2
== NULL
)
1248 if (n1
== NULL
|| n2
== NULL
)
1251 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
1255 * Callback to allocate neighbor hash entry.
1257 static void *zvni_neigh_alloc(void *p
)
1259 const zebra_neigh_t
*tmp_n
= p
;
1262 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
1269 * Add neighbor entry.
1271 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
1272 struct ethaddr
*mac
)
1274 zebra_neigh_t tmp_n
;
1275 zebra_neigh_t
*n
= NULL
;
1276 zebra_mac_t
*zmac
= NULL
;
1278 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
1279 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1280 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
1283 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1284 n
->state
= ZEBRA_NEIGH_INACTIVE
;
1286 /* Associate the neigh to mac */
1287 zmac
= zvni_mac_lookup(zvni
, mac
);
1289 listnode_add_sort(zmac
->neigh_list
, n
);
1295 * Delete neighbor entry.
1297 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1299 zebra_neigh_t
*tmp_n
;
1300 zebra_mac_t
*zmac
= NULL
;
1302 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
1304 listnode_delete(zmac
->neigh_list
, n
);
1306 /* Free the VNI hash entry and allocated memory. */
1307 tmp_n
= hash_release(zvni
->neigh_table
, n
);
1309 XFREE(MTYPE_NEIGH
, tmp_n
);
1315 * Free neighbor hash entry (callback)
1317 static void zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
1319 struct neigh_walk_ctx
*wctx
= arg
;
1320 zebra_neigh_t
*n
= backet
->data
;
1322 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1323 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
1324 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
1325 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
1326 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
1327 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
1328 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1329 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
1332 if (wctx
->uninstall
)
1333 zvni_neigh_uninstall(wctx
->zvni
, n
);
1335 zvni_neigh_del(wctx
->zvni
, n
);
1342 * Delete all neighbor entries from specific VTEP for a particular VNI.
1344 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
1345 struct in_addr
*r_vtep_ip
)
1347 struct neigh_walk_ctx wctx
;
1349 if (!zvni
->neigh_table
)
1352 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1354 wctx
.uninstall
= uninstall
;
1355 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
1356 wctx
.r_vtep_ip
= *r_vtep_ip
;
1358 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1362 * Delete all neighbor entries for this VNI.
1364 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
1367 struct neigh_walk_ctx wctx
;
1369 if (!zvni
->neigh_table
)
1372 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1374 wctx
.uninstall
= uninstall
;
1375 wctx
.upd_client
= upd_client
;
1378 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1382 * Look up neighbor hash entry.
1384 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
1389 memset(&tmp
, 0, sizeof(tmp
));
1390 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
1391 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
1396 /* Process all neigh associated to a mac upon local mac add event */
1397 static void zvni_process_neigh_on_local_mac_add(zebra_vni_t
*zvni
,
1400 zebra_neigh_t
*n
= NULL
;
1401 struct listnode
*node
= NULL
;
1402 char buf
[ETHER_ADDR_STRLEN
];
1403 char buf2
[INET6_ADDRSTRLEN
];
1405 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1406 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1407 /* MAC is learnt locally, program all inactive neigh
1408 * pointing to this mac */
1409 if (IS_ZEBRA_NEIGH_INACTIVE(n
)) {
1410 if (IS_ZEBRA_DEBUG_VXLAN
)
1412 "neigh %s (MAC %s) on L2-VNI %u is now ACTIVE",
1413 ipaddr2str(&n
->ip
, buf2
,
1415 prefix_mac2str(&n
->emac
, buf
,
1419 ZEBRA_NEIGH_SET_ACTIVE(n
);
1420 zvni_neigh_send_add_to_client(
1421 zvni
->vni
, &n
->ip
, &n
->emac
, n
->flags
);
1423 if (IS_ZEBRA_DEBUG_VXLAN
)
1425 "neigh %s (MAC %s) on VNI %u should NOT be ACTIVE",
1426 ipaddr2str(&n
->ip
, buf2
,
1428 prefix_mac2str(&n
->emac
, buf
,
1432 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1433 /* TODO: assume the neigh has moved too ?? */
1438 /* Process all neigh associated to a mac upon local mac del event */
1439 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
1442 zebra_neigh_t
*n
= NULL
;
1443 struct listnode
*node
= NULL
;
1444 char buf
[ETHER_ADDR_STRLEN
];
1445 char buf2
[INET6_ADDRSTRLEN
];
1447 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1448 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1449 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1450 if (IS_ZEBRA_DEBUG_VXLAN
)
1452 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1453 ipaddr2str(&n
->ip
, buf2
,
1455 prefix_mac2str(&n
->emac
, buf
,
1459 ZEBRA_NEIGH_SET_INACTIVE(n
);
1460 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1463 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
1464 && IS_ZEBRA_DEBUG_VXLAN
) {
1466 "local MAC %s getting deleted on VNI %u has remote neigh %s",
1467 prefix_mac2str(&n
->emac
, buf
, sizeof(buf
)),
1469 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1474 /* process all neigh associated to a mac entry upon remote mac add */
1475 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
1478 zebra_neigh_t
*n
= NULL
;
1479 struct listnode
*node
= NULL
;
1480 char buf
[ETHER_ADDR_STRLEN
];
1481 char buf2
[INET6_ADDRSTRLEN
];
1483 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1484 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1485 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1486 if (IS_ZEBRA_DEBUG_VXLAN
)
1488 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1489 ipaddr2str(&n
->ip
, buf2
,
1491 prefix_mac2str(&n
->emac
, buf
,
1495 ZEBRA_NEIGH_SET_INACTIVE(n
);
1496 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1503 /* process all neigh associated to mac entry upon remote mac del */
1504 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
1507 zebra_neigh_t
*n
= NULL
;
1508 struct listnode
*node
= NULL
;
1509 char buf
[ETHER_ADDR_STRLEN
];
1510 char buf2
[INET6_ADDRSTRLEN
];
1512 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1513 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)
1514 && IS_ZEBRA_DEBUG_VXLAN
) {
1516 "remote MAC %s getting deleted on VNI %u has local neigh %s",
1517 prefix_mac2str(&n
->emac
, buf
, sizeof(buf
)),
1519 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1525 * Inform BGP about local neighbor addition.
1527 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
1528 struct ethaddr
*macaddr
,
1529 uint8_t neigh_flags
)
1533 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
1534 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
1535 /* Set router flag (R-bit) based on local neigh entry add */
1536 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
1537 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
1539 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1544 * Inform BGP about local neighbor deletion.
1546 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
1547 struct ethaddr
*macaddr
, uint8_t flags
)
1549 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1554 * Install remote neighbor into the kernel.
1556 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1558 struct zebra_if
*zif
;
1559 struct zebra_l2info_vxlan
*vxl
;
1560 struct interface
*vlan_if
;
1564 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1567 zif
= zvni
->vxlan_if
->info
;
1570 vxl
= &zif
->l2info
.vxl
;
1572 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1576 flags
= NTF_EXT_LEARNED
;
1577 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
1578 flags
|= NTF_ROUTER
;
1579 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
1585 * Uninstall remote neighbor from the kernel.
1587 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1589 struct zebra_if
*zif
;
1590 struct zebra_l2info_vxlan
*vxl
;
1591 struct interface
*vlan_if
;
1593 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1596 if (!zvni
->vxlan_if
) {
1597 zlog_warn("VNI %u hash %p couldn't be uninstalled - no intf",
1602 zif
= zvni
->vxlan_if
->info
;
1605 vxl
= &zif
->l2info
.vxl
;
1606 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1610 return kernel_del_neigh(vlan_if
, &n
->ip
);
1614 * Install neighbor hash entry - called upon access VLAN change.
1616 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
1619 struct neigh_walk_ctx
*wctx
= ctxt
;
1621 n
= (zebra_neigh_t
*)backet
->data
;
1623 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
1624 zvni_neigh_install(wctx
->zvni
, n
);
1627 /* Get the VRR interface for SVI if any */
1628 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
1630 struct zebra_vrf
*zvrf
= NULL
;
1631 struct interface
*tmp_if
= NULL
;
1632 struct zebra_if
*zif
= NULL
;
1634 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1637 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
1642 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
1645 if (zif
->link
== ifp
)
1652 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1654 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1655 struct connected
*c
= NULL
;
1656 struct ethaddr macaddr
;
1658 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1660 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1663 memset(&ip
, 0, sizeof(struct ipaddr
));
1664 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1667 if (c
->address
->family
== AF_INET
) {
1668 ip
.ipa_type
= IPADDR_V4
;
1669 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1670 sizeof(struct in_addr
));
1671 } else if (c
->address
->family
== AF_INET6
) {
1672 ip
.ipa_type
= IPADDR_V6
;
1673 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1674 sizeof(struct in6_addr
));
1679 zvni_gw_macip_del(ifp
, zvni
, &ip
);
1685 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1687 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1688 struct connected
*c
= NULL
;
1689 struct ethaddr macaddr
;
1691 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1693 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1696 memset(&ip
, 0, sizeof(struct ipaddr
));
1697 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1700 if (c
->address
->family
== AF_INET
) {
1701 ip
.ipa_type
= IPADDR_V4
;
1702 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1703 sizeof(struct in_addr
));
1704 } else if (c
->address
->family
== AF_INET6
) {
1705 ip
.ipa_type
= IPADDR_V6
;
1706 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1707 sizeof(struct in6_addr
));
1712 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
1718 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
1721 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1722 struct connected
*c
= NULL
;
1723 struct ethaddr macaddr
;
1725 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1727 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1730 memcpy(&p
, c
->address
, sizeof(struct prefix
));
1732 /* skip link local address */
1733 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
1738 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1739 ZEBRA_IP_PREFIX_ROUTE_ADD
);
1741 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1742 ZEBRA_IP_PREFIX_ROUTE_DEL
);
1748 * zvni_gw_macip_add_to_client
1750 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
1751 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
1753 char buf
[ETHER_ADDR_STRLEN
];
1754 char buf2
[INET6_ADDRSTRLEN
];
1755 zebra_neigh_t
*n
= NULL
;
1756 zebra_mac_t
*mac
= NULL
;
1757 struct zebra_if
*zif
= NULL
;
1758 struct zebra_l2info_vxlan
*vxl
= NULL
;
1760 zif
= zvni
->vxlan_if
->info
;
1764 vxl
= &zif
->l2info
.vxl
;
1766 mac
= zvni_mac_lookup(zvni
, macaddr
);
1768 mac
= zvni_mac_add(zvni
, macaddr
);
1770 flog_err(ZEBRA_ERR_MAC_ADD_FAILED
,
1771 "Failed to add MAC %s intf %s(%u) VID %u",
1772 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1773 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
1778 /* Set "local" forwarding info. */
1779 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
1780 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
1781 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
1782 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
1783 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
1784 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
1786 n
= zvni_neigh_lookup(zvni
, ip
);
1788 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
1791 ZEBRA_ERR_MAC_ADD_FAILED
,
1792 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1793 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
1794 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1795 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
1800 /* Set "local" forwarding info. */
1801 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
1802 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
1803 /* Set Router flag (R-bit) */
1804 if (ip
->ipa_type
== IPADDR_V6
)
1805 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
1806 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
1807 n
->ifindex
= ifp
->ifindex
;
1809 /* Only advertise in BGP if the knob is enabled */
1810 if (!advertise_gw_macip_enabled(zvni
))
1813 if (IS_ZEBRA_DEBUG_VXLAN
)
1815 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
1816 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1817 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1818 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
1820 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, n
->flags
);
1826 * zvni_gw_macip_del_from_client
1828 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
1831 char buf1
[ETHER_ADDR_STRLEN
];
1832 char buf2
[INET6_ADDRSTRLEN
];
1833 zebra_neigh_t
*n
= NULL
;
1834 zebra_mac_t
*mac
= NULL
;
1836 /* If the neigh entry is not present nothing to do*/
1837 n
= zvni_neigh_lookup(zvni
, ip
);
1841 /* mac entry should be present */
1842 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
1844 zlog_warn("MAC %s doesnt exists for neigh %s on VNI %u",
1845 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
1846 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1850 /* If the entry is not local nothing to do*/
1851 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
1854 /* only need to delete the entry from bgp if we sent it before */
1855 if (IS_ZEBRA_DEBUG_VXLAN
)
1857 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
1858 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1859 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
1860 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1862 /* Remove neighbor from BGP. */
1863 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
1864 ZEBRA_MACIP_TYPE_GW
);
1866 /* Delete this neighbor entry. */
1867 zvni_neigh_del(zvni
, n
);
1869 /* see if the mac needs to be deleted as well*/
1871 zvni_deref_ip2mac(zvni
, mac
, 0);
1876 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
1879 zebra_vni_t
*zvni
= NULL
;
1880 struct zebra_if
*zif
= NULL
;
1881 struct zebra_l2info_vxlan zl2_info
;
1882 struct interface
*vlan_if
= NULL
;
1883 struct interface
*vrr_if
= NULL
;
1884 struct interface
*ifp
;
1886 /* Add primary SVI MAC*/
1887 zvni
= (zebra_vni_t
*)backet
->data
;
1889 ifp
= zvni
->vxlan_if
;
1894 /* If down or not mapped to a bridge, we're done. */
1895 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1898 zl2_info
= zif
->l2info
.vxl
;
1901 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1905 /* Del primary MAC-IP */
1906 zvni_del_macip_for_intf(vlan_if
, zvni
);
1908 /* Del VRR MAC-IP - if any*/
1909 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1911 zvni_del_macip_for_intf(vrr_if
, zvni
);
1916 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
1919 zebra_vni_t
*zvni
= NULL
;
1920 struct zebra_if
*zif
= NULL
;
1921 struct zebra_l2info_vxlan zl2_info
;
1922 struct interface
*vlan_if
= NULL
;
1923 struct interface
*vrr_if
= NULL
;
1924 struct interface
*ifp
= NULL
;
1926 zvni
= (zebra_vni_t
*)backet
->data
;
1928 ifp
= zvni
->vxlan_if
;
1933 /* If down or not mapped to a bridge, we're done. */
1934 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1936 zl2_info
= zif
->l2info
.vxl
;
1939 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1943 /* Add primary SVI MAC-IP */
1944 zvni_add_macip_for_intf(vlan_if
, zvni
);
1946 /* Add VRR MAC-IP - if any*/
1947 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1949 zvni_add_macip_for_intf(vrr_if
, zvni
);
1954 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
1955 struct interface
*ifp
,
1957 struct ethaddr
*macaddr
,
1958 uint8_t router_flag
)
1960 char buf
[ETHER_ADDR_STRLEN
];
1961 char buf2
[INET6_ADDRSTRLEN
];
1962 zebra_neigh_t
*n
= NULL
;
1963 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
1965 /* create a dummy MAC if the MAC is not already present */
1966 zmac
= zvni_mac_lookup(zvni
, macaddr
);
1968 if (IS_ZEBRA_DEBUG_VXLAN
)
1970 "AUTO MAC %s created for neigh %s on VNI %u",
1971 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1972 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1974 zmac
= zvni_mac_add(zvni
, macaddr
);
1976 zlog_warn("Failed to add MAC %s VNI %u",
1977 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1982 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
1983 memset(&zmac
->flags
, 0, sizeof(uint32_t));
1984 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
1987 /* If same entry already exists, it might be a change or it might be a
1988 * move from remote to local.
1990 n
= zvni_neigh_lookup(zvni
, ip
);
1992 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1993 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
1995 /* Update any params and return - client doesn't
1996 * care about a purely local change.
1998 n
->ifindex
= ifp
->ifindex
;
2002 /* If the MAC has changed,
2003 * need to issue a delete first
2004 * as this means a different MACIP route.
2005 * Also, need to do some unlinking/relinking.
2007 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2009 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2011 listnode_delete(old_zmac
->neigh_list
, n
);
2012 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
2015 /* Update the forwarding info. */
2016 n
->ifindex
= ifp
->ifindex
;
2017 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2019 /* Link to new MAC */
2020 listnode_add_sort(zmac
->neigh_list
, n
);
2023 /* Neighbor has moved from remote to local. */
2025 /* If MAC has changed, do the unlink/link */
2026 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2028 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2030 listnode_delete(old_zmac
->neigh_list
,
2032 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
2035 /* Link to new MAC */
2036 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2037 listnode_add_sort(zmac
->neigh_list
, n
);
2040 /* Mark appropriately */
2041 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2042 n
->r_vtep_ip
.s_addr
= 0;
2043 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2044 n
->ifindex
= ifp
->ifindex
;
2047 /* New neighbor - create */
2048 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2051 ZEBRA_ERR_MAC_ADD_FAILED
,
2052 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2053 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2054 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2055 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2058 /* Set "local" forwarding info. */
2059 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2060 n
->ifindex
= ifp
->ifindex
;
2063 /* Before we program this in BGP, we need to check if MAC is locally
2064 * learnt. If not, force neighbor to be inactive.
2066 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
2067 if (IS_ZEBRA_DEBUG_VXLAN
)
2069 "Skipping neigh %s add to client as MAC %s is not local on VNI %u",
2070 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2071 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2074 ZEBRA_NEIGH_SET_INACTIVE(n
);
2078 /*Set router flag (R-bit) */
2080 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2083 if (IS_ZEBRA_DEBUG_VXLAN
)
2084 zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u with flags 0x%x",
2085 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2086 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2087 zvni
->vni
, n
->flags
);
2088 ZEBRA_NEIGH_SET_ACTIVE(n
);
2090 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, n
->flags
);
2093 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
2094 struct interface
*ifp
,
2096 struct ethaddr
*macaddr
,
2099 char buf
[ETHER_ADDR_STRLEN
];
2100 char buf2
[INET6_ADDRSTRLEN
];
2101 zebra_neigh_t
*n
= NULL
;
2102 zebra_mac_t
*zmac
= NULL
;
2104 /* If the neighbor is unknown, there is no further action. */
2105 n
= zvni_neigh_lookup(zvni
, ip
);
2109 /* If a remote entry, see if it needs to be refreshed */
2110 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2112 if (state
& NUD_STALE
)
2113 zvni_neigh_install(zvni
, n
);
2116 /* We got a "remote" neighbor notification for an entry
2117 * we think is local. This can happen in a multihoming
2118 * scenario - but only if the MAC is already "remote".
2119 * Just mark our entry as "remote".
2121 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2122 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2124 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
2125 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
2126 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2131 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2132 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2133 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
2140 * Make hash key for MAC.
2142 static unsigned int mac_hash_keymake(void *p
)
2144 zebra_mac_t
*pmac
= p
;
2145 const void *pnt
= (void *)pmac
->macaddr
.octet
;
2147 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
2151 * Compare two MAC addresses.
2153 static int mac_cmp(const void *p1
, const void *p2
)
2155 const zebra_mac_t
*pmac1
= p1
;
2156 const zebra_mac_t
*pmac2
= p2
;
2158 if (pmac1
== NULL
&& pmac2
== NULL
)
2161 if (pmac1
== NULL
|| pmac2
== NULL
)
2164 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
2169 * Callback to allocate MAC hash entry.
2171 static void *zvni_mac_alloc(void *p
)
2173 const zebra_mac_t
*tmp_mac
= p
;
2176 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2179 return ((void *)mac
);
2185 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
2187 zebra_mac_t tmp_mac
;
2188 zebra_mac_t
*mac
= NULL
;
2190 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
2191 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
2192 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
2195 mac
->neigh_list
= list_new();
2196 mac
->neigh_list
->cmp
= (int (*)(void *, void *))neigh_cmp
;
2204 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2206 zebra_mac_t
*tmp_mac
;
2208 list_delete_and_null(&mac
->neigh_list
);
2210 /* Free the VNI hash entry and allocated memory. */
2211 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
2213 XFREE(MTYPE_MAC
, tmp_mac
);
2219 * Free MAC hash entry (callback)
2221 static void zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2223 struct mac_walk_ctx
*wctx
= arg
;
2224 zebra_mac_t
*mac
= backet
->data
;
2226 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
2227 || ((wctx
->flags
& DEL_REMOTE_MAC
)
2228 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
2229 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
2230 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
2231 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
2232 &wctx
->r_vtep_ip
))) {
2233 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
2234 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
2235 &mac
->macaddr
, mac
->flags
);
2238 if (wctx
->uninstall
)
2239 zvni_mac_uninstall(wctx
->zvni
, mac
, 0);
2241 zvni_mac_del(wctx
->zvni
, mac
);
2248 * Delete all MAC entries from specific VTEP for a particular VNI.
2250 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2251 struct in_addr
*r_vtep_ip
)
2253 struct mac_walk_ctx wctx
;
2255 if (!zvni
->mac_table
)
2258 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2260 wctx
.uninstall
= uninstall
;
2261 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
2262 wctx
.r_vtep_ip
= *r_vtep_ip
;
2264 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2268 * Delete all MAC entries for this VNI.
2270 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2273 struct mac_walk_ctx wctx
;
2275 if (!zvni
->mac_table
)
2278 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2280 wctx
.uninstall
= uninstall
;
2281 wctx
.upd_client
= upd_client
;
2284 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2288 * Look up MAC hash entry.
2290 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
2295 memset(&tmp
, 0, sizeof(tmp
));
2296 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
2297 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
2303 * Inform BGP about local MAC addition.
2305 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2310 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2311 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2312 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2313 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2315 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2320 * Inform BGP about local MAC deletion.
2322 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2327 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2328 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2329 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2330 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2332 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2337 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2338 * notifications, to see if they are of interest.
2340 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
2341 struct interface
*br_if
, vlanid_t vid
)
2343 struct zebra_ns
*zns
;
2344 struct route_node
*rn
;
2345 struct interface
*tmp_if
= NULL
;
2346 struct zebra_if
*zif
;
2347 struct zebra_l2info_bridge
*br
;
2348 struct zebra_l2info_vxlan
*vxl
= NULL
;
2349 uint8_t bridge_vlan_aware
;
2353 /* Determine if bridge is VLAN-aware or not */
2356 br
= &zif
->l2info
.br
;
2357 bridge_vlan_aware
= br
->vlan_aware
;
2359 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2360 /* TODO: Optimize with a hash. */
2361 zns
= zebra_ns_lookup(NS_DEFAULT
);
2362 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2363 tmp_if
= (struct interface
*)rn
->info
;
2367 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2369 if (!if_is_operative(tmp_if
))
2371 vxl
= &zif
->l2info
.vxl
;
2373 if (zif
->brslave_info
.br_if
!= br_if
)
2376 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2385 zvni
= zvni_lookup(vxl
->vni
);
2390 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2391 * neighbor notifications, to see if they are of interest.
2393 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
2394 struct interface
*br_if
)
2396 struct zebra_ns
*zns
;
2397 struct route_node
*rn
;
2398 struct interface
*tmp_if
= NULL
;
2399 struct zebra_if
*zif
;
2400 struct zebra_l2info_bridge
*br
;
2401 struct zebra_l2info_vxlan
*vxl
= NULL
;
2402 uint8_t bridge_vlan_aware
;
2410 /* Make sure the linked interface is a bridge. */
2411 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
2414 /* Determine if bridge is VLAN-aware or not */
2417 br
= &zif
->l2info
.br
;
2418 bridge_vlan_aware
= br
->vlan_aware
;
2419 if (bridge_vlan_aware
) {
2420 struct zebra_l2info_vlan
*vl
;
2422 if (!IS_ZEBRA_IF_VLAN(ifp
))
2427 vl
= &zif
->l2info
.vl
;
2431 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2432 /* TODO: Optimize with a hash. */
2433 zns
= zebra_ns_lookup(NS_DEFAULT
);
2434 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2435 tmp_if
= (struct interface
*)rn
->info
;
2439 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2441 if (!if_is_operative(tmp_if
))
2443 vxl
= &zif
->l2info
.vxl
;
2445 if (zif
->brslave_info
.br_if
!= br_if
)
2448 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2457 zvni
= zvni_lookup(vxl
->vni
);
2461 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
2463 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
2464 * linked to the bridge
2465 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
2468 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
2470 struct zebra_ns
*zns
;
2471 struct route_node
*rn
;
2472 struct interface
*tmp_if
= NULL
;
2473 struct zebra_if
*zif
;
2474 struct zebra_l2info_bridge
*br
;
2475 struct zebra_l2info_vlan
*vl
;
2476 uint8_t bridge_vlan_aware
;
2479 /* Defensive check, caller expected to invoke only with valid bridge. */
2483 /* Determine if bridge is VLAN-aware or not */
2486 br
= &zif
->l2info
.br
;
2487 bridge_vlan_aware
= br
->vlan_aware
;
2489 /* Check oper status of the SVI. */
2490 if (!bridge_vlan_aware
)
2491 return if_is_operative(br_if
) ? br_if
: NULL
;
2493 /* Identify corresponding VLAN interface. */
2494 /* TODO: Optimize with a hash. */
2495 zns
= zebra_ns_lookup(NS_DEFAULT
);
2496 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2497 tmp_if
= (struct interface
*)rn
->info
;
2498 /* Check oper status of the SVI. */
2499 if (!tmp_if
|| !if_is_operative(tmp_if
))
2502 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
2503 || zif
->link
!= br_if
)
2505 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
2507 if (vl
->vid
== vid
) {
2513 return found
? tmp_if
: NULL
;
2517 * Install remote MAC into the kernel.
2519 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2521 struct zebra_if
*zif
;
2522 struct zebra_l2info_vxlan
*vxl
;
2525 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2528 zif
= zvni
->vxlan_if
->info
;
2531 vxl
= &zif
->l2info
.vxl
;
2533 sticky
= CHECK_FLAG(mac
->flags
,
2534 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
)) ? 1 : 0;
2536 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
2537 mac
->fwd_info
.r_vtep_ip
, sticky
);
2541 * Uninstall remote MAC from the kernel. In the scenario where the MAC
2542 * moves to remote, we have to uninstall any existing local entry first.
2544 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
)
2546 struct zebra_if
*zif
;
2547 struct zebra_l2info_vxlan
*vxl
;
2548 struct in_addr vtep_ip
= {.s_addr
= 0};
2549 struct zebra_ns
*zns
;
2550 struct interface
*ifp
;
2552 if (!local
&& !(mac
->flags
& ZEBRA_MAC_REMOTE
))
2555 if (!zvni
->vxlan_if
) {
2556 zlog_warn("VNI %u hash %p couldn't be uninstalled - no intf",
2561 zif
= zvni
->vxlan_if
->info
;
2564 vxl
= &zif
->l2info
.vxl
;
2567 zns
= zebra_ns_lookup(NS_DEFAULT
);
2568 ifp
= if_lookup_by_index_per_ns(zns
,
2569 mac
->fwd_info
.local
.ifindex
);
2570 if (!ifp
) // unexpected
2573 ifp
= zvni
->vxlan_if
;
2574 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
2577 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
,
2582 * Install MAC hash entry - called upon access VLAN change.
2584 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
2587 struct mac_walk_ctx
*wctx
= ctxt
;
2589 mac
= (zebra_mac_t
*)backet
->data
;
2591 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
2592 zvni_mac_install(wctx
->zvni
, mac
);
2596 * Decrement neighbor refcount of MAC; uninstall and free it if
2599 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
2602 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)
2603 || !list_isempty(mac
->neigh_list
))
2607 zvni_mac_uninstall(zvni
, mac
, 0);
2609 zvni_mac_del(zvni
, mac
);
2613 * Read and populate local MACs and neighbors corresponding to this VNI.
2615 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
2617 struct zebra_ns
*zns
;
2618 struct zebra_if
*zif
;
2619 struct interface
*vlan_if
;
2620 struct zebra_l2info_vxlan
*vxl
;
2621 struct interface
*vrr_if
;
2624 vxl
= &zif
->l2info
.vxl
;
2625 zns
= zebra_ns_lookup(NS_DEFAULT
);
2627 if (IS_ZEBRA_DEBUG_VXLAN
)
2629 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2630 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2631 zif
->brslave_info
.bridge_ifindex
);
2633 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
2634 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2637 /* Add SVI MAC-IP */
2638 zvni_add_macip_for_intf(vlan_if
, zvni
);
2640 /* Add VRR MAC-IP - if any*/
2641 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2643 zvni_add_macip_for_intf(vrr_if
, zvni
);
2645 neigh_read_for_vlan(zns
, vlan_if
);
2650 * Hash function for VNI.
2652 static unsigned int vni_hash_keymake(void *p
)
2654 const zebra_vni_t
*zvni
= p
;
2656 return (jhash_1word(zvni
->vni
, 0));
2660 * Compare 2 VNI hash entries.
2662 static int vni_hash_cmp(const void *p1
, const void *p2
)
2664 const zebra_vni_t
*zvni1
= p1
;
2665 const zebra_vni_t
*zvni2
= p2
;
2667 return (zvni1
->vni
== zvni2
->vni
);
2671 * Callback to allocate VNI hash entry.
2673 static void *zvni_alloc(void *p
)
2675 const zebra_vni_t
*tmp_vni
= p
;
2678 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
2679 zvni
->vni
= tmp_vni
->vni
;
2680 return ((void *)zvni
);
2684 * Look up VNI hash entry.
2686 static zebra_vni_t
*zvni_lookup(vni_t vni
)
2688 struct zebra_vrf
*zvrf
;
2689 zebra_vni_t tmp_vni
;
2690 zebra_vni_t
*zvni
= NULL
;
2692 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2694 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
2696 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
2702 * Add VNI hash entry.
2704 static zebra_vni_t
*zvni_add(vni_t vni
)
2706 struct zebra_vrf
*zvrf
;
2707 zebra_vni_t tmp_zvni
;
2708 zebra_vni_t
*zvni
= NULL
;
2710 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2712 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
2714 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
2717 /* Create hash table for MAC */
2719 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
2721 /* Create hash table for neighbors */
2722 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
2723 "Zebra VNI Neighbor Table");
2729 * Delete VNI hash entry.
2731 static int zvni_del(zebra_vni_t
*zvni
)
2733 struct zebra_vrf
*zvrf
;
2734 zebra_vni_t
*tmp_zvni
;
2736 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2739 zvni
->vxlan_if
= NULL
;
2741 /* Free the neighbor hash table. */
2742 hash_free(zvni
->neigh_table
);
2743 zvni
->neigh_table
= NULL
;
2745 /* Free the MAC hash table. */
2746 hash_free(zvni
->mac_table
);
2747 zvni
->mac_table
= NULL
;
2749 /* Free the VNI hash entry and allocated memory. */
2750 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
2752 XFREE(MTYPE_ZVNI
, tmp_zvni
);
2758 * Inform BGP about local VNI addition.
2760 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
2762 struct zserv
*client
;
2765 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2766 /* BGP may not be running. */
2770 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2772 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
2773 stream_putl(s
, zvni
->vni
);
2774 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
2775 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
2777 /* Write packet size. */
2778 stream_putw_at(s
, 0, stream_get_endp(s
));
2780 if (IS_ZEBRA_DEBUG_VXLAN
)
2781 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
2782 inet_ntoa(zvni
->local_vtep_ip
),
2783 vrf_id_to_name(zvni
->vrf_id
),
2784 zebra_route_string(client
->proto
));
2786 client
->vniadd_cnt
++;
2787 return zserv_send_message(client
, s
);
2791 * Inform BGP about local VNI deletion.
2793 static int zvni_send_del_to_client(vni_t vni
)
2795 struct zserv
*client
;
2798 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2799 /* BGP may not be running. */
2803 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2806 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
2807 stream_putl(s
, vni
);
2809 /* Write packet size. */
2810 stream_putw_at(s
, 0, stream_get_endp(s
));
2812 if (IS_ZEBRA_DEBUG_VXLAN
)
2813 zlog_debug("Send VNI_DEL %u to %s", vni
,
2814 zebra_route_string(client
->proto
));
2816 client
->vnidel_cnt
++;
2817 return zserv_send_message(client
, s
);
2821 * Build the VNI hash table by going over the VxLAN interfaces. This
2822 * is called when EVPN (advertise-all-vni) is enabled.
2824 static void zvni_build_hash_table()
2826 struct zebra_ns
*zns
;
2827 struct route_node
*rn
;
2828 struct interface
*ifp
;
2830 /* Walk VxLAN interfaces and create VNI hash. */
2831 zns
= zebra_ns_lookup(NS_DEFAULT
);
2832 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2834 zebra_vni_t
*zvni
= NULL
;
2835 zebra_l3vni_t
*zl3vni
= NULL
;
2836 struct zebra_if
*zif
;
2837 struct zebra_l2info_vxlan
*vxl
;
2839 ifp
= (struct interface
*)rn
->info
;
2843 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2846 vxl
= &zif
->l2info
.vxl
;
2849 /* L3-VNI and L2-VNI are handled seperately */
2850 zl3vni
= zl3vni_lookup(vni
);
2853 if (IS_ZEBRA_DEBUG_VXLAN
)
2855 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
2856 ifp
->name
, ifp
->ifindex
, vni
);
2858 /* associate with vxlan_if */
2859 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
2860 zl3vni
->vxlan_if
= ifp
;
2863 * we need to associate with SVI.
2864 * we can associate with svi-if only after association
2865 * with vxlan-intf is complete
2867 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
2869 if (is_l3vni_oper_up(zl3vni
))
2870 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
2873 struct interface
*vlan_if
= NULL
;
2875 if (IS_ZEBRA_DEBUG_VXLAN
)
2877 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
2878 ifp
->name
, ifp
->ifindex
, vni
,
2879 inet_ntoa(vxl
->vtep_ip
));
2881 /* VNI hash entry is not expected to exist. */
2882 zvni
= zvni_lookup(vni
);
2885 "VNI hash already present for IF %s(%u) L2-VNI %u",
2886 ifp
->name
, ifp
->ifindex
, vni
);
2890 zvni
= zvni_add(vni
);
2893 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
2894 ifp
->name
, ifp
->ifindex
, vni
);
2898 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
2899 zvni
->vxlan_if
= ifp
;
2900 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
2901 zif
->brslave_info
.br_if
);
2903 zvni
->vrf_id
= vlan_if
->vrf_id
;
2904 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
2906 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
2910 /* Inform BGP if intf is up and mapped to bridge. */
2911 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
2912 zvni_send_add_to_client(zvni
);
2918 * See if remote VTEP matches with prefix.
2920 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
2922 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
2926 * Locate remote VTEP in VNI hash table.
2928 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2930 zebra_vtep_t
*zvtep
;
2935 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2936 if (zvni_vtep_match(vtep_ip
, zvtep
))
2944 * Add remote VTEP to VNI hash table.
2946 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2948 zebra_vtep_t
*zvtep
;
2950 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
2952 zvtep
->vtep_ip
= *vtep_ip
;
2955 zvni
->vteps
->prev
= zvtep
;
2956 zvtep
->next
= zvni
->vteps
;
2957 zvni
->vteps
= zvtep
;
2963 * Remove remote VTEP from VNI hash table.
2965 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
2968 zvtep
->next
->prev
= zvtep
->prev
;
2970 zvtep
->prev
->next
= zvtep
->next
;
2972 zvni
->vteps
= zvtep
->next
;
2974 zvtep
->prev
= zvtep
->next
= NULL
;
2975 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
2981 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
2982 * uninstall from kernel if asked to.
2984 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
2986 zebra_vtep_t
*zvtep
, *zvtep_next
;
2991 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
2992 zvtep_next
= zvtep
->next
;
2994 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
2995 zvni_vtep_del(zvni
, zvtep
);
3002 * Install remote VTEP into the kernel.
3004 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3006 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3010 * Uninstall remote VTEP from the kernel.
3012 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3014 if (!zvni
->vxlan_if
) {
3015 zlog_warn("VNI %u hash %p couldn't be uninstalled - no intf",
3020 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3024 * Cleanup VNI/VTEP and update kernel
3026 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
3028 zebra_vni_t
*zvni
= NULL
;
3029 zebra_l3vni_t
*zl3vni
= NULL
;
3030 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
3032 zvni
= (zebra_vni_t
*)backet
->data
;
3034 /* remove from l3-vni list */
3036 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
3038 listnode_delete(zl3vni
->l2vnis
, zvni
);
3040 /* Free up all neighbors and MACs, if any. */
3041 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
3042 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
3044 /* Free up all remote VTEPs, if any. */
3045 zvni_vtep_del_all(zvni
, 1);
3047 /* Delete the hash entry. */
3052 static void zl3vni_cleanup_all(struct hash_backet
*backet
, void *args
)
3054 zebra_l3vni_t
*zl3vni
= NULL
;
3056 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
3058 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
3061 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
3062 struct prefix
*host
)
3064 struct host_rb_entry lookup
;
3065 struct host_rb_entry
*hle
;
3067 memset(&lookup
, 0, sizeof(lookup
));
3068 memcpy(&lookup
.p
, host
, sizeof(*host
));
3070 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3074 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
3075 memcpy(hle
, &lookup
, sizeof(lookup
));
3077 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
3080 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
3082 struct host_rb_entry lookup
;
3083 struct host_rb_entry
*hle
;
3085 memset(&lookup
, 0, sizeof(lookup
));
3086 memcpy(&lookup
.p
, host
, sizeof(*host
));
3088 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3090 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
3091 XFREE(MTYPE_HOST_PREFIX
, hle
);
3098 * Look up MAC hash entry.
3100 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
3101 struct ethaddr
*rmac
)
3106 memset(&tmp
, 0, sizeof(tmp
));
3107 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
3108 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
3114 * Callback to allocate RMAC hash entry.
3116 static void *zl3vni_rmac_alloc(void *p
)
3118 const zebra_mac_t
*tmp_rmac
= p
;
3121 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3124 return ((void *)zrmac
);
3128 * Add RMAC entry to l3-vni
3130 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
3132 zebra_mac_t tmp_rmac
;
3133 zebra_mac_t
*zrmac
= NULL
;
3135 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
3136 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
3137 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
3140 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
3142 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
3143 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
3151 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3153 zebra_mac_t
*tmp_rmac
;
3154 struct host_rb_entry
*hle
;
3156 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3157 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
3159 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
3160 XFREE(MTYPE_HOST_PREFIX
, hle
);
3163 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
3165 XFREE(MTYPE_MAC
, tmp_rmac
);
3171 * Install remote RMAC into the kernel.
3173 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3175 struct zebra_if
*zif
= NULL
;
3176 struct zebra_l2info_vxlan
*vxl
= NULL
;
3178 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3179 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3182 zif
= zl3vni
->vxlan_if
->info
;
3186 vxl
= &zif
->l2info
.vxl
;
3188 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3189 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3193 * Uninstall remote RMAC from the kernel.
3195 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3197 char buf
[ETHER_ADDR_STRLEN
];
3198 struct zebra_if
*zif
= NULL
;
3199 struct zebra_l2info_vxlan
*vxl
= NULL
;
3201 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3202 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3205 if (!zl3vni
->vxlan_if
) {
3207 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
3208 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
3209 zl3vni
->vni
, zl3vni
);
3213 zif
= zl3vni
->vxlan_if
->info
;
3217 vxl
= &zif
->l2info
.vxl
;
3219 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3220 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3223 /* handle rmac add */
3224 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
3225 struct ipaddr
*vtep_ip
,
3226 struct prefix
*host_prefix
)
3228 char buf
[ETHER_ADDR_STRLEN
];
3229 char buf1
[INET6_ADDRSTRLEN
];
3230 zebra_mac_t
*zrmac
= NULL
;
3232 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3235 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
3238 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
3239 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3241 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
3244 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
3245 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
3247 /* install rmac in kernel */
3248 zl3vni_rmac_install(zl3vni
, zrmac
);
3251 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
3257 /* handle rmac delete */
3258 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
3259 struct prefix
*host_prefix
)
3261 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
3263 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3264 /* uninstall from kernel */
3265 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3267 /* del the rmac entry */
3268 zl3vni_rmac_del(zl3vni
, zrmac
);
3273 * Look up nh hash entry on a l3-vni.
3275 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3280 memset(&tmp
, 0, sizeof(tmp
));
3281 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
3282 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
3289 * Callback to allocate NH hash entry on L3-VNI.
3291 static void *zl3vni_nh_alloc(void *p
)
3293 const zebra_neigh_t
*tmp_n
= p
;
3296 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
3303 * Add neighbor entry.
3305 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3306 struct ethaddr
*mac
)
3308 zebra_neigh_t tmp_n
;
3309 zebra_neigh_t
*n
= NULL
;
3311 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
3312 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
3313 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
3316 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
3318 memcpy(&n
->emac
, mac
, ETH_ALEN
);
3319 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3320 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
3326 * Delete neighbor entry.
3328 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3330 zebra_neigh_t
*tmp_n
;
3331 struct host_rb_entry
*hle
;
3333 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
3334 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
3336 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
3337 XFREE(MTYPE_HOST_PREFIX
, hle
);
3340 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
3342 XFREE(MTYPE_NEIGH
, tmp_n
);
3348 * Install remote nh as neigh into the kernel.
3350 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3355 if (!is_l3vni_oper_up(zl3vni
))
3358 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3359 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3362 flags
= NTF_EXT_LEARNED
;
3363 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
3364 flags
|= NTF_ROUTER
;
3365 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
3371 * Uninstall remote nh from the kernel.
3373 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3375 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3376 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3379 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
3382 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
3385 /* add remote vtep as a neigh entry */
3386 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
3387 struct ethaddr
*rmac
,
3388 struct prefix
*host_prefix
)
3390 char buf
[ETHER_ADDR_STRLEN
];
3391 char buf1
[INET6_ADDRSTRLEN
];
3392 zebra_neigh_t
*nh
= NULL
;
3394 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3396 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
3400 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
3401 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
3402 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3407 /* install the nh neigh in kernel */
3408 zl3vni_nh_install(zl3vni
, nh
);
3411 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
3416 /* handle nh neigh delete */
3417 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
3418 struct prefix
*host_prefix
)
3420 rb_delete_host(&nh
->host_rb
, host_prefix
);
3422 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
3423 /* uninstall from kernel */
3424 zl3vni_nh_uninstall(zl3vni
, nh
);
3426 /* delete the nh entry */
3427 zl3vni_nh_del(zl3vni
, nh
);
3431 /* handle neigh update from kernel - the only thing of interest is to
3432 * readd stale entries.
3434 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3438 zebra_neigh_t
*n
= NULL
;
3440 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3444 /* all next hop neigh are remote and installed by frr.
3445 * If the kernel has aged this entry, re-install.
3447 if (state
& NUD_STALE
)
3448 zl3vni_nh_install(zl3vni
, n
);
3453 /* handle neigh delete from kernel */
3454 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3456 zebra_neigh_t
*n
= NULL
;
3458 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3462 /* all next hop neigh are remote and installed by frr.
3463 * If we get an age out notification for these neigh entries, we have to
3466 zl3vni_nh_install(zl3vni
, n
);
3472 * Hash function for L3 VNI.
3474 static unsigned int l3vni_hash_keymake(void *p
)
3476 const zebra_l3vni_t
*zl3vni
= p
;
3478 return jhash_1word(zl3vni
->vni
, 0);
3482 * Compare 2 L3 VNI hash entries.
3484 static int l3vni_hash_cmp(const void *p1
, const void *p2
)
3486 const zebra_l3vni_t
*zl3vni1
= p1
;
3487 const zebra_l3vni_t
*zl3vni2
= p2
;
3489 return (zl3vni1
->vni
== zl3vni2
->vni
);
3493 * Callback to allocate L3 VNI hash entry.
3495 static void *zl3vni_alloc(void *p
)
3497 zebra_l3vni_t
*zl3vni
= NULL
;
3498 const zebra_l3vni_t
*tmp_l3vni
= p
;
3500 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
3501 zl3vni
->vni
= tmp_l3vni
->vni
;
3502 return ((void *)zl3vni
);
3506 * Look up L3 VNI hash entry.
3508 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
3510 struct zebra_ns
*zns
;
3511 zebra_l3vni_t tmp_l3vni
;
3512 zebra_l3vni_t
*zl3vni
= NULL
;
3514 zns
= zebra_ns_lookup(NS_DEFAULT
);
3516 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
3517 tmp_l3vni
.vni
= vni
;
3518 zl3vni
= hash_lookup(zns
->l3vni_table
, &tmp_l3vni
);
3524 * Add L3 VNI hash entry.
3526 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
3528 zebra_l3vni_t tmp_zl3vni
;
3529 struct zebra_ns
*zns
= NULL
;
3530 zebra_l3vni_t
*zl3vni
= NULL
;
3532 zns
= zebra_ns_lookup(NS_DEFAULT
);
3535 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
3536 tmp_zl3vni
.vni
= vni
;
3538 zl3vni
= hash_get(zns
->l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
3541 zl3vni
->vrf_id
= vrf_id
;
3542 zl3vni
->svi_if
= NULL
;
3543 zl3vni
->vxlan_if
= NULL
;
3544 zl3vni
->l2vnis
= list_new();
3545 zl3vni
->l2vnis
->cmp
= (int (*)(void *, void *))vni_hash_cmp
;
3547 /* Create hash table for remote RMAC */
3548 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
3549 "Zebra L3-VNI RMAC-Table");
3551 /* Create hash table for neighbors */
3552 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3553 "Zebra L3-VNI next-hop table");
3559 * Delete L3 VNI hash entry.
3561 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
3563 struct zebra_ns
*zns
;
3564 zebra_l3vni_t
*tmp_zl3vni
;
3566 zns
= zebra_ns_lookup(NS_DEFAULT
);
3569 /* free the list of l2vnis */
3570 list_delete_and_null(&zl3vni
->l2vnis
);
3571 zl3vni
->l2vnis
= NULL
;
3573 /* Free the rmac table */
3574 hash_free(zl3vni
->rmac_table
);
3575 zl3vni
->rmac_table
= NULL
;
3577 /* Free the nh table */
3578 hash_free(zl3vni
->nh_table
);
3579 zl3vni
->nh_table
= NULL
;
3581 /* Free the VNI hash entry and allocated memory. */
3582 tmp_zl3vni
= hash_release(zns
->l3vni_table
, zl3vni
);
3584 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
3589 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
3591 struct zebra_ns
*zns
= NULL
;
3592 struct route_node
*rn
= NULL
;
3593 struct interface
*ifp
= NULL
;
3595 /* loop through all vxlan-interface */
3596 zns
= zebra_ns_lookup(NS_DEFAULT
);
3597 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3599 struct zebra_if
*zif
= NULL
;
3600 struct zebra_l2info_vxlan
*vxl
= NULL
;
3602 ifp
= (struct interface
*)rn
->info
;
3607 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3610 vxl
= &zif
->l2info
.vxl
;
3611 if (vxl
->vni
== zl3vni
->vni
) {
3612 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3620 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
3622 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
3623 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
3628 if (!zl3vni
->vxlan_if
)
3631 zif
= zl3vni
->vxlan_if
->info
;
3635 vxl
= &zif
->l2info
.vxl
;
3637 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3640 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
3642 struct zebra_vrf
*zvrf
= NULL
;
3644 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
3648 return zl3vni_lookup(zvrf
->l3vni
);
3652 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3653 * neighbor notifications, to see if they are of interest.
3655 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
3656 struct interface
*br_if
)
3660 uint8_t bridge_vlan_aware
= 0;
3661 zebra_l3vni_t
*zl3vni
= NULL
;
3662 struct zebra_ns
*zns
= NULL
;
3663 struct route_node
*rn
= NULL
;
3664 struct zebra_if
*zif
= NULL
;
3665 struct interface
*tmp_if
= NULL
;
3666 struct zebra_l2info_bridge
*br
= NULL
;
3667 struct zebra_l2info_vxlan
*vxl
= NULL
;
3672 /* Make sure the linked interface is a bridge. */
3673 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3676 /* Determine if bridge is VLAN-aware or not */
3679 br
= &zif
->l2info
.br
;
3680 bridge_vlan_aware
= br
->vlan_aware
;
3681 if (bridge_vlan_aware
) {
3682 struct zebra_l2info_vlan
*vl
;
3684 if (!IS_ZEBRA_IF_VLAN(ifp
))
3689 vl
= &zif
->l2info
.vl
;
3693 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3694 /* TODO: Optimize with a hash. */
3695 zns
= zebra_ns_lookup(NS_DEFAULT
);
3696 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3697 tmp_if
= (struct interface
*)rn
->info
;
3701 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3703 if (!if_is_operative(tmp_if
))
3705 vxl
= &zif
->l2info
.vxl
;
3707 if (zif
->brslave_info
.br_if
!= br_if
)
3710 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3719 zl3vni
= zl3vni_lookup(vxl
->vni
);
3724 * Inform BGP about l3-vni.
3726 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
3728 struct stream
*s
= NULL
;
3729 struct zserv
*client
= NULL
;
3730 struct ethaddr rmac
;
3731 char buf
[ETHER_ADDR_STRLEN
];
3733 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3734 /* BGP may not be running. */
3739 memset(&rmac
, 0, sizeof(struct ethaddr
));
3740 zl3vni_get_rmac(zl3vni
, &rmac
);
3742 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3744 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
3745 stream_putl(s
, zl3vni
->vni
);
3746 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
3747 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
3748 stream_put(s
, &zl3vni
->filter
, sizeof(int));
3750 /* Write packet size. */
3751 stream_putw_at(s
, 0, stream_get_endp(s
));
3753 if (IS_ZEBRA_DEBUG_VXLAN
)
3755 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
3756 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3757 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
3758 inet_ntoa(zl3vni
->local_vtep_ip
),
3759 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
3760 ? "prefix-routes-only"
3762 zebra_route_string(client
->proto
));
3764 client
->l3vniadd_cnt
++;
3765 return zserv_send_message(client
, s
);
3769 * Inform BGP about local l3-VNI deletion.
3771 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
3773 struct stream
*s
= NULL
;
3774 struct zserv
*client
= NULL
;
3776 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3777 /* BGP may not be running. */
3781 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3783 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
3784 stream_putl(s
, zl3vni
->vni
);
3786 /* Write packet size. */
3787 stream_putw_at(s
, 0, stream_get_endp(s
));
3789 if (IS_ZEBRA_DEBUG_VXLAN
)
3790 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
3791 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3792 zebra_route_string(client
->proto
));
3794 client
->l3vnidel_cnt
++;
3795 return zserv_send_message(client
, s
);
3798 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
3803 /* send l3vni add to BGP */
3804 zl3vni_send_add_to_client(zl3vni
);
3807 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
3812 /* send l3-vni del to BGP*/
3813 zl3vni_send_del_to_client(zl3vni
);
3816 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
, void *ctxt
)
3818 zebra_vni_t
*zvni
= (zebra_vni_t
*)backet
->data
;
3819 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
3821 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
3822 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3826 * handle transition of vni from l2 to l3 and vice versa
3828 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
3831 zebra_vni_t
*zvni
= NULL
;
3833 /* There is a possibility that VNI notification was already received
3834 * from kernel and we programmed it as L2-VNI
3835 * In such a case we need to delete this L2-VNI first, so
3836 * that it can be reprogrammed as L3-VNI in the system. It is also
3837 * possible that the vrf-vni mapping is removed from FRR while the vxlan
3838 * interface is still present in kernel. In this case to keep it
3839 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
3842 /* Locate hash entry */
3843 zvni
= zvni_lookup(vni
);
3847 if (IS_ZEBRA_DEBUG_VXLAN
)
3848 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
3850 /* Delete VNI from BGP. */
3851 zvni_send_del_to_client(zvni
->vni
);
3853 /* Free up all neighbors and MAC, if any. */
3854 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
3855 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
3857 /* Free up all remote VTEPs, if any. */
3858 zvni_vtep_del_all(zvni
, 0);
3860 /* Delete the hash entry. */
3861 if (zvni_del(zvni
)) {
3862 flog_err(ZEBRA_ERR_VNI_DEL_FAILED
,
3863 "Failed to del VNI hash %p, VNI %u", zvni
,
3868 /* TODO_MITESH: This needs to be thought through. We don't have
3869 * enough information at this point to reprogram the vni as
3870 * l2-vni. One way is to store the required info in l3-vni and
3871 * used it solely for this purpose
3878 /* delete and uninstall rmac hash entry */
3879 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
, void *ctx
)
3881 zebra_mac_t
*zrmac
= NULL
;
3882 zebra_l3vni_t
*zl3vni
= NULL
;
3884 zrmac
= (zebra_mac_t
*)backet
->data
;
3885 zl3vni
= (zebra_l3vni_t
*)ctx
;
3886 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3887 zl3vni_rmac_del(zl3vni
, zrmac
);
3890 /* delete and uninstall nh hash entry */
3891 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
, void *ctx
)
3893 zebra_neigh_t
*n
= NULL
;
3894 zebra_l3vni_t
*zl3vni
= NULL
;
3896 n
= (zebra_neigh_t
*)backet
->data
;
3897 zl3vni
= (zebra_l3vni_t
*)ctx
;
3898 zl3vni_nh_uninstall(zl3vni
, n
);
3899 zl3vni_nh_del(zl3vni
, n
);
3902 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
3905 struct zserv
*client
= NULL
;
3906 struct stream
*s
= NULL
;
3907 char buf
[PREFIX_STRLEN
];
3909 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3910 /* BGP may not be running. */
3914 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3916 zclient_create_header(s
, cmd
, vrf_id
);
3917 stream_put(s
, p
, sizeof(struct prefix
));
3919 /* Write packet size. */
3920 stream_putw_at(s
, 0, stream_get_endp(s
));
3922 if (IS_ZEBRA_DEBUG_VXLAN
)
3923 zlog_debug("Send ip prefix %s %s on vrf %s",
3924 prefix2str(p
, buf
, sizeof(buf
)),
3925 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
3926 vrf_id_to_name(vrf_id
));
3928 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
3929 client
->prefixadd_cnt
++;
3931 client
->prefixdel_cnt
++;
3933 return zserv_send_message(client
, s
);
3936 /* re-add remote rmac if needed */
3937 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
3938 struct ethaddr
*rmac
)
3940 char buf
[ETHER_ADDR_STRLEN
];
3941 zebra_mac_t
*zrmac
= NULL
;
3943 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3947 if (IS_ZEBRA_DEBUG_VXLAN
)
3948 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
3949 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
3951 zl3vni_rmac_install(zl3vni
, zrmac
);
3955 /* Public functions */
3957 int is_l3vni_for_prefix_routes_only(vni_t vni
)
3959 zebra_l3vni_t
*zl3vni
= NULL
;
3961 zl3vni
= zl3vni_lookup(vni
);
3965 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
3968 /* handle evpn route in vrf table */
3969 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
3970 struct ipaddr
*vtep_ip
,
3971 struct prefix
*host_prefix
)
3973 zebra_l3vni_t
*zl3vni
= NULL
;
3974 struct ipaddr ipv4_vtep
;
3976 zl3vni
= zl3vni_from_vrf(vrf_id
);
3977 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
3981 * add the next hop neighbor -
3982 * neigh to be installed is the ipv6 nexthop neigh
3984 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
3987 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
3988 * address. Rmac is programmed against the ipv4 vtep because we only
3989 * support ipv4 tunnels in the h/w right now
3991 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
3992 ipv4_vtep
.ipa_type
= IPADDR_V4
;
3993 if (vtep_ip
->ipa_type
== IPADDR_V6
)
3994 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
3995 &(ipv4_vtep
.ipaddr_v4
));
3997 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
3998 sizeof(struct in_addr
));
4001 * add the rmac - remote rmac to be installed is against the ipv4
4004 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
4007 /* handle evpn vrf route delete */
4008 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
4009 struct ipaddr
*vtep_ip
,
4010 struct prefix
*host_prefix
)
4012 zebra_l3vni_t
*zl3vni
= NULL
;
4013 zebra_neigh_t
*nh
= NULL
;
4014 zebra_mac_t
*zrmac
= NULL
;
4016 zl3vni
= zl3vni_from_vrf(vrf_id
);
4020 /* find the next hop entry and rmac entry */
4021 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4024 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
4026 /* delete the next hop entry */
4027 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
4029 /* delete the rmac entry */
4031 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
4035 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
4036 struct ethaddr
*rmac
,
4039 zebra_l3vni_t
*zl3vni
= NULL
;
4040 zebra_mac_t
*zrmac
= NULL
;
4041 json_object
*json
= NULL
;
4043 if (!is_evpn_enabled()) {
4045 vty_out(vty
, "{}\n");
4050 json
= json_object_new_object();
4052 zl3vni
= zl3vni_lookup(l3vni
);
4055 vty_out(vty
, "{}\n");
4057 vty_out(vty
, "%% L3-VNI %u doesnt exist\n", l3vni
);
4061 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4064 vty_out(vty
, "{}\n");
4067 "%% Requested RMAC doesnt exist in L3-VNI %u",
4072 zl3vni_print_rmac(zrmac
, vty
, json
);
4075 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4076 json
, JSON_C_TO_STRING_PRETTY
));
4077 json_object_free(json
);
4081 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
,
4084 zebra_l3vni_t
*zl3vni
;
4086 struct rmac_walk_ctx wctx
;
4087 json_object
*json
= NULL
;
4089 if (!is_evpn_enabled())
4092 zl3vni
= zl3vni_lookup(l3vni
);
4095 vty_out(vty
, "{}\n");
4097 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4100 num_rmacs
= hashcount(zl3vni
->rmac_table
);
4105 json
= json_object_new_object();
4107 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
4111 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
4113 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
4115 json_object_int_add(json
, "numRmacs", num_rmacs
);
4117 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
4120 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4121 json
, JSON_C_TO_STRING_PRETTY
));
4122 json_object_free(json
);
4126 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, uint8_t use_json
)
4128 struct zebra_ns
*zns
= NULL
;
4129 json_object
*json
= NULL
;
4132 if (!is_evpn_enabled()) {
4134 vty_out(vty
, "{}\n");
4138 zns
= zebra_ns_lookup(NS_DEFAULT
);
4141 vty_out(vty
, "{}\n");
4146 json
= json_object_new_object();
4150 hash_iterate(zns
->l3vni_table
,
4151 (void (*)(struct hash_backet
*,
4152 void *))zl3vni_print_rmac_hash_all_vni
,
4156 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4157 json
, JSON_C_TO_STRING_PRETTY
));
4158 json_object_free(json
);
4162 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
4163 struct ipaddr
*ip
, uint8_t use_json
)
4165 zebra_l3vni_t
*zl3vni
= NULL
;
4166 zebra_neigh_t
*n
= NULL
;
4167 json_object
*json
= NULL
;
4169 if (!is_evpn_enabled()) {
4171 vty_out(vty
, "{}\n");
4176 json
= json_object_new_object();
4178 zl3vni
= zl3vni_lookup(l3vni
);
4181 vty_out(vty
, "{}\n");
4183 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4187 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4190 vty_out(vty
, "{}\n");
4193 "%% Requested next-hop not present for L3-VNI %u",
4198 zl3vni_print_nh(n
, vty
, json
);
4201 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4202 json
, JSON_C_TO_STRING_PRETTY
));
4203 json_object_free(json
);
4207 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, uint8_t use_json
)
4210 struct nh_walk_ctx wctx
;
4211 json_object
*json
= NULL
;
4212 zebra_l3vni_t
*zl3vni
= NULL
;
4214 if (!is_evpn_enabled())
4217 zl3vni
= zl3vni_lookup(l3vni
);
4220 vty_out(vty
, "{}\n");
4222 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4226 num_nh
= hashcount(zl3vni
->nh_table
);
4231 json
= json_object_new_object();
4236 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
4238 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
4240 json_object_int_add(json
, "numNextHops", num_nh
);
4242 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
4245 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4246 json
, JSON_C_TO_STRING_PRETTY
));
4247 json_object_free(json
);
4251 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, uint8_t use_json
)
4253 struct zebra_ns
*zns
= NULL
;
4254 json_object
*json
= NULL
;
4257 if (!is_evpn_enabled()) {
4259 vty_out(vty
, "{}\n");
4263 zns
= zebra_ns_lookup(NS_DEFAULT
);
4268 json
= json_object_new_object();
4272 hash_iterate(zns
->l3vni_table
,
4273 (void (*)(struct hash_backet
*,
4274 void *))zl3vni_print_nh_hash_all_vni
,
4278 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4279 json
, JSON_C_TO_STRING_PRETTY
));
4280 json_object_free(json
);
4286 * Display L3 VNI information (VTY command handler).
4288 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, uint8_t use_json
)
4291 json_object
*json
= NULL
;
4292 zebra_l3vni_t
*zl3vni
= NULL
;
4294 if (!is_evpn_enabled()) {
4296 vty_out(vty
, "{}\n");
4300 zl3vni
= zl3vni_lookup(vni
);
4303 vty_out(vty
, "{}\n");
4305 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4310 json
= json_object_new_object();
4314 zl3vni_print(zl3vni
, (void *)args
);
4317 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4318 json
, JSON_C_TO_STRING_PRETTY
));
4319 json_object_free(json
);
4323 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4324 json_object
*json_vrfs
)
4326 char buf
[ETHER_ADDR_STRLEN
];
4327 zebra_l3vni_t
*zl3vni
= NULL
;
4329 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4334 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
4335 zvrf_name(zvrf
), zl3vni
->vni
,
4336 zl3vni_vxlan_if_name(zl3vni
),
4337 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
4338 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4340 json_object
*json_vrf
= NULL
;
4341 json_vrf
= json_object_new_object();
4342 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
4343 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
4344 json_object_string_add(json_vrf
, "vxlanIntf",
4345 zl3vni_vxlan_if_name(zl3vni
));
4346 json_object_string_add(json_vrf
, "sviIntf",
4347 zl3vni_svi_if_name(zl3vni
));
4348 json_object_string_add(json_vrf
, "state",
4349 zl3vni_state2str(zl3vni
));
4350 json_object_string_add(
4351 json_vrf
, "routerMac",
4352 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4353 json_object_array_add(json_vrfs
, json_vrf
);
4358 * Display Neighbors for a VNI (VTY command handler).
4360 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4361 vni_t vni
, uint8_t use_json
)
4365 struct neigh_walk_ctx wctx
;
4366 json_object
*json
= NULL
;
4368 if (!is_evpn_enabled())
4370 zvni
= zvni_lookup(vni
);
4373 vty_out(vty
, "{}\n");
4375 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4378 num_neigh
= hashcount(zvni
->neigh_table
);
4383 json
= json_object_new_object();
4385 /* Since we have IPv6 addresses to deal with which can vary widely in
4386 * size, we try to be a bit more elegant in display by first computing
4387 * the maximum width.
4389 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4392 wctx
.addr_width
= 15;
4394 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4398 "Number of ARPs (local and remote) known for this VNI: %u\n",
4400 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
4401 "Type", "MAC", "Remote VTEP");
4403 json_object_int_add(json
, "numArpNd", num_neigh
);
4405 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4407 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4408 json
, JSON_C_TO_STRING_PRETTY
));
4409 json_object_free(json
);
4414 * Display neighbors across all VNIs (VTY command handler).
4416 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4419 json_object
*json
= NULL
;
4422 if (!is_evpn_enabled())
4426 json
= json_object_new_object();
4430 hash_iterate(zvrf
->vni_table
,
4431 (void (*)(struct hash_backet
*,
4432 void *))zvni_print_neigh_hash_all_vni
,
4435 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4436 json
, JSON_C_TO_STRING_PRETTY
));
4437 json_object_free(json
);
4442 * Display specific neighbor for a VNI, if present (VTY command handler).
4444 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
4445 struct zebra_vrf
*zvrf
, vni_t vni
,
4446 struct ipaddr
*ip
, uint8_t use_json
)
4450 json_object
*json
= NULL
;
4452 if (!is_evpn_enabled())
4454 zvni
= zvni_lookup(vni
);
4457 vty_out(vty
, "{}\n");
4459 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4462 n
= zvni_neigh_lookup(zvni
, ip
);
4466 "%% Requested neighbor does not exist in VNI %u\n",
4471 json
= json_object_new_object();
4473 zvni_print_neigh(n
, vty
, json
);
4476 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4477 json
, JSON_C_TO_STRING_PRETTY
));
4478 json_object_free(json
);
4483 * Display neighbors for a VNI from specific VTEP (VTY command handler).
4484 * By definition, these are remote neighbors.
4486 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4487 vni_t vni
, struct in_addr vtep_ip
,
4492 struct neigh_walk_ctx wctx
;
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 num_neigh
= hashcount(zvni
->neigh_table
);
4509 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4512 wctx
.addr_width
= 15;
4513 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
4514 wctx
.r_vtep_ip
= vtep_ip
;
4516 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4517 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4520 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4521 json
, JSON_C_TO_STRING_PRETTY
));
4522 json_object_free(json
);
4527 * Display MACs for a VNI (VTY command handler).
4529 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4530 vni_t vni
, uint8_t use_json
)
4534 struct mac_walk_ctx wctx
;
4535 json_object
*json
= NULL
;
4536 json_object
*json_mac
= 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_macs
= num_valid_macs(zvni
);
4553 json
= json_object_new_object();
4554 json_mac
= json_object_new_object();
4557 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4560 wctx
.json
= json_mac
;
4564 "Number of MACs (local and remote) known for this VNI: %u\n",
4566 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
4567 "Intf/Remote VTEP", "VLAN");
4569 json_object_int_add(json
, "numMacs", num_macs
);
4571 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4574 json_object_object_add(json
, "macs", json_mac
);
4575 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4576 json
, JSON_C_TO_STRING_PRETTY
));
4577 json_object_free(json
);
4582 * Display MACs for all VNIs (VTY command handler).
4584 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4587 struct mac_walk_ctx wctx
;
4588 json_object
*json
= NULL
;
4590 if (!is_evpn_enabled()) {
4592 vty_out(vty
, "{}\n");
4596 json
= json_object_new_object();
4598 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4601 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4604 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4605 json
, JSON_C_TO_STRING_PRETTY
));
4606 json_object_free(json
);
4611 * Display MACs for all VNIs (VTY command handler).
4613 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
4614 struct zebra_vrf
*zvrf
,
4615 struct in_addr vtep_ip
,
4618 struct mac_walk_ctx wctx
;
4619 json_object
*json
= NULL
;
4621 if (!is_evpn_enabled())
4625 json
= json_object_new_object();
4627 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4629 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4630 wctx
.r_vtep_ip
= vtep_ip
;
4632 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4635 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4636 json
, JSON_C_TO_STRING_PRETTY
));
4637 json_object_free(json
);
4642 * Display specific MAC for a VNI, if present (VTY command handler).
4644 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4645 vni_t vni
, struct ethaddr
*macaddr
)
4650 if (!is_evpn_enabled())
4652 zvni
= zvni_lookup(vni
);
4654 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4657 mac
= zvni_mac_lookup(zvni
, macaddr
);
4659 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
4664 zvni_print_mac(mac
, vty
);
4668 * Display MACs for a VNI from specific VTEP (VTY command handler).
4670 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4671 vni_t vni
, struct in_addr vtep_ip
,
4676 struct mac_walk_ctx wctx
;
4677 json_object
*json
= NULL
;
4678 json_object
*json_mac
= NULL
;
4680 if (!is_evpn_enabled())
4682 zvni
= zvni_lookup(vni
);
4685 vty_out(vty
, "{}\n");
4687 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4690 num_macs
= num_valid_macs(zvni
);
4695 json
= json_object_new_object();
4696 json_mac
= json_object_new_object();
4699 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4702 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4703 wctx
.r_vtep_ip
= vtep_ip
;
4704 wctx
.json
= json_mac
;
4705 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4708 json_object_int_add(json
, "numMacs", wctx
.count
);
4710 json_object_object_add(json
, "macs", json_mac
);
4711 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4712 json
, JSON_C_TO_STRING_PRETTY
));
4713 json_object_free(json
);
4719 * Display VNI information (VTY command handler).
4721 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
4724 json_object
*json
= NULL
;
4726 zebra_l3vni_t
*zl3vni
= NULL
;
4727 zebra_vni_t
*zvni
= NULL
;
4729 if (!is_evpn_enabled())
4733 json
= json_object_new_object();
4737 zl3vni
= zl3vni_lookup(vni
);
4739 zl3vni_print(zl3vni
, (void *)args
);
4741 zvni
= zvni_lookup(vni
);
4744 vty_out(vty
, "{}\n");
4746 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4750 zvni_print(zvni
, (void *)args
);
4754 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4755 json
, JSON_C_TO_STRING_PRETTY
));
4756 json_object_free(json
);
4760 /* Display all global details for EVPN */
4761 void zebra_vxlan_print_evpn(struct vty
*vty
, uint8_t uj
)
4766 json_object
*json
= NULL
;
4767 struct zebra_ns
*zns
= NULL
;
4768 struct zebra_vrf
*zvrf
= NULL
;
4770 if (!is_evpn_enabled())
4773 zns
= zebra_ns_lookup(NS_DEFAULT
);
4777 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
4781 num_l3vnis
= hashcount(zns
->l3vni_table
);
4782 num_l2vnis
= hashcount(zvrf
->vni_table
);
4783 num_vnis
= num_l2vnis
+ num_l3vnis
;
4786 json
= json_object_new_object();
4787 json_object_string_add(json
, "advertiseGatewayMacip",
4788 zvrf
->advertise_gw_macip
? "Yes" : "No");
4789 json_object_int_add(json
, "numVnis", num_vnis
);
4790 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4791 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4793 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
4794 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
4795 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
4796 zvrf
->advertise_gw_macip
? "Yes" : "No");
4800 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4801 json
, JSON_C_TO_STRING_PRETTY
));
4802 json_object_free(json
);
4807 * Display VNI hash table (VTY command handler).
4809 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4812 json_object
*json
= NULL
;
4813 struct zebra_ns
*zns
= NULL
;
4816 if (!is_evpn_enabled())
4819 zns
= zebra_ns_lookup(NS_DEFAULT
);
4825 json
= json_object_new_object();
4827 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
4828 "Type", "VxLAN IF", "# MACs", "# ARPs",
4829 "# Remote VTEPs", "Tenant VRF");
4834 /* Display all L2-VNIs */
4835 hash_iterate(zvrf
->vni_table
,
4836 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
4839 /* Display all L3-VNIs */
4840 hash_iterate(zns
->l3vni_table
,
4841 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
4845 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4846 json
, JSON_C_TO_STRING_PRETTY
));
4847 json_object_free(json
);
4852 * Handle neighbor delete notification from the kernel (on a VLAN device
4853 * / L3 interface). This may result in either the neighbor getting deleted
4854 * from our database or being re-added to the kernel (if it is a valid
4857 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
4858 struct interface
*link_if
,
4861 char buf
[INET6_ADDRSTRLEN
];
4862 char buf2
[ETHER_ADDR_STRLEN
];
4863 zebra_neigh_t
*n
= NULL
;
4864 zebra_vni_t
*zvni
= NULL
;
4865 zebra_mac_t
*zmac
= NULL
;
4866 zebra_l3vni_t
*zl3vni
= NULL
;
4868 /* check if this is a remote neigh entry corresponding to remote
4871 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4873 return zl3vni_local_nh_del(zl3vni
, ip
);
4875 /* We are only interested in neighbors on an SVI that resides on top
4876 * of a VxLAN bridge.
4878 zvni
= zvni_from_svi(ifp
, link_if
);
4882 if (!zvni
->vxlan_if
) {
4884 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
4889 if (IS_ZEBRA_DEBUG_VXLAN
)
4890 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
4891 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
4892 ifp
->ifindex
, zvni
->vni
);
4894 /* If entry doesn't exist, nothing to do. */
4895 n
= zvni_neigh_lookup(zvni
, ip
);
4899 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
4901 if (IS_ZEBRA_DEBUG_VXLAN
)
4903 "Trying to del a neigh %s without a mac %s on VNI %u",
4904 ipaddr2str(ip
, buf
, sizeof(buf
)),
4905 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
4911 /* If it is a remote entry, the kernel has aged this out or someone has
4912 * deleted it, it needs to be re-installed as Quagga is the owner.
4914 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
4915 zvni_neigh_install(zvni
, n
);
4919 /* Remove neighbor from BGP. */
4920 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
4921 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0);
4923 /* Delete this neighbor entry. */
4924 zvni_neigh_del(zvni
, n
);
4926 /* see if the AUTO mac needs to be deleted */
4927 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
4928 && !listcount(zmac
->neigh_list
))
4929 zvni_mac_del(zvni
, zmac
);
4935 * Handle neighbor add or update notification from the kernel (on a VLAN
4936 * device / L3 interface). This is typically for a local neighbor but can
4937 * also be for a remote neighbor (e.g., ageout notification). It could
4938 * also be a "move" scenario.
4940 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
4941 struct interface
*link_if
,
4943 struct ethaddr
*macaddr
,
4945 uint8_t ext_learned
,
4946 uint8_t router_flag
)
4948 char buf
[ETHER_ADDR_STRLEN
];
4949 char buf2
[INET6_ADDRSTRLEN
];
4950 zebra_vni_t
*zvni
= NULL
;
4951 zebra_l3vni_t
*zl3vni
= NULL
;
4953 /* check if this is a remote neigh entry corresponding to remote
4956 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4958 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
4960 /* We are only interested in neighbors on an SVI that resides on top
4961 * of a VxLAN bridge.
4963 zvni
= zvni_from_svi(ifp
, link_if
);
4967 if (IS_ZEBRA_DEBUG_VXLAN
)
4969 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u",
4970 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
4971 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
4972 ifp
->ifindex
, state
, ext_learned
? "ext-learned " : "",
4975 /* Is this about a local neighbor or a remote one? */
4977 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
4980 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
4985 * Handle message from client to delete a remote MACIP for a VNI.
4987 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
4991 struct ethaddr macaddr
;
4993 struct in_addr vtep_ip
;
4997 unsigned short l
= 0, ipa_len
;
4998 char buf
[ETHER_ADDR_STRLEN
];
4999 char buf1
[INET6_ADDRSTRLEN
];
5000 struct interface
*ifp
= NULL
;
5001 struct zebra_if
*zif
= NULL
;
5003 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5004 memset(&ip
, 0, sizeof(struct ipaddr
));
5005 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5009 while (l
< hdr
->length
) {
5010 /* Obtain each remote MACIP and process. */
5011 /* Message contains VNI, followed by MAC followed by IP (if any)
5012 * followed by remote VTEP IP.
5016 memset(&ip
, 0, sizeof(ip
));
5017 STREAM_GETL(s
, vni
);
5018 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5019 STREAM_GETL(s
, ipa_len
);
5021 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5023 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5025 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5026 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5027 l
+= IPV4_MAX_BYTELEN
;
5029 if (IS_ZEBRA_DEBUG_VXLAN
)
5031 "Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
5032 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5033 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5035 zebra_route_string(client
->proto
));
5037 /* Locate VNI hash entry - expected to exist. */
5038 zvni
= zvni_lookup(vni
);
5040 if (IS_ZEBRA_DEBUG_VXLAN
)
5042 "Failed to locate VNI hash upon remote MACIP DEL, "
5047 ifp
= zvni
->vxlan_if
;
5050 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
5056 /* If down or not mapped to a bridge, we're done. */
5057 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5060 /* The remote VTEP specified is normally expected to exist, but
5062 * possible that the peer may delete the VTEP before deleting
5064 * referring to the VTEP, in which case the handler (see
5066 * would have already deleted the MACs.
5068 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5071 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5073 n
= zvni_neigh_lookup(zvni
, &ip
);
5076 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u",
5077 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5078 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5082 /* If the remote mac or neighbor doesn't exist there is nothing
5084 * to do. Otherwise, uninstall the entry and then remove it.
5089 /* Ignore the delete if this mac is a gateway mac-ip */
5090 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5091 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5093 "%u: Ignore Del for MAC %s neigh %s on VNI %u as it is configured as a default gateway",
5095 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5096 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5100 /* Uninstall remote neighbor or MAC. */
5102 /* When the MAC changes for an IP, it is possible the
5104 * update the new MAC before trying to delete the "old"
5106 * (as these are two different MACIP routes). Do the
5108 * if the MAC matches.
5110 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5111 && (memcmp(n
->emac
.octet
, macaddr
.octet
, ETH_ALEN
)
5113 zvni_neigh_uninstall(zvni
, n
);
5114 zvni_neigh_del(zvni
, n
);
5115 zvni_deref_ip2mac(zvni
, mac
, 1);
5118 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5119 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5121 if (list_isempty(mac
->neigh_list
)) {
5122 zvni_mac_uninstall(zvni
, mac
, 0);
5123 zvni_mac_del(zvni
, mac
);
5125 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5135 * Handle message from client to add a remote MACIP for a VNI. This
5136 * could be just the add of a MAC address or the add of a neighbor
5139 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
5143 struct ethaddr macaddr
;
5145 struct in_addr vtep_ip
;
5147 zebra_vtep_t
*zvtep
;
5148 zebra_mac_t
*mac
, *old_mac
;
5150 unsigned short l
= 0, ipa_len
;
5151 int update_mac
= 0, update_neigh
= 0;
5152 char buf
[ETHER_ADDR_STRLEN
];
5153 char buf1
[INET6_ADDRSTRLEN
];
5155 u_char remote_gw
= 0;
5157 struct interface
*ifp
= NULL
;
5158 struct zebra_if
*zif
= NULL
;
5160 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5161 memset(&ip
, 0, sizeof(struct ipaddr
));
5162 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5164 if (!EVPN_ENABLED(zvrf
)) {
5166 "%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
5167 __PRETTY_FUNCTION__
);
5173 while (l
< hdr
->length
) {
5174 /* Obtain each remote MACIP and process. */
5175 /* Message contains VNI, followed by MAC followed by IP (if any)
5176 * followed by remote VTEP IP.
5178 update_mac
= update_neigh
= 0;
5181 memset(&ip
, 0, sizeof(ip
));
5182 STREAM_GETL(s
, vni
);
5183 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5184 STREAM_GETL(s
, ipa_len
);
5186 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5188 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5190 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5191 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5192 l
+= IPV4_MAX_BYTELEN
;
5194 /* Get flags - sticky mac and/or gateway mac */
5195 STREAM_GETC(s
, flags
);
5196 sticky
= CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5197 remote_gw
= CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5200 if (IS_ZEBRA_DEBUG_VXLAN
)
5202 "Recv MACIP Add MAC %s IP %s VNI %u Remote VTEP %s with flags 0x%x from %s",
5203 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5204 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5205 inet_ntoa(vtep_ip
), flags
,
5206 zebra_route_string(client
->proto
));
5208 /* Locate VNI hash entry - expected to exist. */
5209 zvni
= zvni_lookup(vni
);
5212 "Failed to locate VNI hash upon remote MACIP ADD, VNI %u",
5216 ifp
= zvni
->vxlan_if
;
5219 "VNI %u hash %p doesn't have intf upon remote MACIP add",
5225 /* If down or not mapped to a bridge, we're done. */
5226 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5229 /* The remote VTEP specified should normally exist, but it is
5231 * that when peering comes up, peer may advertise MACIP routes
5233 * advertising type-3 routes.
5235 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5237 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5239 ZEBRA_ERR_VTEP_ADD_FAILED
,
5240 "Failed to add remote VTEP, VNI %u zvni %p",
5245 zvni_vtep_install(zvni
, &vtep_ip
);
5248 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5250 /* Ignore the update if the mac is already present
5252 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)
5253 && CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5254 if (IS_ZEBRA_DEBUG_VXLAN
)
5256 "%u:Ignore MAC %s IP %s on VNI %u as MAC is already configured as gateway mac",
5258 prefix_mac2str(&macaddr
, buf
,
5260 ipaddr2str(&ip
, buf1
, sizeof(buf1
)),
5265 /* check if the remote MAC is unknown or has a change.
5266 * If so, that needs to be updated first. Note that client could
5267 * install MAC and MACIP separately or just install the latter.
5269 if (!mac
|| !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5270 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0)
5272 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
) ? 1 : 0)
5274 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
))
5279 mac
= zvni_mac_add(zvni
, &macaddr
);
5282 "Failed to add MAC %s VNI %u Remote VTEP %s",
5283 prefix_mac2str(&macaddr
, buf
,
5285 vni
, inet_ntoa(vtep_ip
));
5289 /* Is this MAC created for a MACIP? */
5291 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5294 /* Set "auto" and "remote" forwarding info. */
5295 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5296 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5297 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5298 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5301 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5303 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5306 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5308 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5310 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5312 /* Install the entry. */
5313 zvni_mac_install(zvni
, mac
);
5316 /* If there is no IP, continue - after clearing AUTO flag of
5319 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5323 /* Check if the remote neighbor itself is unknown or has a
5325 * If so, create or update and then install the entry.
5327 n
= zvni_neigh_lookup(zvni
, &ip
);
5328 if (!n
|| !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5329 || (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
)) != 0)
5330 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
))
5335 n
= zvni_neigh_add(zvni
, &ip
, &macaddr
);
5338 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5339 ipaddr2str(&ip
, buf1
,
5341 prefix_mac2str(&macaddr
, buf
,
5343 vni
, inet_ntoa(vtep_ip
));
5347 } else if (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
))
5349 /* MAC change, update neigh list for old and new
5351 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5353 listnode_delete(old_mac
->neigh_list
, n
);
5354 zvni_deref_ip2mac(zvni
, old_mac
, 1);
5356 listnode_add_sort(mac
->neigh_list
, n
);
5357 memcpy(&n
->emac
, &macaddr
, ETH_ALEN
);
5360 /* Set "remote" forwarding info. */
5361 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5362 /* TODO: Handle MAC change. */
5363 n
->r_vtep_ip
= vtep_ip
;
5364 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5366 /* Set router flag (R-bit) to this Neighbor entry */
5367 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5368 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5370 /* Install the entry. */
5371 zvni_neigh_install(zvni
, n
);
5380 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5381 * us, this must involve a multihoming scenario. Treat this as implicit delete
5382 * of any prior local MAC.
5384 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
5385 struct interface
*br_if
,
5386 struct ethaddr
*macaddr
, vlanid_t vid
)
5388 struct zebra_if
*zif
;
5389 struct zebra_l2info_vxlan
*vxl
;
5393 char buf
[ETHER_ADDR_STRLEN
];
5397 vxl
= &zif
->l2info
.vxl
;
5400 /* Check if EVPN is enabled. */
5401 if (!is_evpn_enabled())
5404 /* Locate hash entry; it is expected to exist. */
5405 zvni
= zvni_lookup(vni
);
5409 /* If entry doesn't exist, nothing to do. */
5410 mac
= zvni_mac_lookup(zvni
, macaddr
);
5414 /* Is it a local entry? */
5415 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5418 if (IS_ZEBRA_DEBUG_VXLAN
)
5420 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5421 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5424 /* Remove MAC from BGP. */
5425 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5428 * If there are no neigh associated with the mac delete the mac
5429 * else mark it as AUTO for forward reference
5431 if (!listcount(mac
->neigh_list
)) {
5432 zvni_mac_del(zvni
, mac
);
5434 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5435 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5442 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5443 * This can happen because the remote MAC entries are also added as "dynamic",
5444 * so the kernel can ageout the entry.
5446 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
5447 struct interface
*br_if
,
5448 struct ethaddr
*macaddr
, vlanid_t vid
)
5450 struct zebra_if
*zif
= NULL
;
5451 struct zebra_l2info_vxlan
*vxl
= NULL
;
5453 zebra_vni_t
*zvni
= NULL
;
5454 zebra_l3vni_t
*zl3vni
= NULL
;
5455 zebra_mac_t
*mac
= NULL
;
5456 char buf
[ETHER_ADDR_STRLEN
];
5460 vxl
= &zif
->l2info
.vxl
;
5463 /* Check if EVPN is enabled. */
5464 if (!is_evpn_enabled())
5467 /* check if this is a remote RMAC and readd simillar to remote macs */
5468 zl3vni
= zl3vni_lookup(vni
);
5470 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
5472 /* Locate hash entry; it is expected to exist. */
5473 zvni
= zvni_lookup(vni
);
5477 /* If entry doesn't exist, nothing to do. */
5478 mac
= zvni_mac_lookup(zvni
, macaddr
);
5482 /* Is it a remote entry? */
5483 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
5486 if (IS_ZEBRA_DEBUG_VXLAN
)
5487 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
5488 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5491 zvni_mac_install(zvni
, mac
);
5496 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
5498 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
5499 struct ethaddr
*macaddr
, vlanid_t vid
)
5503 char buf
[ETHER_ADDR_STRLEN
];
5505 /* We are interested in MACs only on ports or (port, VLAN) that
5508 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5511 if (!zvni
->vxlan_if
) {
5512 zlog_warn("VNI %u hash %p doesn't have intf upon local MAC DEL",
5517 if (IS_ZEBRA_DEBUG_VXLAN
)
5518 zlog_debug("Del MAC %s intf %s(%u) VID %u -> VNI %u",
5519 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5520 ifp
->ifindex
, vid
, zvni
->vni
);
5522 /* If entry doesn't exist, nothing to do. */
5523 mac
= zvni_mac_lookup(zvni
, macaddr
);
5527 /* Is it a local entry? */
5528 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5531 /* Remove MAC from BGP. */
5532 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5534 /* Update all the neigh entries associated with this mac */
5535 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
5538 * If there are no neigh associated with the mac delete the mac
5539 * else mark it as AUTO for forward reference
5541 if (!listcount(mac
->neigh_list
)) {
5542 zvni_mac_del(zvni
, mac
);
5544 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5545 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5552 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
5554 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
5555 struct interface
*br_if
,
5556 struct ethaddr
*macaddr
, vlanid_t vid
,
5561 char buf
[ETHER_ADDR_STRLEN
];
5565 /* We are interested in MACs only on ports or (port, VLAN) that
5568 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5570 if (IS_ZEBRA_DEBUG_VXLAN
)
5572 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5573 sticky
? "sticky " : "",
5574 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5575 ifp
->name
, ifp
->ifindex
, vid
);
5579 if (!zvni
->vxlan_if
) {
5580 zlog_warn("VNI %u hash %p doesn't have intf upon local MAC ADD",
5585 if (IS_ZEBRA_DEBUG_VXLAN
)
5586 zlog_debug("Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
5587 sticky
? "sticky " : "",
5588 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5589 ifp
->ifindex
, vid
, zvni
->vni
);
5591 /* If same entry already exists, nothing to do. */
5592 mac
= zvni_mac_lookup(zvni
, macaddr
);
5594 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5595 mac_sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5601 * return if nothing has changed.
5602 * inform bgp if sticky flag has changed
5603 * update locally and do not inform bgp if local
5604 * parameters like interface has changed
5606 if (mac_sticky
== sticky
5607 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
5608 && mac
->fwd_info
.local
.vid
== vid
) {
5609 if (IS_ZEBRA_DEBUG_VXLAN
)
5611 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
5612 "entry exists and has not changed ",
5613 sticky
? "sticky " : "",
5614 prefix_mac2str(macaddr
, buf
,
5616 ifp
->name
, ifp
->ifindex
, vid
,
5619 } else if (mac_sticky
!= sticky
) {
5622 add
= 0; /* This is an update of local
5625 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5627 * If we have already learned the MAC as a remote sticky
5629 * this is a operator error and we must log a warning
5631 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
5633 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
5634 prefix_mac2str(macaddr
, buf
,
5636 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
5644 mac
= zvni_mac_add(zvni
, macaddr
);
5646 flog_err(ZEBRA_ERR_MAC_ADD_FAILED
,
5647 "Failed to add MAC %s intf %s(%u) VID %u",
5648 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5649 ifp
->name
, ifp
->ifindex
, vid
);
5654 /* Set "local" forwarding info. */
5655 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5656 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5657 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5658 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5659 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
5660 mac
->fwd_info
.local
.vid
= vid
;
5663 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5665 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5667 /* Inform BGP if required. */
5669 zvni_process_neigh_on_local_mac_add(zvni
, mac
);
5670 return zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
5678 * Handle message from client to delete a remote VTEP for a VNI.
5680 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
5683 unsigned short l
= 0;
5685 struct in_addr vtep_ip
;
5687 zebra_vtep_t
*zvtep
;
5688 struct interface
*ifp
;
5689 struct zebra_if
*zif
;
5691 if (!is_evpn_enabled()) {
5693 "%s: EVPN is not enabled yet we have received a vtep del command",
5694 __PRETTY_FUNCTION__
);
5698 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5699 zlog_warn("Recv MACIP DEL for non-default VRF %u",
5706 while (l
< hdr
->length
) {
5707 /* Obtain each remote VTEP and process. */
5708 STREAM_GETL(s
, vni
);
5710 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5711 l
+= IPV4_MAX_BYTELEN
;
5713 if (IS_ZEBRA_DEBUG_VXLAN
)
5714 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
5715 inet_ntoa(vtep_ip
), vni
,
5716 zebra_route_string(client
->proto
));
5718 /* Locate VNI hash entry - expected to exist. */
5719 zvni
= zvni_lookup(vni
);
5721 if (IS_ZEBRA_DEBUG_VXLAN
)
5723 "Failed to locate VNI hash upon remote VTEP DEL, "
5729 ifp
= zvni
->vxlan_if
;
5732 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
5738 /* If down or not mapped to a bridge, we're done. */
5739 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5742 /* If the remote VTEP does not exist, there's nothing more to
5744 * Otherwise, uninstall any remote MACs pointing to this VTEP
5746 * then, the VTEP entry itself and remove it.
5748 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5752 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
5753 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
5754 zvni_vtep_uninstall(zvni
, &vtep_ip
);
5755 zvni_vtep_del(zvni
, zvtep
);
5763 * Handle message from client to add a remote VTEP for a VNI.
5765 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
5768 unsigned short l
= 0;
5770 struct in_addr vtep_ip
;
5772 struct interface
*ifp
;
5773 struct zebra_if
*zif
;
5775 if (!is_evpn_enabled()) {
5777 "%s: EVPN not enabled yet we received a vtep_add zapi call",
5778 __PRETTY_FUNCTION__
);
5782 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5783 zlog_warn("Recv MACIP ADD for non-default VRF %u",
5790 while (l
< hdr
->length
) {
5791 /* Obtain each remote VTEP and process. */
5792 STREAM_GETL(s
, vni
);
5794 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5795 l
+= IPV4_MAX_BYTELEN
;
5797 if (IS_ZEBRA_DEBUG_VXLAN
)
5798 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
5799 inet_ntoa(vtep_ip
), vni
,
5800 zebra_route_string(client
->proto
));
5802 /* Locate VNI hash entry - expected to exist. */
5803 zvni
= zvni_lookup(vni
);
5806 ZEBRA_ERR_VTEP_ADD_FAILED
,
5807 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
5812 ifp
= zvni
->vxlan_if
;
5815 ZEBRA_ERR_VTEP_ADD_FAILED
,
5816 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
5823 /* If down or not mapped to a bridge, we're done. */
5824 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5827 /* If the remote VTEP already exists,
5828 there's nothing more to do. */
5829 if (zvni_vtep_find(zvni
, &vtep_ip
))
5832 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5833 flog_err(ZEBRA_ERR_VTEP_ADD_FAILED
,
5834 "Failed to add remote VTEP, VNI %u zvni %p",
5839 zvni_vtep_install(zvni
, &vtep_ip
);
5847 * Add/Del gateway macip to evpn
5849 * 1. SVI interface on a vlan aware bridge
5850 * 2. SVI interface on a vlan unaware bridge
5851 * 3. vrr interface (MACVLAN) associated to a SVI
5852 * We advertise macip routes for an interface if it is associated to VxLan vlan
5854 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
5858 struct ethaddr macaddr
;
5859 zebra_vni_t
*zvni
= NULL
;
5861 memset(&ip
, 0, sizeof(struct ipaddr
));
5862 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5864 /* Check if EVPN is enabled. */
5865 if (!is_evpn_enabled())
5868 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
5869 struct interface
*svi_if
=
5870 NULL
; /* SVI corresponding to the MACVLAN */
5871 struct zebra_if
*ifp_zif
=
5872 NULL
; /* Zebra daemon specific info for MACVLAN */
5873 struct zebra_if
*svi_if_zif
=
5874 NULL
; /* Zebra daemon specific info for SVI*/
5876 ifp_zif
= ifp
->info
;
5881 * for a MACVLAN interface the link represents the svi_if
5883 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
5884 ifp_zif
->link_ifindex
);
5886 zlog_warn("MACVLAN %s(%u) without link information",
5887 ifp
->name
, ifp
->ifindex
);
5891 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
5893 * If it is a vlan aware bridge then the link gives the
5894 * bridge information
5896 struct interface
*svi_if_link
= NULL
;
5898 svi_if_zif
= svi_if
->info
;
5900 svi_if_link
= if_lookup_by_index_per_ns(
5901 zebra_ns_lookup(NS_DEFAULT
),
5902 svi_if_zif
->link_ifindex
);
5903 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
5905 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
5907 * If it is a vlan unaware bridge then svi is the bridge
5910 zvni
= zvni_from_svi(svi_if
, svi_if
);
5912 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
5913 struct zebra_if
*svi_if_zif
=
5914 NULL
; /* Zebra daemon specific info for SVI */
5915 struct interface
*svi_if_link
=
5916 NULL
; /* link info for the SVI = bridge info */
5918 svi_if_zif
= ifp
->info
;
5920 svi_if_link
= if_lookup_by_index_per_ns(
5921 zebra_ns_lookup(NS_DEFAULT
),
5922 svi_if_zif
->link_ifindex
);
5924 zvni
= zvni_from_svi(ifp
, svi_if_link
);
5926 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
5927 zvni
= zvni_from_svi(ifp
, ifp
);
5933 if (!zvni
->vxlan_if
) {
5934 zlog_warn("VNI %u hash %p doesn't have intf upon MACVLAN up",
5940 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
5942 if (p
->family
== AF_INET
) {
5943 ip
.ipa_type
= IPADDR_V4
;
5944 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
5945 sizeof(struct in_addr
));
5946 } else if (p
->family
== AF_INET6
) {
5947 ip
.ipa_type
= IPADDR_V6
;
5948 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
5949 sizeof(struct in6_addr
));
5954 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
5956 zvni_gw_macip_del(ifp
, zvni
, &ip
);
5962 * Handle SVI interface going down.
5963 * SVI can be associated to either L3-VNI or L2-VNI.
5964 * For L2-VNI: At this point, this is a NOP since
5965 * the kernel deletes the neighbor entries on this SVI (if any).
5966 * We only need to update the vrf corresponding to zvni.
5967 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
5970 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
5972 zebra_l3vni_t
*zl3vni
= NULL
;
5974 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5977 /* process l3-vni down */
5978 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
5980 /* remove association with svi-if */
5981 zl3vni
->svi_if
= NULL
;
5983 zebra_vni_t
*zvni
= NULL
;
5985 /* since we dont have svi corresponding to zvni, we associate it
5986 * to default vrf. Note: the corresponding neigh entries on the
5987 * SVI would have already been deleted */
5988 zvni
= zvni_from_svi(ifp
, link_if
);
5990 zvni
->vrf_id
= VRF_DEFAULT
;
5992 /* update the tenant vrf in BGP */
5993 zvni_send_add_to_client(zvni
);
6000 * Handle SVI interface coming up.
6001 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
6003 * For L2-VNI: we need to install any remote neighbors entried (used for
6005 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
6007 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
6009 zebra_vni_t
*zvni
= NULL
;
6010 zebra_l3vni_t
*zl3vni
= NULL
;
6012 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6015 /* associate with svi */
6016 zl3vni
->svi_if
= ifp
;
6018 /* process oper-up */
6019 if (is_l3vni_oper_up(zl3vni
))
6020 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6023 /* process SVI up for l2-vni */
6024 struct neigh_walk_ctx n_wctx
;
6026 zvni
= zvni_from_svi(ifp
, link_if
);
6030 if (!zvni
->vxlan_if
) {
6032 "VNI %u hash %p doesn't have intf upon SVI up",
6037 if (IS_ZEBRA_DEBUG_VXLAN
)
6039 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
6040 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
6041 vrf_id_to_name(ifp
->vrf_id
));
6043 /* update the vrf information for l2-vni and inform bgp */
6044 zvni
->vrf_id
= ifp
->vrf_id
;
6045 zvni_send_add_to_client(zvni
);
6047 /* Install any remote neighbors for this VNI. */
6048 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6050 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6058 * Handle VxLAN interface down
6060 int zebra_vxlan_if_down(struct interface
*ifp
)
6063 struct zebra_if
*zif
= NULL
;
6064 struct zebra_l2info_vxlan
*vxl
= NULL
;
6065 zebra_l3vni_t
*zl3vni
= NULL
;
6068 /* Check if EVPN is enabled. */
6069 if (!is_evpn_enabled())
6074 vxl
= &zif
->l2info
.vxl
;
6077 zl3vni
= zl3vni_lookup(vni
);
6079 /* process-if-down for l3-vni */
6080 if (IS_ZEBRA_DEBUG_VXLAN
)
6081 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
6084 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6086 /* process if-down for l2-vni */
6087 if (IS_ZEBRA_DEBUG_VXLAN
)
6088 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
6091 /* Locate hash entry; it is expected to exist. */
6092 zvni
= zvni_lookup(vni
);
6095 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
6096 ifp
->name
, ifp
->ifindex
, vni
);
6100 assert(zvni
->vxlan_if
== ifp
);
6102 /* Delete this VNI from BGP. */
6103 zvni_send_del_to_client(zvni
->vni
);
6105 /* Free up all neighbors and MACs, if any. */
6106 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6107 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6109 /* Free up all remote VTEPs, if any. */
6110 zvni_vtep_del_all(zvni
, 1);
6116 * Handle VxLAN interface up - update BGP if required.
6118 int zebra_vxlan_if_up(struct interface
*ifp
)
6121 struct zebra_if
*zif
= NULL
;
6122 struct zebra_l2info_vxlan
*vxl
= NULL
;
6123 zebra_vni_t
*zvni
= NULL
;
6124 zebra_l3vni_t
*zl3vni
= NULL
;
6126 /* Check if EVPN is enabled. */
6127 if (!is_evpn_enabled())
6132 vxl
= &zif
->l2info
.vxl
;
6135 zl3vni
= zl3vni_lookup(vni
);
6138 if (IS_ZEBRA_DEBUG_VXLAN
)
6139 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
6142 /* we need to associate with SVI, if any, we can associate with
6143 * svi-if only after association with vxlan-intf is complete
6145 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6147 if (is_l3vni_oper_up(zl3vni
))
6148 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6150 /* Handle L2-VNI add */
6151 struct interface
*vlan_if
= NULL
;
6153 if (IS_ZEBRA_DEBUG_VXLAN
)
6154 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
6157 /* Locate hash entry; it is expected to exist. */
6158 zvni
= zvni_lookup(vni
);
6161 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
6162 ifp
->name
, ifp
->ifindex
, vni
);
6166 assert(zvni
->vxlan_if
== ifp
);
6167 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6168 zif
->brslave_info
.br_if
);
6170 zvni
->vrf_id
= vlan_if
->vrf_id
;
6171 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6173 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6176 /* If part of a bridge, inform BGP about this VNI. */
6177 /* Also, read and populate local MACs and neighbors. */
6178 if (zif
->brslave_info
.br_if
) {
6179 zvni_send_add_to_client(zvni
);
6180 zvni_read_mac_neigh(zvni
, ifp
);
6188 * Handle VxLAN interface delete. Locate and remove entry in hash table
6189 * and update BGP, if required.
6191 int zebra_vxlan_if_del(struct interface
*ifp
)
6194 struct zebra_if
*zif
= NULL
;
6195 struct zebra_l2info_vxlan
*vxl
= NULL
;
6196 zebra_vni_t
*zvni
= NULL
;
6197 zebra_l3vni_t
*zl3vni
= NULL
;
6199 /* Check if EVPN is enabled. */
6200 if (!is_evpn_enabled())
6205 vxl
= &zif
->l2info
.vxl
;
6208 zl3vni
= zl3vni_lookup(vni
);
6211 if (IS_ZEBRA_DEBUG_VXLAN
)
6212 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
6215 /* process oper-down for l3-vni */
6216 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6218 /* remove the association with vxlan_if */
6219 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
6220 zl3vni
->vxlan_if
= NULL
;
6223 /* process if-del for l2-vni*/
6224 if (IS_ZEBRA_DEBUG_VXLAN
)
6225 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
6228 /* Locate hash entry; it is expected to exist. */
6229 zvni
= zvni_lookup(vni
);
6232 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6233 ifp
->name
, ifp
->ifindex
, vni
);
6237 /* remove from l3-vni list */
6238 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
6240 listnode_delete(zl3vni
->l2vnis
, zvni
);
6242 /* Delete VNI from BGP. */
6243 zvni_send_del_to_client(zvni
->vni
);
6245 /* Free up all neighbors and MAC, if any. */
6246 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
6247 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
6249 /* Free up all remote VTEPs, if any. */
6250 zvni_vtep_del_all(zvni
, 0);
6252 /* Delete the hash entry. */
6253 if (zvni_del(zvni
)) {
6254 flog_err(ZEBRA_ERR_VNI_DEL_FAILED
,
6255 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
6256 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
6264 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6266 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
6269 struct zebra_if
*zif
= NULL
;
6270 struct zebra_l2info_vxlan
*vxl
= NULL
;
6271 zebra_vni_t
*zvni
= NULL
;
6272 zebra_l3vni_t
*zl3vni
= NULL
;
6274 /* Check if EVPN is enabled. */
6275 if (!is_evpn_enabled())
6280 vxl
= &zif
->l2info
.vxl
;
6283 zl3vni
= zl3vni_lookup(vni
);
6286 if (IS_ZEBRA_DEBUG_VXLAN
)
6288 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6289 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6290 inet_ntoa(vxl
->vtep_ip
),
6291 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6293 /* Removed from bridge? Cleanup and return */
6294 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6295 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6296 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6300 /* access-vlan change - process oper down, associate with new
6301 * svi_if and then process oper up again
6303 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6304 if (if_is_operative(ifp
)) {
6305 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6306 zl3vni
->svi_if
= NULL
;
6307 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6308 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6309 if (is_l3vni_oper_up(zl3vni
))
6310 zebra_vxlan_process_l3vni_oper_up(
6316 * local-ip change - process oper down, associate with new
6317 * local-ip and then process oper up again
6319 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
6320 if (if_is_operative(ifp
)) {
6321 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6322 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6323 if (is_l3vni_oper_up(zl3vni
))
6324 zebra_vxlan_process_l3vni_oper_up(
6329 /* Update local tunnel IP. */
6330 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6332 /* if we have a valid new master, process l3-vni oper up */
6333 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
6334 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
6335 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6339 /* Update VNI hash. */
6340 zvni
= zvni_lookup(vni
);
6343 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6344 ifp
->name
, ifp
->ifindex
, vni
);
6348 if (IS_ZEBRA_DEBUG_VXLAN
)
6350 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6351 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6352 inet_ntoa(vxl
->vtep_ip
),
6353 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6355 /* Removed from bridge? Cleanup and return */
6356 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6357 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6358 /* Delete from client, remove all remote VTEPs */
6359 /* Also, free up all MACs and neighbors. */
6360 zvni_send_del_to_client(zvni
->vni
);
6361 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6362 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6363 zvni_vtep_del_all(zvni
, 1);
6367 /* Handle other changes. */
6368 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6369 /* Remove all existing local neigh and MACs for this VNI
6370 * (including from BGP)
6372 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6373 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6376 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6377 zvni
->vxlan_if
= ifp
;
6379 /* Take further actions needed.
6380 * Note that if we are here, there is a change of interest.
6382 /* If down or not mapped to a bridge, we're done. */
6383 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6386 /* Inform BGP, if there is a change of interest. */
6388 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
6389 zvni_send_add_to_client(zvni
);
6391 /* If there is a valid new master or a VLAN mapping change,
6392 * read and populate local MACs and neighbors.
6393 * Also, reinstall any remote MACs and neighbors
6394 * for this VNI (based on new VLAN).
6396 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6397 zvni_read_mac_neigh(zvni
, ifp
);
6398 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6399 struct mac_walk_ctx m_wctx
;
6400 struct neigh_walk_ctx n_wctx
;
6402 zvni_read_mac_neigh(zvni
, ifp
);
6404 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6406 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
6409 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6411 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6420 * Handle VxLAN interface add.
6422 int zebra_vxlan_if_add(struct interface
*ifp
)
6425 struct zebra_if
*zif
= NULL
;
6426 struct zebra_l2info_vxlan
*vxl
= NULL
;
6427 zebra_vni_t
*zvni
= NULL
;
6428 zebra_l3vni_t
*zl3vni
= NULL
;
6430 /* Check if EVPN is enabled. */
6431 if (!is_evpn_enabled())
6436 vxl
= &zif
->l2info
.vxl
;
6439 zl3vni
= zl3vni_lookup(vni
);
6442 /* process if-add for l3-vni*/
6443 if (IS_ZEBRA_DEBUG_VXLAN
)
6445 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6446 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6447 inet_ntoa(vxl
->vtep_ip
),
6448 zif
->brslave_info
.bridge_ifindex
);
6450 /* associate with vxlan_if */
6451 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6452 zl3vni
->vxlan_if
= ifp
;
6454 /* Associate with SVI, if any. We can associate with svi-if only
6455 * after association with vxlan_if is complete */
6456 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6458 if (is_l3vni_oper_up(zl3vni
))
6459 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6462 /* process if-add for l2-vni */
6463 struct interface
*vlan_if
= NULL
;
6465 /* Create or update VNI hash. */
6466 zvni
= zvni_lookup(vni
);
6468 zvni
= zvni_add(vni
);
6471 ZEBRA_ERR_VNI_ADD_FAILED
,
6472 "Failed to add VNI hash, IF %s(%u) VNI %u",
6473 ifp
->name
, ifp
->ifindex
, vni
);
6478 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6479 zvni
->vxlan_if
= ifp
;
6480 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6481 zif
->brslave_info
.br_if
);
6483 zvni
->vrf_id
= vlan_if
->vrf_id
;
6484 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6486 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6489 if (IS_ZEBRA_DEBUG_VXLAN
)
6491 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6493 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
6495 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6496 inet_ntoa(vxl
->vtep_ip
),
6497 zif
->brslave_info
.bridge_ifindex
);
6499 /* If down or not mapped to a bridge, we're done. */
6500 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6504 zvni_send_add_to_client(zvni
);
6506 /* Read and populate local MACs and neighbors */
6507 zvni_read_mac_neigh(zvni
, ifp
);
6513 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
6514 char *err
, int err_str_sz
, int filter
,
6517 zebra_l3vni_t
*zl3vni
= NULL
;
6518 struct zebra_vrf
*zvrf_default
= NULL
;
6520 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
6524 if (IS_ZEBRA_DEBUG_VXLAN
)
6525 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
6526 add
? "ADD" : "DEL");
6530 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6532 /* check if the vni is already present under zvrf */
6534 snprintf(err
, err_str_sz
,
6535 "VNI is already configured under the vrf");
6539 /* check if this VNI is already present in the system */
6540 zl3vni
= zl3vni_lookup(vni
);
6542 snprintf(err
, err_str_sz
,
6543 "VNI is already configured as L3-VNI");
6547 /* add the L3-VNI to the global table */
6548 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
6550 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
6554 /* associate the vrf with vni */
6557 /* set the filter in l3vni to denote if we are using l3vni only
6561 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
6563 /* associate with vxlan-intf;
6564 * we need to associate with the vxlan-intf first
6566 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
6568 /* associate with corresponding SVI interface, we can associate
6569 * with svi-if only after vxlan interface association is
6572 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6574 /* formulate l2vni list */
6575 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
6578 if (is_l3vni_oper_up(zl3vni
))
6579 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6582 zl3vni
= zl3vni_lookup(vni
);
6584 snprintf(err
, err_str_sz
, "VNI doesn't exist");
6588 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
6589 snprintf(err
, ERR_STR_SZ
,
6590 "prefix-routes-only is not set for the vni");
6594 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6596 /* delete and uninstall all rmacs */
6597 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
6600 /* delete and uninstall all next-hops */
6601 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
6607 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6612 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
6614 zebra_l3vni_t
*zl3vni
= NULL
;
6617 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6621 zl3vni
->vrf_id
= zvrf_id(zvrf
);
6622 if (is_l3vni_oper_up(zl3vni
))
6623 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6627 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
6629 zebra_l3vni_t
*zl3vni
= NULL
;
6632 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6636 zl3vni
->vrf_id
= VRF_UNKNOWN
;
6637 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6641 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
6643 zebra_l3vni_t
*zl3vni
= NULL
;
6647 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6653 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
6659 * Handle message from client to enable/disable advertisement of g/w macip
6662 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
6667 zebra_vni_t
*zvni
= NULL
;
6668 struct interface
*ifp
= NULL
;
6669 struct zebra_if
*zif
= NULL
;
6670 struct zebra_l2info_vxlan zl2_info
;
6671 struct interface
*vlan_if
= NULL
;
6673 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6674 zlog_warn("EVPN GW-MACIP Adv for non-default VRF %u",
6680 STREAM_GETC(s
, advertise
);
6681 vni
= stream_get3(s
);
6683 zvni
= zvni_lookup(vni
);
6687 if (zvni
->advertise_subnet
== advertise
)
6690 if (IS_ZEBRA_DEBUG_VXLAN
)
6691 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
6692 advertise
? "enabled" : "disabled", vni
,
6693 zvni
->advertise_subnet
? "enabled" : "disabled");
6696 zvni
->advertise_subnet
= advertise
;
6698 ifp
= zvni
->vxlan_if
;
6704 /* If down or not mapped to a bridge, we're done. */
6705 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6708 zl2_info
= zif
->l2info
.vxl
;
6711 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
6715 if (zvni
->advertise_subnet
)
6716 zvni_advertise_subnet(zvni
, vlan_if
, 1);
6718 zvni_advertise_subnet(zvni
, vlan_if
, 0);
6725 * Handle message from client to enable/disable advertisement of g/w macip
6728 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
6733 zebra_vni_t
*zvni
= NULL
;
6734 struct interface
*ifp
= NULL
;
6736 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6737 zlog_warn("EVPN GW-MACIP Adv for non-default VRF %u",
6743 STREAM_GETC(s
, advertise
);
6744 STREAM_GETL(s
, vni
);
6747 if (IS_ZEBRA_DEBUG_VXLAN
)
6748 zlog_debug("EVPN gateway macip Adv %s, currently %s",
6749 advertise
? "enabled" : "disabled",
6750 advertise_gw_macip_enabled(NULL
)
6754 if (zvrf
->advertise_gw_macip
== advertise
)
6757 zvrf
->advertise_gw_macip
= advertise
;
6759 if (advertise_gw_macip_enabled(zvni
))
6760 hash_iterate(zvrf
->vni_table
,
6761 zvni_gw_macip_add_for_vni_hash
, NULL
);
6763 hash_iterate(zvrf
->vni_table
,
6764 zvni_gw_macip_del_for_vni_hash
, NULL
);
6767 struct zebra_if
*zif
= NULL
;
6768 struct zebra_l2info_vxlan zl2_info
;
6769 struct interface
*vlan_if
= NULL
;
6770 struct interface
*vrr_if
= NULL
;
6772 zvni
= zvni_lookup(vni
);
6776 if (IS_ZEBRA_DEBUG_VXLAN
)
6778 "EVPN gateway macip Adv %s on VNI %d , currently %s",
6779 advertise
? "enabled" : "disabled", vni
,
6780 advertise_gw_macip_enabled(zvni
) ? "enabled"
6783 if (zvni
->advertise_gw_macip
== advertise
)
6786 zvni
->advertise_gw_macip
= advertise
;
6788 ifp
= zvni
->vxlan_if
;
6794 /* If down or not mapped to a bridge, we're done. */
6795 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6798 zl2_info
= zif
->l2info
.vxl
;
6800 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
6801 zif
->brslave_info
.br_if
);
6805 if (advertise_gw_macip_enabled(zvni
)) {
6806 /* Add primary SVI MAC-IP */
6807 zvni_add_macip_for_intf(vlan_if
, zvni
);
6809 /* Add VRR MAC-IP - if any*/
6810 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6812 zvni_add_macip_for_intf(vrr_if
, zvni
);
6814 /* Del primary MAC-IP */
6815 zvni_del_macip_for_intf(vlan_if
, zvni
);
6817 /* Del VRR MAC-IP - if any*/
6818 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6820 zvni_del_macip_for_intf(vrr_if
, zvni
);
6830 * Handle message from client to learn (or stop learning) about VNIs and MACs.
6831 * When enabled, the VNI hash table will be built and MAC FDB table read;
6832 * when disabled, the entries should be deleted and remote VTEPs and MACs
6833 * uninstalled from the kernel.
6835 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
6837 struct stream
*s
= NULL
;
6839 struct zebra_ns
*zns
= NULL
;
6841 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6842 zlog_warn("EVPN VNI Adv for non-default VRF %u", zvrf_id(zvrf
));
6847 STREAM_GETC(s
, advertise
);
6849 if (IS_ZEBRA_DEBUG_VXLAN
)
6850 zlog_debug("EVPN VNI Adv %s, currently %s",
6851 advertise
? "enabled" : "disabled",
6852 is_evpn_enabled() ? "enabled" : "disabled");
6854 if (zvrf
->advertise_all_vni
== advertise
)
6857 zvrf
->advertise_all_vni
= advertise
;
6858 if (is_evpn_enabled()) {
6859 /* Build VNI hash table and inform BGP. */
6860 zvni_build_hash_table();
6862 /* Add all SVI (L3 GW) MACs to BGP*/
6863 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
6866 /* Read the MAC FDB */
6867 macfdb_read(zvrf
->zns
);
6869 /* Read neighbors */
6870 neigh_read(zvrf
->zns
);
6872 /* Cleanup VTEPs for all VNIs - uninstall from
6873 * kernel and free entries.
6875 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6877 /* cleanup all l3vnis */
6878 zns
= zebra_ns_lookup(NS_DEFAULT
);
6882 hash_iterate(zns
->l3vni_table
, zl3vni_cleanup_all
, NULL
);
6890 * Allocate VNI hash table for this VRF and do other initialization.
6891 * NOTE: Currently supported only for default VRF.
6893 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
6897 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
6898 "Zebra VRF VNI Table");
6901 /* Cleanup VNI info, but don't free the table. */
6902 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
6906 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6909 /* Close all VNI handling */
6910 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
6914 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6915 hash_free(zvrf
->vni_table
);
6918 /* init the l3vni table */
6919 void zebra_vxlan_ns_init(struct zebra_ns
*zns
)
6921 zns
->l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
6922 "Zebra VRF L3 VNI table");
6925 /* free l3vni table */
6926 void zebra_vxlan_ns_disable(struct zebra_ns
*zns
)
6928 hash_free(zns
->l3vni_table
);
6931 /* get the l3vni svi ifindex */
6932 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
6934 zebra_l3vni_t
*zl3vni
= NULL
;
6936 zl3vni
= zl3vni_from_vrf(vrf_id
);
6937 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
6940 return zl3vni
->svi_if
->ifindex
;