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
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
)),
2077 /*Set router flag (R-bit) */
2079 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2082 if (IS_ZEBRA_DEBUG_VXLAN
)
2083 zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u with flags 0x%x",
2084 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2085 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2086 zvni
->vni
, n
->flags
);
2087 ZEBRA_NEIGH_SET_ACTIVE(n
);
2089 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, n
->flags
);
2092 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
2093 struct interface
*ifp
,
2095 struct ethaddr
*macaddr
,
2098 char buf
[ETHER_ADDR_STRLEN
];
2099 char buf2
[INET6_ADDRSTRLEN
];
2100 zebra_neigh_t
*n
= NULL
;
2101 zebra_mac_t
*zmac
= NULL
;
2103 /* If the neighbor is unknown, there is no further action. */
2104 n
= zvni_neigh_lookup(zvni
, ip
);
2108 /* If a remote entry, see if it needs to be refreshed */
2109 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2111 if (state
& NUD_STALE
)
2112 zvni_neigh_install(zvni
, n
);
2115 /* We got a "remote" neighbor notification for an entry
2116 * we think is local. This can happen in a multihoming
2117 * scenario - but only if the MAC is already "remote".
2118 * Just mark our entry as "remote".
2120 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2121 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2123 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
2124 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
2125 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2130 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2131 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2132 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
2139 * Make hash key for MAC.
2141 static unsigned int mac_hash_keymake(void *p
)
2143 zebra_mac_t
*pmac
= p
;
2144 const void *pnt
= (void *)pmac
->macaddr
.octet
;
2146 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
2150 * Compare two MAC addresses.
2152 static int mac_cmp(const void *p1
, const void *p2
)
2154 const zebra_mac_t
*pmac1
= p1
;
2155 const zebra_mac_t
*pmac2
= p2
;
2157 if (pmac1
== NULL
&& pmac2
== NULL
)
2160 if (pmac1
== NULL
|| pmac2
== NULL
)
2163 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
2168 * Callback to allocate MAC hash entry.
2170 static void *zvni_mac_alloc(void *p
)
2172 const zebra_mac_t
*tmp_mac
= p
;
2175 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2178 return ((void *)mac
);
2184 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
2186 zebra_mac_t tmp_mac
;
2187 zebra_mac_t
*mac
= NULL
;
2189 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
2190 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
2191 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
2194 mac
->neigh_list
= list_new();
2195 mac
->neigh_list
->cmp
= (int (*)(void *, void *))neigh_cmp
;
2203 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2205 zebra_mac_t
*tmp_mac
;
2207 list_delete_and_null(&mac
->neigh_list
);
2209 /* Free the VNI hash entry and allocated memory. */
2210 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
2212 XFREE(MTYPE_MAC
, tmp_mac
);
2218 * Free MAC hash entry (callback)
2220 static void zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2222 struct mac_walk_ctx
*wctx
= arg
;
2223 zebra_mac_t
*mac
= backet
->data
;
2225 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
2226 || ((wctx
->flags
& DEL_REMOTE_MAC
)
2227 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
2228 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
2229 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
2230 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
2231 &wctx
->r_vtep_ip
))) {
2232 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
2233 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
2234 &mac
->macaddr
, mac
->flags
);
2237 if (wctx
->uninstall
)
2238 zvni_mac_uninstall(wctx
->zvni
, mac
, 0);
2240 zvni_mac_del(wctx
->zvni
, mac
);
2247 * Delete all MAC entries from specific VTEP for a particular VNI.
2249 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2250 struct in_addr
*r_vtep_ip
)
2252 struct mac_walk_ctx wctx
;
2254 if (!zvni
->mac_table
)
2257 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2259 wctx
.uninstall
= uninstall
;
2260 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
2261 wctx
.r_vtep_ip
= *r_vtep_ip
;
2263 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2267 * Delete all MAC entries for this VNI.
2269 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2272 struct mac_walk_ctx wctx
;
2274 if (!zvni
->mac_table
)
2277 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2279 wctx
.uninstall
= uninstall
;
2280 wctx
.upd_client
= upd_client
;
2283 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2287 * Look up MAC hash entry.
2289 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
2294 memset(&tmp
, 0, sizeof(tmp
));
2295 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
2296 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
2302 * Inform BGP about local MAC addition.
2304 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2309 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2310 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2311 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2312 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2314 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2319 * Inform BGP about local MAC deletion.
2321 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2326 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2327 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2328 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2329 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2331 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2336 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2337 * notifications, to see if they are of interest.
2339 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
2340 struct interface
*br_if
, vlanid_t vid
)
2342 struct zebra_ns
*zns
;
2343 struct route_node
*rn
;
2344 struct interface
*tmp_if
= NULL
;
2345 struct zebra_if
*zif
;
2346 struct zebra_l2info_bridge
*br
;
2347 struct zebra_l2info_vxlan
*vxl
= NULL
;
2348 uint8_t bridge_vlan_aware
;
2352 /* Determine if bridge is VLAN-aware or not */
2355 br
= &zif
->l2info
.br
;
2356 bridge_vlan_aware
= br
->vlan_aware
;
2358 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2359 /* TODO: Optimize with a hash. */
2360 zns
= zebra_ns_lookup(NS_DEFAULT
);
2361 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2362 tmp_if
= (struct interface
*)rn
->info
;
2366 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2368 if (!if_is_operative(tmp_if
))
2370 vxl
= &zif
->l2info
.vxl
;
2372 if (zif
->brslave_info
.br_if
!= br_if
)
2375 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2384 zvni
= zvni_lookup(vxl
->vni
);
2389 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2390 * neighbor notifications, to see if they are of interest.
2392 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
2393 struct interface
*br_if
)
2395 struct zebra_ns
*zns
;
2396 struct route_node
*rn
;
2397 struct interface
*tmp_if
= NULL
;
2398 struct zebra_if
*zif
;
2399 struct zebra_l2info_bridge
*br
;
2400 struct zebra_l2info_vxlan
*vxl
= NULL
;
2401 uint8_t bridge_vlan_aware
;
2409 /* Make sure the linked interface is a bridge. */
2410 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
2413 /* Determine if bridge is VLAN-aware or not */
2416 br
= &zif
->l2info
.br
;
2417 bridge_vlan_aware
= br
->vlan_aware
;
2418 if (bridge_vlan_aware
) {
2419 struct zebra_l2info_vlan
*vl
;
2421 if (!IS_ZEBRA_IF_VLAN(ifp
))
2426 vl
= &zif
->l2info
.vl
;
2430 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2431 /* TODO: Optimize with a hash. */
2432 zns
= zebra_ns_lookup(NS_DEFAULT
);
2433 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2434 tmp_if
= (struct interface
*)rn
->info
;
2438 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2440 if (!if_is_operative(tmp_if
))
2442 vxl
= &zif
->l2info
.vxl
;
2444 if (zif
->brslave_info
.br_if
!= br_if
)
2447 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2456 zvni
= zvni_lookup(vxl
->vni
);
2460 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
2462 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
2463 * linked to the bridge
2464 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
2467 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
2469 struct zebra_ns
*zns
;
2470 struct route_node
*rn
;
2471 struct interface
*tmp_if
= NULL
;
2472 struct zebra_if
*zif
;
2473 struct zebra_l2info_bridge
*br
;
2474 struct zebra_l2info_vlan
*vl
;
2475 uint8_t bridge_vlan_aware
;
2478 /* Defensive check, caller expected to invoke only with valid bridge. */
2482 /* Determine if bridge is VLAN-aware or not */
2485 br
= &zif
->l2info
.br
;
2486 bridge_vlan_aware
= br
->vlan_aware
;
2488 /* Check oper status of the SVI. */
2489 if (!bridge_vlan_aware
)
2490 return if_is_operative(br_if
) ? br_if
: NULL
;
2492 /* Identify corresponding VLAN interface. */
2493 /* TODO: Optimize with a hash. */
2494 zns
= zebra_ns_lookup(NS_DEFAULT
);
2495 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2496 tmp_if
= (struct interface
*)rn
->info
;
2497 /* Check oper status of the SVI. */
2498 if (!tmp_if
|| !if_is_operative(tmp_if
))
2501 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
2502 || zif
->link
!= br_if
)
2504 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
2506 if (vl
->vid
== vid
) {
2512 return found
? tmp_if
: NULL
;
2516 * Install remote MAC into the kernel.
2518 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2520 struct zebra_if
*zif
;
2521 struct zebra_l2info_vxlan
*vxl
;
2524 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2527 zif
= zvni
->vxlan_if
->info
;
2530 vxl
= &zif
->l2info
.vxl
;
2532 sticky
= CHECK_FLAG(mac
->flags
,
2533 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
)) ? 1 : 0;
2535 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
2536 mac
->fwd_info
.r_vtep_ip
, sticky
);
2540 * Uninstall remote MAC from the kernel. In the scenario where the MAC
2541 * moves to remote, we have to uninstall any existing local entry first.
2543 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
)
2545 struct zebra_if
*zif
;
2546 struct zebra_l2info_vxlan
*vxl
;
2547 struct in_addr vtep_ip
= {.s_addr
= 0};
2548 struct zebra_ns
*zns
;
2549 struct interface
*ifp
;
2551 if (!local
&& !(mac
->flags
& ZEBRA_MAC_REMOTE
))
2554 if (!zvni
->vxlan_if
) {
2555 zlog_warn("VNI %u hash %p couldn't be uninstalled - no intf",
2560 zif
= zvni
->vxlan_if
->info
;
2563 vxl
= &zif
->l2info
.vxl
;
2566 zns
= zebra_ns_lookup(NS_DEFAULT
);
2567 ifp
= if_lookup_by_index_per_ns(zns
,
2568 mac
->fwd_info
.local
.ifindex
);
2569 if (!ifp
) // unexpected
2572 ifp
= zvni
->vxlan_if
;
2573 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
2576 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
,
2581 * Install MAC hash entry - called upon access VLAN change.
2583 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
2586 struct mac_walk_ctx
*wctx
= ctxt
;
2588 mac
= (zebra_mac_t
*)backet
->data
;
2590 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
2591 zvni_mac_install(wctx
->zvni
, mac
);
2595 * Decrement neighbor refcount of MAC; uninstall and free it if
2598 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
2601 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)
2602 || !list_isempty(mac
->neigh_list
))
2606 zvni_mac_uninstall(zvni
, mac
, 0);
2608 zvni_mac_del(zvni
, mac
);
2612 * Read and populate local MACs and neighbors corresponding to this VNI.
2614 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
2616 struct zebra_ns
*zns
;
2617 struct zebra_if
*zif
;
2618 struct interface
*vlan_if
;
2619 struct zebra_l2info_vxlan
*vxl
;
2620 struct interface
*vrr_if
;
2623 vxl
= &zif
->l2info
.vxl
;
2624 zns
= zebra_ns_lookup(NS_DEFAULT
);
2626 if (IS_ZEBRA_DEBUG_VXLAN
)
2628 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2629 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2630 zif
->brslave_info
.bridge_ifindex
);
2632 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
2633 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2636 /* Add SVI MAC-IP */
2637 zvni_add_macip_for_intf(vlan_if
, zvni
);
2639 /* Add VRR MAC-IP - if any*/
2640 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2642 zvni_add_macip_for_intf(vrr_if
, zvni
);
2644 neigh_read_for_vlan(zns
, vlan_if
);
2649 * Hash function for VNI.
2651 static unsigned int vni_hash_keymake(void *p
)
2653 const zebra_vni_t
*zvni
= p
;
2655 return (jhash_1word(zvni
->vni
, 0));
2659 * Compare 2 VNI hash entries.
2661 static int vni_hash_cmp(const void *p1
, const void *p2
)
2663 const zebra_vni_t
*zvni1
= p1
;
2664 const zebra_vni_t
*zvni2
= p2
;
2666 return (zvni1
->vni
== zvni2
->vni
);
2670 * Callback to allocate VNI hash entry.
2672 static void *zvni_alloc(void *p
)
2674 const zebra_vni_t
*tmp_vni
= p
;
2677 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
2678 zvni
->vni
= tmp_vni
->vni
;
2679 return ((void *)zvni
);
2683 * Look up VNI hash entry.
2685 static zebra_vni_t
*zvni_lookup(vni_t vni
)
2687 struct zebra_vrf
*zvrf
;
2688 zebra_vni_t tmp_vni
;
2689 zebra_vni_t
*zvni
= NULL
;
2691 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2693 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
2695 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
2701 * Add VNI hash entry.
2703 static zebra_vni_t
*zvni_add(vni_t vni
)
2705 struct zebra_vrf
*zvrf
;
2706 zebra_vni_t tmp_zvni
;
2707 zebra_vni_t
*zvni
= NULL
;
2709 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2711 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
2713 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
2716 /* Create hash table for MAC */
2718 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
2720 /* Create hash table for neighbors */
2721 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
2722 "Zebra VNI Neighbor Table");
2728 * Delete VNI hash entry.
2730 static int zvni_del(zebra_vni_t
*zvni
)
2732 struct zebra_vrf
*zvrf
;
2733 zebra_vni_t
*tmp_zvni
;
2735 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2738 zvni
->vxlan_if
= NULL
;
2740 /* Free the neighbor hash table. */
2741 hash_free(zvni
->neigh_table
);
2742 zvni
->neigh_table
= NULL
;
2744 /* Free the MAC hash table. */
2745 hash_free(zvni
->mac_table
);
2746 zvni
->mac_table
= NULL
;
2748 /* Free the VNI hash entry and allocated memory. */
2749 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
2751 XFREE(MTYPE_ZVNI
, tmp_zvni
);
2757 * Inform BGP about local VNI addition.
2759 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
2761 struct zserv
*client
;
2764 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2765 /* BGP may not be running. */
2769 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2771 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
2772 stream_putl(s
, zvni
->vni
);
2773 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
2774 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
2776 /* Write packet size. */
2777 stream_putw_at(s
, 0, stream_get_endp(s
));
2779 if (IS_ZEBRA_DEBUG_VXLAN
)
2780 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
2781 inet_ntoa(zvni
->local_vtep_ip
),
2782 vrf_id_to_name(zvni
->vrf_id
),
2783 zebra_route_string(client
->proto
));
2785 client
->vniadd_cnt
++;
2786 return zserv_send_message(client
, s
);
2790 * Inform BGP about local VNI deletion.
2792 static int zvni_send_del_to_client(vni_t vni
)
2794 struct zserv
*client
;
2797 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2798 /* BGP may not be running. */
2802 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2805 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
2806 stream_putl(s
, vni
);
2808 /* Write packet size. */
2809 stream_putw_at(s
, 0, stream_get_endp(s
));
2811 if (IS_ZEBRA_DEBUG_VXLAN
)
2812 zlog_debug("Send VNI_DEL %u to %s", vni
,
2813 zebra_route_string(client
->proto
));
2815 client
->vnidel_cnt
++;
2816 return zserv_send_message(client
, s
);
2820 * Build the VNI hash table by going over the VxLAN interfaces. This
2821 * is called when EVPN (advertise-all-vni) is enabled.
2823 static void zvni_build_hash_table()
2825 struct zebra_ns
*zns
;
2826 struct route_node
*rn
;
2827 struct interface
*ifp
;
2829 /* Walk VxLAN interfaces and create VNI hash. */
2830 zns
= zebra_ns_lookup(NS_DEFAULT
);
2831 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2833 zebra_vni_t
*zvni
= NULL
;
2834 zebra_l3vni_t
*zl3vni
= NULL
;
2835 struct zebra_if
*zif
;
2836 struct zebra_l2info_vxlan
*vxl
;
2838 ifp
= (struct interface
*)rn
->info
;
2842 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2845 vxl
= &zif
->l2info
.vxl
;
2848 /* L3-VNI and L2-VNI are handled seperately */
2849 zl3vni
= zl3vni_lookup(vni
);
2852 if (IS_ZEBRA_DEBUG_VXLAN
)
2854 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
2855 ifp
->name
, ifp
->ifindex
, vni
);
2857 /* associate with vxlan_if */
2858 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
2859 zl3vni
->vxlan_if
= ifp
;
2862 * we need to associate with SVI.
2863 * we can associate with svi-if only after association
2864 * with vxlan-intf is complete
2866 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
2868 if (is_l3vni_oper_up(zl3vni
))
2869 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
2872 struct interface
*vlan_if
= NULL
;
2874 if (IS_ZEBRA_DEBUG_VXLAN
)
2876 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
2877 ifp
->name
, ifp
->ifindex
, vni
,
2878 inet_ntoa(vxl
->vtep_ip
));
2880 /* VNI hash entry is not expected to exist. */
2881 zvni
= zvni_lookup(vni
);
2884 "VNI hash already present for IF %s(%u) L2-VNI %u",
2885 ifp
->name
, ifp
->ifindex
, vni
);
2889 zvni
= zvni_add(vni
);
2892 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
2893 ifp
->name
, ifp
->ifindex
, vni
);
2897 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
2898 zvni
->vxlan_if
= ifp
;
2899 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
2900 zif
->brslave_info
.br_if
);
2902 zvni
->vrf_id
= vlan_if
->vrf_id
;
2903 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
2905 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
2909 /* Inform BGP if intf is up and mapped to bridge. */
2910 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
2911 zvni_send_add_to_client(zvni
);
2917 * See if remote VTEP matches with prefix.
2919 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
2921 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
2925 * Locate remote VTEP in VNI hash table.
2927 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2929 zebra_vtep_t
*zvtep
;
2934 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2935 if (zvni_vtep_match(vtep_ip
, zvtep
))
2943 * Add remote VTEP to VNI hash table.
2945 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2947 zebra_vtep_t
*zvtep
;
2949 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
2951 zvtep
->vtep_ip
= *vtep_ip
;
2954 zvni
->vteps
->prev
= zvtep
;
2955 zvtep
->next
= zvni
->vteps
;
2956 zvni
->vteps
= zvtep
;
2962 * Remove remote VTEP from VNI hash table.
2964 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
2967 zvtep
->next
->prev
= zvtep
->prev
;
2969 zvtep
->prev
->next
= zvtep
->next
;
2971 zvni
->vteps
= zvtep
->next
;
2973 zvtep
->prev
= zvtep
->next
= NULL
;
2974 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
2980 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
2981 * uninstall from kernel if asked to.
2983 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
2985 zebra_vtep_t
*zvtep
, *zvtep_next
;
2990 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
2991 zvtep_next
= zvtep
->next
;
2993 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
2994 zvni_vtep_del(zvni
, zvtep
);
3001 * Install remote VTEP into the kernel.
3003 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3005 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3009 * Uninstall remote VTEP from the kernel.
3011 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3013 if (!zvni
->vxlan_if
) {
3014 zlog_warn("VNI %u hash %p couldn't be uninstalled - no intf",
3019 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3023 * Cleanup VNI/VTEP and update kernel
3025 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
3027 zebra_vni_t
*zvni
= NULL
;
3028 zebra_l3vni_t
*zl3vni
= NULL
;
3029 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
3031 zvni
= (zebra_vni_t
*)backet
->data
;
3033 /* remove from l3-vni list */
3035 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
3037 listnode_delete(zl3vni
->l2vnis
, zvni
);
3039 /* Free up all neighbors and MACs, if any. */
3040 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
3041 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
3043 /* Free up all remote VTEPs, if any. */
3044 zvni_vtep_del_all(zvni
, 1);
3046 /* Delete the hash entry. */
3051 static void zl3vni_cleanup_all(struct hash_backet
*backet
, void *args
)
3053 zebra_l3vni_t
*zl3vni
= NULL
;
3055 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
3057 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
3060 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
3061 struct prefix
*host
)
3063 struct host_rb_entry lookup
;
3064 struct host_rb_entry
*hle
;
3066 memset(&lookup
, 0, sizeof(lookup
));
3067 memcpy(&lookup
.p
, host
, sizeof(*host
));
3069 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3073 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
3074 memcpy(hle
, &lookup
, sizeof(lookup
));
3076 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
3079 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
3081 struct host_rb_entry lookup
;
3082 struct host_rb_entry
*hle
;
3084 memset(&lookup
, 0, sizeof(lookup
));
3085 memcpy(&lookup
.p
, host
, sizeof(*host
));
3087 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3089 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
3090 XFREE(MTYPE_HOST_PREFIX
, hle
);
3097 * Look up MAC hash entry.
3099 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
3100 struct ethaddr
*rmac
)
3105 memset(&tmp
, 0, sizeof(tmp
));
3106 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
3107 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
3113 * Callback to allocate RMAC hash entry.
3115 static void *zl3vni_rmac_alloc(void *p
)
3117 const zebra_mac_t
*tmp_rmac
= p
;
3120 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3123 return ((void *)zrmac
);
3127 * Add RMAC entry to l3-vni
3129 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
3131 zebra_mac_t tmp_rmac
;
3132 zebra_mac_t
*zrmac
= NULL
;
3134 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
3135 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
3136 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
3139 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
3141 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
3142 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
3150 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3152 zebra_mac_t
*tmp_rmac
;
3153 struct host_rb_entry
*hle
;
3155 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3156 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
3158 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
3159 XFREE(MTYPE_HOST_PREFIX
, hle
);
3162 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
3164 XFREE(MTYPE_MAC
, tmp_rmac
);
3170 * Install remote RMAC into the kernel.
3172 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3174 struct zebra_if
*zif
= NULL
;
3175 struct zebra_l2info_vxlan
*vxl
= NULL
;
3177 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3178 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3181 zif
= zl3vni
->vxlan_if
->info
;
3185 vxl
= &zif
->l2info
.vxl
;
3187 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3188 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3192 * Uninstall remote RMAC from the kernel.
3194 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3196 char buf
[ETHER_ADDR_STRLEN
];
3197 struct zebra_if
*zif
= NULL
;
3198 struct zebra_l2info_vxlan
*vxl
= NULL
;
3200 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3201 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3204 if (!zl3vni
->vxlan_if
) {
3206 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
3207 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
3208 zl3vni
->vni
, zl3vni
);
3212 zif
= zl3vni
->vxlan_if
->info
;
3216 vxl
= &zif
->l2info
.vxl
;
3218 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3219 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3222 /* handle rmac add */
3223 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
3224 struct ipaddr
*vtep_ip
,
3225 struct prefix
*host_prefix
)
3227 char buf
[ETHER_ADDR_STRLEN
];
3228 char buf1
[INET6_ADDRSTRLEN
];
3229 zebra_mac_t
*zrmac
= NULL
;
3231 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3234 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
3237 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
3238 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3240 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
3243 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
3244 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
3246 /* install rmac in kernel */
3247 zl3vni_rmac_install(zl3vni
, zrmac
);
3250 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
3256 /* handle rmac delete */
3257 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
3258 struct prefix
*host_prefix
)
3260 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
3262 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3263 /* uninstall from kernel */
3264 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3266 /* del the rmac entry */
3267 zl3vni_rmac_del(zl3vni
, zrmac
);
3272 * Look up nh hash entry on a l3-vni.
3274 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3279 memset(&tmp
, 0, sizeof(tmp
));
3280 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
3281 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
3288 * Callback to allocate NH hash entry on L3-VNI.
3290 static void *zl3vni_nh_alloc(void *p
)
3292 const zebra_neigh_t
*tmp_n
= p
;
3295 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
3302 * Add neighbor entry.
3304 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3305 struct ethaddr
*mac
)
3307 zebra_neigh_t tmp_n
;
3308 zebra_neigh_t
*n
= NULL
;
3310 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
3311 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
3312 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
3315 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
3317 memcpy(&n
->emac
, mac
, ETH_ALEN
);
3318 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3319 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
3325 * Delete neighbor entry.
3327 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3329 zebra_neigh_t
*tmp_n
;
3330 struct host_rb_entry
*hle
;
3332 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
3333 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
3335 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
3336 XFREE(MTYPE_HOST_PREFIX
, hle
);
3339 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
3341 XFREE(MTYPE_NEIGH
, tmp_n
);
3347 * Install remote nh as neigh into the kernel.
3349 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3354 if (!is_l3vni_oper_up(zl3vni
))
3357 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3358 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3361 flags
= NTF_EXT_LEARNED
;
3362 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
3363 flags
|= NTF_ROUTER
;
3364 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
3370 * Uninstall remote nh from the kernel.
3372 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3374 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3375 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3378 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
3381 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
3384 /* add remote vtep as a neigh entry */
3385 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
3386 struct ethaddr
*rmac
,
3387 struct prefix
*host_prefix
)
3389 char buf
[ETHER_ADDR_STRLEN
];
3390 char buf1
[INET6_ADDRSTRLEN
];
3391 zebra_neigh_t
*nh
= NULL
;
3393 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3395 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
3399 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
3400 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
3401 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3406 /* install the nh neigh in kernel */
3407 zl3vni_nh_install(zl3vni
, nh
);
3410 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
3415 /* handle nh neigh delete */
3416 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
3417 struct prefix
*host_prefix
)
3419 rb_delete_host(&nh
->host_rb
, host_prefix
);
3421 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
3422 /* uninstall from kernel */
3423 zl3vni_nh_uninstall(zl3vni
, nh
);
3425 /* delete the nh entry */
3426 zl3vni_nh_del(zl3vni
, nh
);
3430 /* handle neigh update from kernel - the only thing of interest is to
3431 * readd stale entries.
3433 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3437 zebra_neigh_t
*n
= NULL
;
3439 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3443 /* all next hop neigh are remote and installed by frr.
3444 * If the kernel has aged this entry, re-install.
3446 if (state
& NUD_STALE
)
3447 zl3vni_nh_install(zl3vni
, n
);
3452 /* handle neigh delete from kernel */
3453 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3455 zebra_neigh_t
*n
= NULL
;
3457 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3461 /* all next hop neigh are remote and installed by frr.
3462 * If we get an age out notification for these neigh entries, we have to
3465 zl3vni_nh_install(zl3vni
, n
);
3471 * Hash function for L3 VNI.
3473 static unsigned int l3vni_hash_keymake(void *p
)
3475 const zebra_l3vni_t
*zl3vni
= p
;
3477 return jhash_1word(zl3vni
->vni
, 0);
3481 * Compare 2 L3 VNI hash entries.
3483 static int l3vni_hash_cmp(const void *p1
, const void *p2
)
3485 const zebra_l3vni_t
*zl3vni1
= p1
;
3486 const zebra_l3vni_t
*zl3vni2
= p2
;
3488 return (zl3vni1
->vni
== zl3vni2
->vni
);
3492 * Callback to allocate L3 VNI hash entry.
3494 static void *zl3vni_alloc(void *p
)
3496 zebra_l3vni_t
*zl3vni
= NULL
;
3497 const zebra_l3vni_t
*tmp_l3vni
= p
;
3499 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
3500 zl3vni
->vni
= tmp_l3vni
->vni
;
3501 return ((void *)zl3vni
);
3505 * Look up L3 VNI hash entry.
3507 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
3509 struct zebra_ns
*zns
;
3510 zebra_l3vni_t tmp_l3vni
;
3511 zebra_l3vni_t
*zl3vni
= NULL
;
3513 zns
= zebra_ns_lookup(NS_DEFAULT
);
3515 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
3516 tmp_l3vni
.vni
= vni
;
3517 zl3vni
= hash_lookup(zns
->l3vni_table
, &tmp_l3vni
);
3523 * Add L3 VNI hash entry.
3525 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
3527 zebra_l3vni_t tmp_zl3vni
;
3528 struct zebra_ns
*zns
= NULL
;
3529 zebra_l3vni_t
*zl3vni
= NULL
;
3531 zns
= zebra_ns_lookup(NS_DEFAULT
);
3534 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
3535 tmp_zl3vni
.vni
= vni
;
3537 zl3vni
= hash_get(zns
->l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
3540 zl3vni
->vrf_id
= vrf_id
;
3541 zl3vni
->svi_if
= NULL
;
3542 zl3vni
->vxlan_if
= NULL
;
3543 zl3vni
->l2vnis
= list_new();
3544 zl3vni
->l2vnis
->cmp
= (int (*)(void *, void *))vni_hash_cmp
;
3546 /* Create hash table for remote RMAC */
3547 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
3548 "Zebra L3-VNI RMAC-Table");
3550 /* Create hash table for neighbors */
3551 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3552 "Zebra L3-VNI next-hop table");
3558 * Delete L3 VNI hash entry.
3560 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
3562 struct zebra_ns
*zns
;
3563 zebra_l3vni_t
*tmp_zl3vni
;
3565 zns
= zebra_ns_lookup(NS_DEFAULT
);
3568 /* free the list of l2vnis */
3569 list_delete_and_null(&zl3vni
->l2vnis
);
3570 zl3vni
->l2vnis
= NULL
;
3572 /* Free the rmac table */
3573 hash_free(zl3vni
->rmac_table
);
3574 zl3vni
->rmac_table
= NULL
;
3576 /* Free the nh table */
3577 hash_free(zl3vni
->nh_table
);
3578 zl3vni
->nh_table
= NULL
;
3580 /* Free the VNI hash entry and allocated memory. */
3581 tmp_zl3vni
= hash_release(zns
->l3vni_table
, zl3vni
);
3583 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
3588 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
3590 struct zebra_ns
*zns
= NULL
;
3591 struct route_node
*rn
= NULL
;
3592 struct interface
*ifp
= NULL
;
3594 /* loop through all vxlan-interface */
3595 zns
= zebra_ns_lookup(NS_DEFAULT
);
3596 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3598 struct zebra_if
*zif
= NULL
;
3599 struct zebra_l2info_vxlan
*vxl
= NULL
;
3601 ifp
= (struct interface
*)rn
->info
;
3606 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3609 vxl
= &zif
->l2info
.vxl
;
3610 if (vxl
->vni
== zl3vni
->vni
) {
3611 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3619 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
3621 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
3622 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
3627 if (!zl3vni
->vxlan_if
)
3630 zif
= zl3vni
->vxlan_if
->info
;
3634 vxl
= &zif
->l2info
.vxl
;
3636 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3639 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
3641 struct zebra_vrf
*zvrf
= NULL
;
3643 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
3647 return zl3vni_lookup(zvrf
->l3vni
);
3651 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3652 * neighbor notifications, to see if they are of interest.
3654 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
3655 struct interface
*br_if
)
3659 uint8_t bridge_vlan_aware
= 0;
3660 zebra_l3vni_t
*zl3vni
= NULL
;
3661 struct zebra_ns
*zns
= NULL
;
3662 struct route_node
*rn
= NULL
;
3663 struct zebra_if
*zif
= NULL
;
3664 struct interface
*tmp_if
= NULL
;
3665 struct zebra_l2info_bridge
*br
= NULL
;
3666 struct zebra_l2info_vxlan
*vxl
= NULL
;
3671 /* Make sure the linked interface is a bridge. */
3672 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3675 /* Determine if bridge is VLAN-aware or not */
3678 br
= &zif
->l2info
.br
;
3679 bridge_vlan_aware
= br
->vlan_aware
;
3680 if (bridge_vlan_aware
) {
3681 struct zebra_l2info_vlan
*vl
;
3683 if (!IS_ZEBRA_IF_VLAN(ifp
))
3688 vl
= &zif
->l2info
.vl
;
3692 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3693 /* TODO: Optimize with a hash. */
3694 zns
= zebra_ns_lookup(NS_DEFAULT
);
3695 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3696 tmp_if
= (struct interface
*)rn
->info
;
3700 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3702 if (!if_is_operative(tmp_if
))
3704 vxl
= &zif
->l2info
.vxl
;
3706 if (zif
->brslave_info
.br_if
!= br_if
)
3709 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3718 zl3vni
= zl3vni_lookup(vxl
->vni
);
3723 * Inform BGP about l3-vni.
3725 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
3727 struct stream
*s
= NULL
;
3728 struct zserv
*client
= NULL
;
3729 struct ethaddr rmac
;
3730 char buf
[ETHER_ADDR_STRLEN
];
3732 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3733 /* BGP may not be running. */
3738 memset(&rmac
, 0, sizeof(struct ethaddr
));
3739 zl3vni_get_rmac(zl3vni
, &rmac
);
3741 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3743 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
3744 stream_putl(s
, zl3vni
->vni
);
3745 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
3746 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
3747 stream_put(s
, &zl3vni
->filter
, sizeof(int));
3749 /* Write packet size. */
3750 stream_putw_at(s
, 0, stream_get_endp(s
));
3752 if (IS_ZEBRA_DEBUG_VXLAN
)
3754 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
3755 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3756 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
3757 inet_ntoa(zl3vni
->local_vtep_ip
),
3758 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
3759 ? "prefix-routes-only"
3761 zebra_route_string(client
->proto
));
3763 client
->l3vniadd_cnt
++;
3764 return zserv_send_message(client
, s
);
3768 * Inform BGP about local l3-VNI deletion.
3770 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
3772 struct stream
*s
= NULL
;
3773 struct zserv
*client
= NULL
;
3775 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3776 /* BGP may not be running. */
3780 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3782 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
3783 stream_putl(s
, zl3vni
->vni
);
3785 /* Write packet size. */
3786 stream_putw_at(s
, 0, stream_get_endp(s
));
3788 if (IS_ZEBRA_DEBUG_VXLAN
)
3789 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
3790 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3791 zebra_route_string(client
->proto
));
3793 client
->l3vnidel_cnt
++;
3794 return zserv_send_message(client
, s
);
3797 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
3802 /* send l3vni add to BGP */
3803 zl3vni_send_add_to_client(zl3vni
);
3806 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
3811 /* send l3-vni del to BGP*/
3812 zl3vni_send_del_to_client(zl3vni
);
3815 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
, void *ctxt
)
3817 zebra_vni_t
*zvni
= (zebra_vni_t
*)backet
->data
;
3818 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
3820 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
3821 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3825 * handle transition of vni from l2 to l3 and vice versa
3827 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
3830 zebra_vni_t
*zvni
= NULL
;
3832 /* There is a possibility that VNI notification was already received
3833 * from kernel and we programmed it as L2-VNI
3834 * In such a case we need to delete this L2-VNI first, so
3835 * that it can be reprogrammed as L3-VNI in the system. It is also
3836 * possible that the vrf-vni mapping is removed from FRR while the vxlan
3837 * interface is still present in kernel. In this case to keep it
3838 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
3841 /* Locate hash entry */
3842 zvni
= zvni_lookup(vni
);
3846 if (IS_ZEBRA_DEBUG_VXLAN
)
3847 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
3849 /* Delete VNI from BGP. */
3850 zvni_send_del_to_client(zvni
->vni
);
3852 /* Free up all neighbors and MAC, if any. */
3853 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
3854 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
3856 /* Free up all remote VTEPs, if any. */
3857 zvni_vtep_del_all(zvni
, 0);
3859 /* Delete the hash entry. */
3860 if (zvni_del(zvni
)) {
3861 flog_err(ZEBRA_ERR_VNI_DEL_FAILED
,
3862 "Failed to del VNI hash %p, VNI %u", zvni
,
3867 /* TODO_MITESH: This needs to be thought through. We don't have
3868 * enough information at this point to reprogram the vni as
3869 * l2-vni. One way is to store the required info in l3-vni and
3870 * used it solely for this purpose
3877 /* delete and uninstall rmac hash entry */
3878 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
, void *ctx
)
3880 zebra_mac_t
*zrmac
= NULL
;
3881 zebra_l3vni_t
*zl3vni
= NULL
;
3883 zrmac
= (zebra_mac_t
*)backet
->data
;
3884 zl3vni
= (zebra_l3vni_t
*)ctx
;
3885 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3886 zl3vni_rmac_del(zl3vni
, zrmac
);
3889 /* delete and uninstall nh hash entry */
3890 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
, void *ctx
)
3892 zebra_neigh_t
*n
= NULL
;
3893 zebra_l3vni_t
*zl3vni
= NULL
;
3895 n
= (zebra_neigh_t
*)backet
->data
;
3896 zl3vni
= (zebra_l3vni_t
*)ctx
;
3897 zl3vni_nh_uninstall(zl3vni
, n
);
3898 zl3vni_nh_del(zl3vni
, n
);
3901 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
3904 struct zserv
*client
= NULL
;
3905 struct stream
*s
= NULL
;
3906 char buf
[PREFIX_STRLEN
];
3908 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3909 /* BGP may not be running. */
3913 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3915 zclient_create_header(s
, cmd
, vrf_id
);
3916 stream_put(s
, p
, sizeof(struct prefix
));
3918 /* Write packet size. */
3919 stream_putw_at(s
, 0, stream_get_endp(s
));
3921 if (IS_ZEBRA_DEBUG_VXLAN
)
3922 zlog_debug("Send ip prefix %s %s on vrf %s",
3923 prefix2str(p
, buf
, sizeof(buf
)),
3924 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
3925 vrf_id_to_name(vrf_id
));
3927 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
3928 client
->prefixadd_cnt
++;
3930 client
->prefixdel_cnt
++;
3932 return zserv_send_message(client
, s
);
3935 /* re-add remote rmac if needed */
3936 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
3937 struct ethaddr
*rmac
)
3939 char buf
[ETHER_ADDR_STRLEN
];
3940 zebra_mac_t
*zrmac
= NULL
;
3942 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3946 if (IS_ZEBRA_DEBUG_VXLAN
)
3947 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
3948 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
3950 zl3vni_rmac_install(zl3vni
, zrmac
);
3954 /* Public functions */
3956 int is_l3vni_for_prefix_routes_only(vni_t vni
)
3958 zebra_l3vni_t
*zl3vni
= NULL
;
3960 zl3vni
= zl3vni_lookup(vni
);
3964 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
3967 /* handle evpn route in vrf table */
3968 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
3969 struct ipaddr
*vtep_ip
,
3970 struct prefix
*host_prefix
)
3972 zebra_l3vni_t
*zl3vni
= NULL
;
3973 struct ipaddr ipv4_vtep
;
3975 zl3vni
= zl3vni_from_vrf(vrf_id
);
3976 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
3980 * add the next hop neighbor -
3981 * neigh to be installed is the ipv6 nexthop neigh
3983 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
3986 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
3987 * address. Rmac is programmed against the ipv4 vtep because we only
3988 * support ipv4 tunnels in the h/w right now
3990 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
3991 ipv4_vtep
.ipa_type
= IPADDR_V4
;
3992 if (vtep_ip
->ipa_type
== IPADDR_V6
)
3993 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
3994 &(ipv4_vtep
.ipaddr_v4
));
3996 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
3997 sizeof(struct in_addr
));
4000 * add the rmac - remote rmac to be installed is against the ipv4
4003 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
4006 /* handle evpn vrf route delete */
4007 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
4008 struct ipaddr
*vtep_ip
,
4009 struct prefix
*host_prefix
)
4011 zebra_l3vni_t
*zl3vni
= NULL
;
4012 zebra_neigh_t
*nh
= NULL
;
4013 zebra_mac_t
*zrmac
= NULL
;
4015 zl3vni
= zl3vni_from_vrf(vrf_id
);
4019 /* find the next hop entry and rmac entry */
4020 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4023 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
4025 /* delete the next hop entry */
4026 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
4028 /* delete the rmac entry */
4030 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
4034 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
4035 struct ethaddr
*rmac
,
4038 zebra_l3vni_t
*zl3vni
= NULL
;
4039 zebra_mac_t
*zrmac
= NULL
;
4040 json_object
*json
= NULL
;
4042 if (!is_evpn_enabled()) {
4044 vty_out(vty
, "{}\n");
4049 json
= json_object_new_object();
4051 zl3vni
= zl3vni_lookup(l3vni
);
4054 vty_out(vty
, "{}\n");
4056 vty_out(vty
, "%% L3-VNI %u doesnt exist\n", l3vni
);
4060 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4063 vty_out(vty
, "{}\n");
4066 "%% Requested RMAC doesnt exist in L3-VNI %u",
4071 zl3vni_print_rmac(zrmac
, vty
, json
);
4074 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4075 json
, JSON_C_TO_STRING_PRETTY
));
4076 json_object_free(json
);
4080 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
,
4083 zebra_l3vni_t
*zl3vni
;
4085 struct rmac_walk_ctx wctx
;
4086 json_object
*json
= NULL
;
4088 if (!is_evpn_enabled())
4091 zl3vni
= zl3vni_lookup(l3vni
);
4094 vty_out(vty
, "{}\n");
4096 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4099 num_rmacs
= hashcount(zl3vni
->rmac_table
);
4104 json
= json_object_new_object();
4106 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
4110 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
4112 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
4114 json_object_int_add(json
, "numRmacs", num_rmacs
);
4116 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
4119 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4120 json
, JSON_C_TO_STRING_PRETTY
));
4121 json_object_free(json
);
4125 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, uint8_t use_json
)
4127 struct zebra_ns
*zns
= NULL
;
4128 json_object
*json
= NULL
;
4131 if (!is_evpn_enabled()) {
4133 vty_out(vty
, "{}\n");
4137 zns
= zebra_ns_lookup(NS_DEFAULT
);
4140 vty_out(vty
, "{}\n");
4145 json
= json_object_new_object();
4149 hash_iterate(zns
->l3vni_table
,
4150 (void (*)(struct hash_backet
*,
4151 void *))zl3vni_print_rmac_hash_all_vni
,
4155 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4156 json
, JSON_C_TO_STRING_PRETTY
));
4157 json_object_free(json
);
4161 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
4162 struct ipaddr
*ip
, uint8_t use_json
)
4164 zebra_l3vni_t
*zl3vni
= NULL
;
4165 zebra_neigh_t
*n
= NULL
;
4166 json_object
*json
= NULL
;
4168 if (!is_evpn_enabled()) {
4170 vty_out(vty
, "{}\n");
4175 json
= json_object_new_object();
4177 zl3vni
= zl3vni_lookup(l3vni
);
4180 vty_out(vty
, "{}\n");
4182 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4186 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4189 vty_out(vty
, "{}\n");
4192 "%% Requested next-hop not present for L3-VNI %u",
4197 zl3vni_print_nh(n
, vty
, json
);
4200 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4201 json
, JSON_C_TO_STRING_PRETTY
));
4202 json_object_free(json
);
4206 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, uint8_t use_json
)
4209 struct nh_walk_ctx wctx
;
4210 json_object
*json
= NULL
;
4211 zebra_l3vni_t
*zl3vni
= NULL
;
4213 if (!is_evpn_enabled())
4216 zl3vni
= zl3vni_lookup(l3vni
);
4219 vty_out(vty
, "{}\n");
4221 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4225 num_nh
= hashcount(zl3vni
->nh_table
);
4230 json
= json_object_new_object();
4235 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
4237 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
4239 json_object_int_add(json
, "numNextHops", num_nh
);
4241 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
4244 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4245 json
, JSON_C_TO_STRING_PRETTY
));
4246 json_object_free(json
);
4250 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, uint8_t use_json
)
4252 struct zebra_ns
*zns
= NULL
;
4253 json_object
*json
= NULL
;
4256 if (!is_evpn_enabled()) {
4258 vty_out(vty
, "{}\n");
4262 zns
= zebra_ns_lookup(NS_DEFAULT
);
4267 json
= json_object_new_object();
4271 hash_iterate(zns
->l3vni_table
,
4272 (void (*)(struct hash_backet
*,
4273 void *))zl3vni_print_nh_hash_all_vni
,
4277 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4278 json
, JSON_C_TO_STRING_PRETTY
));
4279 json_object_free(json
);
4285 * Display L3 VNI information (VTY command handler).
4287 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, uint8_t use_json
)
4290 json_object
*json
= NULL
;
4291 zebra_l3vni_t
*zl3vni
= NULL
;
4293 if (!is_evpn_enabled()) {
4295 vty_out(vty
, "{}\n");
4299 zl3vni
= zl3vni_lookup(vni
);
4302 vty_out(vty
, "{}\n");
4304 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4309 json
= json_object_new_object();
4313 zl3vni_print(zl3vni
, (void *)args
);
4316 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4317 json
, JSON_C_TO_STRING_PRETTY
));
4318 json_object_free(json
);
4322 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4323 json_object
*json_vrfs
)
4325 char buf
[ETHER_ADDR_STRLEN
];
4326 zebra_l3vni_t
*zl3vni
= NULL
;
4328 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4333 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
4334 zvrf_name(zvrf
), zl3vni
->vni
,
4335 zl3vni_vxlan_if_name(zl3vni
),
4336 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
4337 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4339 json_object
*json_vrf
= NULL
;
4340 json_vrf
= json_object_new_object();
4341 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
4342 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
4343 json_object_string_add(json_vrf
, "vxlanIntf",
4344 zl3vni_vxlan_if_name(zl3vni
));
4345 json_object_string_add(json_vrf
, "sviIntf",
4346 zl3vni_svi_if_name(zl3vni
));
4347 json_object_string_add(json_vrf
, "state",
4348 zl3vni_state2str(zl3vni
));
4349 json_object_string_add(
4350 json_vrf
, "routerMac",
4351 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4352 json_object_array_add(json_vrfs
, json_vrf
);
4357 * Display Neighbors for a VNI (VTY command handler).
4359 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4360 vni_t vni
, uint8_t use_json
)
4364 struct neigh_walk_ctx wctx
;
4365 json_object
*json
= NULL
;
4367 if (!is_evpn_enabled())
4369 zvni
= zvni_lookup(vni
);
4372 vty_out(vty
, "{}\n");
4374 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4377 num_neigh
= hashcount(zvni
->neigh_table
);
4382 json
= json_object_new_object();
4384 /* Since we have IPv6 addresses to deal with which can vary widely in
4385 * size, we try to be a bit more elegant in display by first computing
4386 * the maximum width.
4388 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4391 wctx
.addr_width
= 15;
4393 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4397 "Number of ARPs (local and remote) known for this VNI: %u\n",
4399 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
4400 "Type", "MAC", "Remote VTEP");
4402 json_object_int_add(json
, "numArpNd", num_neigh
);
4404 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4406 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4407 json
, JSON_C_TO_STRING_PRETTY
));
4408 json_object_free(json
);
4413 * Display neighbors across all VNIs (VTY command handler).
4415 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4418 json_object
*json
= NULL
;
4421 if (!is_evpn_enabled())
4425 json
= json_object_new_object();
4429 hash_iterate(zvrf
->vni_table
,
4430 (void (*)(struct hash_backet
*,
4431 void *))zvni_print_neigh_hash_all_vni
,
4434 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4435 json
, JSON_C_TO_STRING_PRETTY
));
4436 json_object_free(json
);
4441 * Display specific neighbor for a VNI, if present (VTY command handler).
4443 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
4444 struct zebra_vrf
*zvrf
, vni_t vni
,
4445 struct ipaddr
*ip
, uint8_t use_json
)
4449 json_object
*json
= NULL
;
4451 if (!is_evpn_enabled())
4453 zvni
= zvni_lookup(vni
);
4456 vty_out(vty
, "{}\n");
4458 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4461 n
= zvni_neigh_lookup(zvni
, ip
);
4465 "%% Requested neighbor does not exist in VNI %u\n",
4470 json
= json_object_new_object();
4472 zvni_print_neigh(n
, vty
, json
);
4475 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4476 json
, JSON_C_TO_STRING_PRETTY
));
4477 json_object_free(json
);
4482 * Display neighbors for a VNI from specific VTEP (VTY command handler).
4483 * By definition, these are remote neighbors.
4485 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4486 vni_t vni
, struct in_addr vtep_ip
,
4491 struct neigh_walk_ctx wctx
;
4492 json_object
*json
= NULL
;
4494 if (!is_evpn_enabled())
4496 zvni
= zvni_lookup(vni
);
4499 vty_out(vty
, "{}\n");
4501 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4504 num_neigh
= hashcount(zvni
->neigh_table
);
4508 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4511 wctx
.addr_width
= 15;
4512 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
4513 wctx
.r_vtep_ip
= vtep_ip
;
4515 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4516 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4519 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4520 json
, JSON_C_TO_STRING_PRETTY
));
4521 json_object_free(json
);
4526 * Display MACs for a VNI (VTY command handler).
4528 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4529 vni_t vni
, uint8_t use_json
)
4533 struct mac_walk_ctx wctx
;
4534 json_object
*json
= NULL
;
4535 json_object
*json_mac
= NULL
;
4537 if (!is_evpn_enabled())
4539 zvni
= zvni_lookup(vni
);
4542 vty_out(vty
, "{}\n");
4544 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4547 num_macs
= num_valid_macs(zvni
);
4552 json
= json_object_new_object();
4553 json_mac
= json_object_new_object();
4556 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4559 wctx
.json
= json_mac
;
4563 "Number of MACs (local and remote) known for this VNI: %u\n",
4565 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
4566 "Intf/Remote VTEP", "VLAN");
4568 json_object_int_add(json
, "numMacs", num_macs
);
4570 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4573 json_object_object_add(json
, "macs", json_mac
);
4574 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4575 json
, JSON_C_TO_STRING_PRETTY
));
4576 json_object_free(json
);
4581 * Display MACs for all VNIs (VTY command handler).
4583 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4586 struct mac_walk_ctx wctx
;
4587 json_object
*json
= NULL
;
4589 if (!is_evpn_enabled()) {
4591 vty_out(vty
, "{}\n");
4595 json
= json_object_new_object();
4597 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4600 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4603 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4604 json
, JSON_C_TO_STRING_PRETTY
));
4605 json_object_free(json
);
4610 * Display MACs for all VNIs (VTY command handler).
4612 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
4613 struct zebra_vrf
*zvrf
,
4614 struct in_addr vtep_ip
,
4617 struct mac_walk_ctx wctx
;
4618 json_object
*json
= NULL
;
4620 if (!is_evpn_enabled())
4624 json
= json_object_new_object();
4626 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4628 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4629 wctx
.r_vtep_ip
= vtep_ip
;
4631 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4634 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4635 json
, JSON_C_TO_STRING_PRETTY
));
4636 json_object_free(json
);
4641 * Display specific MAC for a VNI, if present (VTY command handler).
4643 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4644 vni_t vni
, struct ethaddr
*macaddr
)
4649 if (!is_evpn_enabled())
4651 zvni
= zvni_lookup(vni
);
4653 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4656 mac
= zvni_mac_lookup(zvni
, macaddr
);
4658 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
4663 zvni_print_mac(mac
, vty
);
4667 * Display MACs for a VNI from specific VTEP (VTY command handler).
4669 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4670 vni_t vni
, struct in_addr vtep_ip
,
4675 struct mac_walk_ctx wctx
;
4676 json_object
*json
= NULL
;
4677 json_object
*json_mac
= NULL
;
4679 if (!is_evpn_enabled())
4681 zvni
= zvni_lookup(vni
);
4684 vty_out(vty
, "{}\n");
4686 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4689 num_macs
= num_valid_macs(zvni
);
4694 json
= json_object_new_object();
4695 json_mac
= json_object_new_object();
4698 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4701 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4702 wctx
.r_vtep_ip
= vtep_ip
;
4703 wctx
.json
= json_mac
;
4704 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4707 json_object_int_add(json
, "numMacs", wctx
.count
);
4709 json_object_object_add(json
, "macs", json_mac
);
4710 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4711 json
, JSON_C_TO_STRING_PRETTY
));
4712 json_object_free(json
);
4718 * Display VNI information (VTY command handler).
4720 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
4723 json_object
*json
= NULL
;
4725 zebra_l3vni_t
*zl3vni
= NULL
;
4726 zebra_vni_t
*zvni
= NULL
;
4728 if (!is_evpn_enabled())
4732 json
= json_object_new_object();
4736 zl3vni
= zl3vni_lookup(vni
);
4738 zl3vni_print(zl3vni
, (void *)args
);
4740 zvni
= zvni_lookup(vni
);
4743 vty_out(vty
, "{}\n");
4745 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4749 zvni_print(zvni
, (void *)args
);
4753 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4754 json
, JSON_C_TO_STRING_PRETTY
));
4755 json_object_free(json
);
4759 /* Display all global details for EVPN */
4760 void zebra_vxlan_print_evpn(struct vty
*vty
, uint8_t uj
)
4765 json_object
*json
= NULL
;
4766 struct zebra_ns
*zns
= NULL
;
4767 struct zebra_vrf
*zvrf
= NULL
;
4769 if (!is_evpn_enabled())
4772 zns
= zebra_ns_lookup(NS_DEFAULT
);
4776 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
4780 num_l3vnis
= hashcount(zns
->l3vni_table
);
4781 num_l2vnis
= hashcount(zvrf
->vni_table
);
4782 num_vnis
= num_l2vnis
+ num_l3vnis
;
4785 json
= json_object_new_object();
4786 json_object_string_add(json
, "advertiseGatewayMacip",
4787 zvrf
->advertise_gw_macip
? "Yes" : "No");
4788 json_object_int_add(json
, "numVnis", num_vnis
);
4789 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4790 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4792 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
4793 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
4794 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
4795 zvrf
->advertise_gw_macip
? "Yes" : "No");
4799 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4800 json
, JSON_C_TO_STRING_PRETTY
));
4801 json_object_free(json
);
4806 * Display VNI hash table (VTY command handler).
4808 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4811 json_object
*json
= NULL
;
4812 struct zebra_ns
*zns
= NULL
;
4815 if (!is_evpn_enabled())
4818 zns
= zebra_ns_lookup(NS_DEFAULT
);
4824 json
= json_object_new_object();
4826 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
4827 "Type", "VxLAN IF", "# MACs", "# ARPs",
4828 "# Remote VTEPs", "Tenant VRF");
4833 /* Display all L2-VNIs */
4834 hash_iterate(zvrf
->vni_table
,
4835 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
4838 /* Display all L3-VNIs */
4839 hash_iterate(zns
->l3vni_table
,
4840 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
4844 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4845 json
, JSON_C_TO_STRING_PRETTY
));
4846 json_object_free(json
);
4851 * Handle neighbor delete notification from the kernel (on a VLAN device
4852 * / L3 interface). This may result in either the neighbor getting deleted
4853 * from our database or being re-added to the kernel (if it is a valid
4856 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
4857 struct interface
*link_if
,
4860 char buf
[INET6_ADDRSTRLEN
];
4861 char buf2
[ETHER_ADDR_STRLEN
];
4862 zebra_neigh_t
*n
= NULL
;
4863 zebra_vni_t
*zvni
= NULL
;
4864 zebra_mac_t
*zmac
= NULL
;
4865 zebra_l3vni_t
*zl3vni
= NULL
;
4867 /* check if this is a remote neigh entry corresponding to remote
4870 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4872 return zl3vni_local_nh_del(zl3vni
, ip
);
4874 /* We are only interested in neighbors on an SVI that resides on top
4875 * of a VxLAN bridge.
4877 zvni
= zvni_from_svi(ifp
, link_if
);
4881 if (!zvni
->vxlan_if
) {
4883 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
4888 if (IS_ZEBRA_DEBUG_VXLAN
)
4889 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
4890 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
4891 ifp
->ifindex
, zvni
->vni
);
4893 /* If entry doesn't exist, nothing to do. */
4894 n
= zvni_neigh_lookup(zvni
, ip
);
4898 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
4900 if (IS_ZEBRA_DEBUG_VXLAN
)
4902 "Trying to del a neigh %s without a mac %s on VNI %u",
4903 ipaddr2str(ip
, buf
, sizeof(buf
)),
4904 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
4910 /* If it is a remote entry, the kernel has aged this out or someone has
4911 * deleted it, it needs to be re-installed as Quagga is the owner.
4913 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
4914 zvni_neigh_install(zvni
, n
);
4918 /* Remove neighbor from BGP. */
4919 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
4920 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0);
4922 /* Delete this neighbor entry. */
4923 zvni_neigh_del(zvni
, n
);
4925 /* see if the AUTO mac needs to be deleted */
4926 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
4927 && !listcount(zmac
->neigh_list
))
4928 zvni_mac_del(zvni
, zmac
);
4934 * Handle neighbor add or update notification from the kernel (on a VLAN
4935 * device / L3 interface). This is typically for a local neighbor but can
4936 * also be for a remote neighbor (e.g., ageout notification). It could
4937 * also be a "move" scenario.
4939 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
4940 struct interface
*link_if
,
4942 struct ethaddr
*macaddr
,
4944 uint8_t ext_learned
,
4945 uint8_t router_flag
)
4947 char buf
[ETHER_ADDR_STRLEN
];
4948 char buf2
[INET6_ADDRSTRLEN
];
4949 zebra_vni_t
*zvni
= NULL
;
4950 zebra_l3vni_t
*zl3vni
= NULL
;
4952 /* check if this is a remote neigh entry corresponding to remote
4955 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4957 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
4959 /* We are only interested in neighbors on an SVI that resides on top
4960 * of a VxLAN bridge.
4962 zvni
= zvni_from_svi(ifp
, link_if
);
4966 if (IS_ZEBRA_DEBUG_VXLAN
)
4968 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u",
4969 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
4970 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
4971 ifp
->ifindex
, state
, ext_learned
? "ext-learned " : "",
4974 /* Is this about a local neighbor or a remote one? */
4976 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
4979 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
4984 * Handle message from client to delete a remote MACIP for a VNI.
4986 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
4990 struct ethaddr macaddr
;
4992 struct in_addr vtep_ip
;
4996 unsigned short l
= 0, ipa_len
;
4997 char buf
[ETHER_ADDR_STRLEN
];
4998 char buf1
[INET6_ADDRSTRLEN
];
4999 struct interface
*ifp
= NULL
;
5000 struct zebra_if
*zif
= NULL
;
5002 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5003 memset(&ip
, 0, sizeof(struct ipaddr
));
5004 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5008 while (l
< hdr
->length
) {
5009 /* Obtain each remote MACIP and process. */
5010 /* Message contains VNI, followed by MAC followed by IP (if any)
5011 * followed by remote VTEP IP.
5015 memset(&ip
, 0, sizeof(ip
));
5016 STREAM_GETL(s
, vni
);
5017 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5018 STREAM_GETL(s
, ipa_len
);
5020 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5022 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5024 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5025 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5026 l
+= IPV4_MAX_BYTELEN
;
5028 if (IS_ZEBRA_DEBUG_VXLAN
)
5030 "Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
5031 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5032 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5034 zebra_route_string(client
->proto
));
5036 /* Locate VNI hash entry - expected to exist. */
5037 zvni
= zvni_lookup(vni
);
5039 if (IS_ZEBRA_DEBUG_VXLAN
)
5041 "Failed to locate VNI hash upon remote MACIP DEL, "
5046 ifp
= zvni
->vxlan_if
;
5049 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
5055 /* If down or not mapped to a bridge, we're done. */
5056 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5059 /* The remote VTEP specified is normally expected to exist, but
5061 * possible that the peer may delete the VTEP before deleting
5063 * referring to the VTEP, in which case the handler (see
5065 * would have already deleted the MACs.
5067 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5070 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5072 n
= zvni_neigh_lookup(zvni
, &ip
);
5075 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u",
5076 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5077 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5081 /* If the remote mac or neighbor doesn't exist there is nothing
5083 * to do. Otherwise, uninstall the entry and then remove it.
5088 /* Ignore the delete if this mac is a gateway mac-ip */
5089 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5090 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5092 "%u: Ignore Del for MAC %s neigh %s on VNI %u as it is configured as a default gateway",
5094 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5095 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5099 /* Uninstall remote neighbor or MAC. */
5101 /* When the MAC changes for an IP, it is possible the
5103 * update the new MAC before trying to delete the "old"
5105 * (as these are two different MACIP routes). Do the
5107 * if the MAC matches.
5109 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5110 && (memcmp(n
->emac
.octet
, macaddr
.octet
, ETH_ALEN
)
5112 zvni_neigh_uninstall(zvni
, n
);
5113 zvni_neigh_del(zvni
, n
);
5114 zvni_deref_ip2mac(zvni
, mac
, 1);
5117 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5118 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5120 if (list_isempty(mac
->neigh_list
)) {
5121 zvni_mac_uninstall(zvni
, mac
, 0);
5122 zvni_mac_del(zvni
, mac
);
5124 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5134 * Handle message from client to add a remote MACIP for a VNI. This
5135 * could be just the add of a MAC address or the add of a neighbor
5138 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
5142 struct ethaddr macaddr
;
5144 struct in_addr vtep_ip
;
5146 zebra_vtep_t
*zvtep
;
5147 zebra_mac_t
*mac
, *old_mac
;
5149 unsigned short l
= 0, ipa_len
;
5150 int update_mac
= 0, update_neigh
= 0;
5151 char buf
[ETHER_ADDR_STRLEN
];
5152 char buf1
[INET6_ADDRSTRLEN
];
5154 u_char remote_gw
= 0;
5156 struct interface
*ifp
= NULL
;
5157 struct zebra_if
*zif
= NULL
;
5159 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5160 memset(&ip
, 0, sizeof(struct ipaddr
));
5161 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5163 if (!EVPN_ENABLED(zvrf
)) {
5165 "%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
5166 __PRETTY_FUNCTION__
);
5172 while (l
< hdr
->length
) {
5173 /* Obtain each remote MACIP and process. */
5174 /* Message contains VNI, followed by MAC followed by IP (if any)
5175 * followed by remote VTEP IP.
5177 update_mac
= update_neigh
= 0;
5180 memset(&ip
, 0, sizeof(ip
));
5181 STREAM_GETL(s
, vni
);
5182 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5183 STREAM_GETL(s
, ipa_len
);
5185 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5187 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5189 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5190 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5191 l
+= IPV4_MAX_BYTELEN
;
5193 /* Get flags - sticky mac and/or gateway mac */
5194 STREAM_GETC(s
, flags
);
5195 sticky
= CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5196 remote_gw
= CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5199 if (IS_ZEBRA_DEBUG_VXLAN
)
5201 "Recv MACIP Add MAC %s IP %s VNI %u Remote VTEP %s with flags 0x%x from %s",
5202 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5203 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5204 inet_ntoa(vtep_ip
), flags
,
5205 zebra_route_string(client
->proto
));
5207 /* Locate VNI hash entry - expected to exist. */
5208 zvni
= zvni_lookup(vni
);
5211 "Failed to locate VNI hash upon remote MACIP ADD, VNI %u",
5215 ifp
= zvni
->vxlan_if
;
5218 "VNI %u hash %p doesn't have intf upon remote MACIP add",
5224 /* If down or not mapped to a bridge, we're done. */
5225 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5228 /* The remote VTEP specified should normally exist, but it is
5230 * that when peering comes up, peer may advertise MACIP routes
5232 * advertising type-3 routes.
5234 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5236 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5238 ZEBRA_ERR_VTEP_ADD_FAILED
,
5239 "Failed to add remote VTEP, VNI %u zvni %p",
5244 zvni_vtep_install(zvni
, &vtep_ip
);
5247 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5249 /* Ignore the update if the mac is already present
5251 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)
5252 && CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5253 if (IS_ZEBRA_DEBUG_VXLAN
)
5255 "%u:Ignore MAC %s IP %s on VNI %u as MAC is already configured as gateway mac",
5257 prefix_mac2str(&macaddr
, buf
,
5259 ipaddr2str(&ip
, buf1
, sizeof(buf1
)),
5264 /* check if the remote MAC is unknown or has a change.
5265 * If so, that needs to be updated first. Note that client could
5266 * install MAC and MACIP separately or just install the latter.
5268 if (!mac
|| !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5269 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0)
5271 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
) ? 1 : 0)
5273 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
))
5278 mac
= zvni_mac_add(zvni
, &macaddr
);
5281 "Failed to add MAC %s VNI %u Remote VTEP %s",
5282 prefix_mac2str(&macaddr
, buf
,
5284 vni
, inet_ntoa(vtep_ip
));
5288 /* Is this MAC created for a MACIP? */
5290 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5293 /* Set "auto" and "remote" forwarding info. */
5294 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5295 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5296 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5297 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5300 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5302 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5305 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5307 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5309 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5311 /* Install the entry. */
5312 zvni_mac_install(zvni
, mac
);
5315 /* If there is no IP, continue - after clearing AUTO flag of
5318 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5322 /* Check if the remote neighbor itself is unknown or has a
5324 * If so, create or update and then install the entry.
5326 n
= zvni_neigh_lookup(zvni
, &ip
);
5327 if (!n
|| !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5328 || (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
)) != 0)
5329 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
))
5334 n
= zvni_neigh_add(zvni
, &ip
, &macaddr
);
5337 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5338 ipaddr2str(&ip
, buf1
,
5340 prefix_mac2str(&macaddr
, buf
,
5342 vni
, inet_ntoa(vtep_ip
));
5346 } else if (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
))
5348 /* MAC change, update neigh list for old and new
5350 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5352 listnode_delete(old_mac
->neigh_list
, n
);
5353 zvni_deref_ip2mac(zvni
, old_mac
, 1);
5355 listnode_add_sort(mac
->neigh_list
, n
);
5356 memcpy(&n
->emac
, &macaddr
, ETH_ALEN
);
5359 /* Set "remote" forwarding info. */
5360 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5361 /* TODO: Handle MAC change. */
5362 n
->r_vtep_ip
= vtep_ip
;
5363 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5365 /* Set router flag (R-bit) to this Neighbor entry */
5366 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5367 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5369 /* Install the entry. */
5370 zvni_neigh_install(zvni
, n
);
5379 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5380 * us, this must involve a multihoming scenario. Treat this as implicit delete
5381 * of any prior local MAC.
5383 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
5384 struct interface
*br_if
,
5385 struct ethaddr
*macaddr
, vlanid_t vid
)
5387 struct zebra_if
*zif
;
5388 struct zebra_l2info_vxlan
*vxl
;
5392 char buf
[ETHER_ADDR_STRLEN
];
5396 vxl
= &zif
->l2info
.vxl
;
5399 /* Check if EVPN is enabled. */
5400 if (!is_evpn_enabled())
5403 /* Locate hash entry; it is expected to exist. */
5404 zvni
= zvni_lookup(vni
);
5408 /* If entry doesn't exist, nothing to do. */
5409 mac
= zvni_mac_lookup(zvni
, macaddr
);
5413 /* Is it a local entry? */
5414 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5417 if (IS_ZEBRA_DEBUG_VXLAN
)
5419 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5420 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5423 /* Remove MAC from BGP. */
5424 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5427 * If there are no neigh associated with the mac delete the mac
5428 * else mark it as AUTO for forward reference
5430 if (!listcount(mac
->neigh_list
)) {
5431 zvni_mac_del(zvni
, mac
);
5433 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5434 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5441 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5442 * This can happen because the remote MAC entries are also added as "dynamic",
5443 * so the kernel can ageout the entry.
5445 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
5446 struct interface
*br_if
,
5447 struct ethaddr
*macaddr
, vlanid_t vid
)
5449 struct zebra_if
*zif
= NULL
;
5450 struct zebra_l2info_vxlan
*vxl
= NULL
;
5452 zebra_vni_t
*zvni
= NULL
;
5453 zebra_l3vni_t
*zl3vni
= NULL
;
5454 zebra_mac_t
*mac
= NULL
;
5455 char buf
[ETHER_ADDR_STRLEN
];
5459 vxl
= &zif
->l2info
.vxl
;
5462 /* Check if EVPN is enabled. */
5463 if (!is_evpn_enabled())
5466 /* check if this is a remote RMAC and readd simillar to remote macs */
5467 zl3vni
= zl3vni_lookup(vni
);
5469 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
5471 /* Locate hash entry; it is expected to exist. */
5472 zvni
= zvni_lookup(vni
);
5476 /* If entry doesn't exist, nothing to do. */
5477 mac
= zvni_mac_lookup(zvni
, macaddr
);
5481 /* Is it a remote entry? */
5482 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
5485 if (IS_ZEBRA_DEBUG_VXLAN
)
5486 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
5487 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5490 zvni_mac_install(zvni
, mac
);
5495 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
5497 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
5498 struct ethaddr
*macaddr
, vlanid_t vid
)
5502 char buf
[ETHER_ADDR_STRLEN
];
5504 /* We are interested in MACs only on ports or (port, VLAN) that
5507 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5510 if (!zvni
->vxlan_if
) {
5511 zlog_warn("VNI %u hash %p doesn't have intf upon local MAC DEL",
5516 if (IS_ZEBRA_DEBUG_VXLAN
)
5517 zlog_debug("Del MAC %s intf %s(%u) VID %u -> VNI %u",
5518 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5519 ifp
->ifindex
, vid
, zvni
->vni
);
5521 /* If entry doesn't exist, nothing to do. */
5522 mac
= zvni_mac_lookup(zvni
, macaddr
);
5526 /* Is it a local entry? */
5527 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5530 /* Remove MAC from BGP. */
5531 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5533 /* Update all the neigh entries associated with this mac */
5534 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
5537 * If there are no neigh associated with the mac delete the mac
5538 * else mark it as AUTO for forward reference
5540 if (!listcount(mac
->neigh_list
)) {
5541 zvni_mac_del(zvni
, mac
);
5543 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5544 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5551 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
5553 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
5554 struct interface
*br_if
,
5555 struct ethaddr
*macaddr
, vlanid_t vid
,
5560 char buf
[ETHER_ADDR_STRLEN
];
5564 /* We are interested in MACs only on ports or (port, VLAN) that
5567 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5569 if (IS_ZEBRA_DEBUG_VXLAN
)
5571 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5572 sticky
? "sticky " : "",
5573 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5574 ifp
->name
, ifp
->ifindex
, vid
);
5578 if (!zvni
->vxlan_if
) {
5579 zlog_warn("VNI %u hash %p doesn't have intf upon local MAC ADD",
5584 if (IS_ZEBRA_DEBUG_VXLAN
)
5585 zlog_debug("Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
5586 sticky
? "sticky " : "",
5587 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5588 ifp
->ifindex
, vid
, zvni
->vni
);
5590 /* If same entry already exists, nothing to do. */
5591 mac
= zvni_mac_lookup(zvni
, macaddr
);
5593 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5594 mac_sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5600 * return if nothing has changed.
5601 * inform bgp if sticky flag has changed
5602 * update locally and do not inform bgp if local
5603 * parameters like interface has changed
5605 if (mac_sticky
== sticky
5606 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
5607 && mac
->fwd_info
.local
.vid
== vid
) {
5608 if (IS_ZEBRA_DEBUG_VXLAN
)
5610 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
5611 "entry exists and has not changed ",
5612 sticky
? "sticky " : "",
5613 prefix_mac2str(macaddr
, buf
,
5615 ifp
->name
, ifp
->ifindex
, vid
,
5618 } else if (mac_sticky
!= sticky
) {
5621 add
= 0; /* This is an update of local
5624 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5626 * If we have already learned the MAC as a remote sticky
5628 * this is a operator error and we must log a warning
5630 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
5632 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
5633 prefix_mac2str(macaddr
, buf
,
5635 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
5643 mac
= zvni_mac_add(zvni
, macaddr
);
5645 flog_err(ZEBRA_ERR_MAC_ADD_FAILED
,
5646 "Failed to add MAC %s intf %s(%u) VID %u",
5647 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5648 ifp
->name
, ifp
->ifindex
, vid
);
5653 /* Set "local" forwarding info. */
5654 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5655 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5656 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5657 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5658 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
5659 mac
->fwd_info
.local
.vid
= vid
;
5662 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5664 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5666 /* Inform BGP if required. */
5668 zvni_process_neigh_on_local_mac_add(zvni
, mac
);
5669 return zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
5677 * Handle message from client to delete a remote VTEP for a VNI.
5679 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
5682 unsigned short l
= 0;
5684 struct in_addr vtep_ip
;
5686 zebra_vtep_t
*zvtep
;
5687 struct interface
*ifp
;
5688 struct zebra_if
*zif
;
5690 if (!is_evpn_enabled()) {
5692 "%s: EVPN is not enabled yet we have received a vtep del command",
5693 __PRETTY_FUNCTION__
);
5697 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5698 zlog_warn("Recv MACIP DEL for non-default VRF %u",
5705 while (l
< hdr
->length
) {
5706 /* Obtain each remote VTEP and process. */
5707 STREAM_GETL(s
, vni
);
5709 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5710 l
+= IPV4_MAX_BYTELEN
;
5712 if (IS_ZEBRA_DEBUG_VXLAN
)
5713 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
5714 inet_ntoa(vtep_ip
), vni
,
5715 zebra_route_string(client
->proto
));
5717 /* Locate VNI hash entry - expected to exist. */
5718 zvni
= zvni_lookup(vni
);
5720 if (IS_ZEBRA_DEBUG_VXLAN
)
5722 "Failed to locate VNI hash upon remote VTEP DEL, "
5728 ifp
= zvni
->vxlan_if
;
5731 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
5737 /* If down or not mapped to a bridge, we're done. */
5738 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5741 /* If the remote VTEP does not exist, there's nothing more to
5743 * Otherwise, uninstall any remote MACs pointing to this VTEP
5745 * then, the VTEP entry itself and remove it.
5747 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5751 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
5752 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
5753 zvni_vtep_uninstall(zvni
, &vtep_ip
);
5754 zvni_vtep_del(zvni
, zvtep
);
5762 * Handle message from client to add a remote VTEP for a VNI.
5764 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
5767 unsigned short l
= 0;
5769 struct in_addr vtep_ip
;
5771 struct interface
*ifp
;
5772 struct zebra_if
*zif
;
5774 if (!is_evpn_enabled()) {
5776 "%s: EVPN not enabled yet we received a vtep_add zapi call",
5777 __PRETTY_FUNCTION__
);
5781 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5782 zlog_warn("Recv MACIP ADD for non-default VRF %u",
5789 while (l
< hdr
->length
) {
5790 /* Obtain each remote VTEP and process. */
5791 STREAM_GETL(s
, vni
);
5793 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5794 l
+= IPV4_MAX_BYTELEN
;
5796 if (IS_ZEBRA_DEBUG_VXLAN
)
5797 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
5798 inet_ntoa(vtep_ip
), vni
,
5799 zebra_route_string(client
->proto
));
5801 /* Locate VNI hash entry - expected to exist. */
5802 zvni
= zvni_lookup(vni
);
5805 ZEBRA_ERR_VTEP_ADD_FAILED
,
5806 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
5811 ifp
= zvni
->vxlan_if
;
5814 ZEBRA_ERR_VTEP_ADD_FAILED
,
5815 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
5822 /* If down or not mapped to a bridge, we're done. */
5823 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5826 /* If the remote VTEP already exists,
5827 there's nothing more to do. */
5828 if (zvni_vtep_find(zvni
, &vtep_ip
))
5831 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5832 flog_err(ZEBRA_ERR_VTEP_ADD_FAILED
,
5833 "Failed to add remote VTEP, VNI %u zvni %p",
5838 zvni_vtep_install(zvni
, &vtep_ip
);
5846 * Add/Del gateway macip to evpn
5848 * 1. SVI interface on a vlan aware bridge
5849 * 2. SVI interface on a vlan unaware bridge
5850 * 3. vrr interface (MACVLAN) associated to a SVI
5851 * We advertise macip routes for an interface if it is associated to VxLan vlan
5853 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
5857 struct ethaddr macaddr
;
5858 zebra_vni_t
*zvni
= NULL
;
5860 memset(&ip
, 0, sizeof(struct ipaddr
));
5861 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5863 /* Check if EVPN is enabled. */
5864 if (!is_evpn_enabled())
5867 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
5868 struct interface
*svi_if
=
5869 NULL
; /* SVI corresponding to the MACVLAN */
5870 struct zebra_if
*ifp_zif
=
5871 NULL
; /* Zebra daemon specific info for MACVLAN */
5872 struct zebra_if
*svi_if_zif
=
5873 NULL
; /* Zebra daemon specific info for SVI*/
5875 ifp_zif
= ifp
->info
;
5880 * for a MACVLAN interface the link represents the svi_if
5882 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
5883 ifp_zif
->link_ifindex
);
5885 zlog_warn("MACVLAN %s(%u) without link information",
5886 ifp
->name
, ifp
->ifindex
);
5890 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
5892 * If it is a vlan aware bridge then the link gives the
5893 * bridge information
5895 struct interface
*svi_if_link
= NULL
;
5897 svi_if_zif
= svi_if
->info
;
5899 svi_if_link
= if_lookup_by_index_per_ns(
5900 zebra_ns_lookup(NS_DEFAULT
),
5901 svi_if_zif
->link_ifindex
);
5902 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
5904 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
5906 * If it is a vlan unaware bridge then svi is the bridge
5909 zvni
= zvni_from_svi(svi_if
, svi_if
);
5911 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
5912 struct zebra_if
*svi_if_zif
=
5913 NULL
; /* Zebra daemon specific info for SVI */
5914 struct interface
*svi_if_link
=
5915 NULL
; /* link info for the SVI = bridge info */
5917 svi_if_zif
= ifp
->info
;
5919 svi_if_link
= if_lookup_by_index_per_ns(
5920 zebra_ns_lookup(NS_DEFAULT
),
5921 svi_if_zif
->link_ifindex
);
5923 zvni
= zvni_from_svi(ifp
, svi_if_link
);
5925 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
5926 zvni
= zvni_from_svi(ifp
, ifp
);
5932 if (!zvni
->vxlan_if
) {
5933 zlog_warn("VNI %u hash %p doesn't have intf upon MACVLAN up",
5939 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
5941 if (p
->family
== AF_INET
) {
5942 ip
.ipa_type
= IPADDR_V4
;
5943 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
5944 sizeof(struct in_addr
));
5945 } else if (p
->family
== AF_INET6
) {
5946 ip
.ipa_type
= IPADDR_V6
;
5947 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
5948 sizeof(struct in6_addr
));
5953 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
5955 zvni_gw_macip_del(ifp
, zvni
, &ip
);
5961 * Handle SVI interface going down.
5962 * SVI can be associated to either L3-VNI or L2-VNI.
5963 * For L2-VNI: At this point, this is a NOP since
5964 * the kernel deletes the neighbor entries on this SVI (if any).
5965 * We only need to update the vrf corresponding to zvni.
5966 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
5969 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
5971 zebra_l3vni_t
*zl3vni
= NULL
;
5973 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5976 /* process l3-vni down */
5977 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
5979 /* remove association with svi-if */
5980 zl3vni
->svi_if
= NULL
;
5982 zebra_vni_t
*zvni
= NULL
;
5984 /* since we dont have svi corresponding to zvni, we associate it
5985 * to default vrf. Note: the corresponding neigh entries on the
5986 * SVI would have already been deleted */
5987 zvni
= zvni_from_svi(ifp
, link_if
);
5989 zvni
->vrf_id
= VRF_DEFAULT
;
5991 /* update the tenant vrf in BGP */
5992 zvni_send_add_to_client(zvni
);
5999 * Handle SVI interface coming up.
6000 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
6002 * For L2-VNI: we need to install any remote neighbors entried (used for
6004 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
6006 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
6008 zebra_vni_t
*zvni
= NULL
;
6009 zebra_l3vni_t
*zl3vni
= NULL
;
6011 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6014 /* associate with svi */
6015 zl3vni
->svi_if
= ifp
;
6017 /* process oper-up */
6018 if (is_l3vni_oper_up(zl3vni
))
6019 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6022 /* process SVI up for l2-vni */
6023 struct neigh_walk_ctx n_wctx
;
6025 zvni
= zvni_from_svi(ifp
, link_if
);
6029 if (!zvni
->vxlan_if
) {
6031 "VNI %u hash %p doesn't have intf upon SVI up",
6036 if (IS_ZEBRA_DEBUG_VXLAN
)
6038 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
6039 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
6040 vrf_id_to_name(ifp
->vrf_id
));
6042 /* update the vrf information for l2-vni and inform bgp */
6043 zvni
->vrf_id
= ifp
->vrf_id
;
6044 zvni_send_add_to_client(zvni
);
6046 /* Install any remote neighbors for this VNI. */
6047 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6049 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6057 * Handle VxLAN interface down
6059 int zebra_vxlan_if_down(struct interface
*ifp
)
6062 struct zebra_if
*zif
= NULL
;
6063 struct zebra_l2info_vxlan
*vxl
= NULL
;
6064 zebra_l3vni_t
*zl3vni
= NULL
;
6067 /* Check if EVPN is enabled. */
6068 if (!is_evpn_enabled())
6073 vxl
= &zif
->l2info
.vxl
;
6076 zl3vni
= zl3vni_lookup(vni
);
6078 /* process-if-down for l3-vni */
6079 if (IS_ZEBRA_DEBUG_VXLAN
)
6080 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
6083 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6085 /* process if-down for l2-vni */
6086 if (IS_ZEBRA_DEBUG_VXLAN
)
6087 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
6090 /* Locate hash entry; it is expected to exist. */
6091 zvni
= zvni_lookup(vni
);
6094 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
6095 ifp
->name
, ifp
->ifindex
, vni
);
6099 assert(zvni
->vxlan_if
== ifp
);
6101 /* Delete this VNI from BGP. */
6102 zvni_send_del_to_client(zvni
->vni
);
6104 /* Free up all neighbors and MACs, if any. */
6105 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6106 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6108 /* Free up all remote VTEPs, if any. */
6109 zvni_vtep_del_all(zvni
, 1);
6115 * Handle VxLAN interface up - update BGP if required.
6117 int zebra_vxlan_if_up(struct interface
*ifp
)
6120 struct zebra_if
*zif
= NULL
;
6121 struct zebra_l2info_vxlan
*vxl
= NULL
;
6122 zebra_vni_t
*zvni
= NULL
;
6123 zebra_l3vni_t
*zl3vni
= NULL
;
6125 /* Check if EVPN is enabled. */
6126 if (!is_evpn_enabled())
6131 vxl
= &zif
->l2info
.vxl
;
6134 zl3vni
= zl3vni_lookup(vni
);
6137 if (IS_ZEBRA_DEBUG_VXLAN
)
6138 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
6141 /* we need to associate with SVI, if any, we can associate with
6142 * svi-if only after association with vxlan-intf is complete
6144 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6146 if (is_l3vni_oper_up(zl3vni
))
6147 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6149 /* Handle L2-VNI add */
6150 struct interface
*vlan_if
= NULL
;
6152 if (IS_ZEBRA_DEBUG_VXLAN
)
6153 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
6156 /* Locate hash entry; it is expected to exist. */
6157 zvni
= zvni_lookup(vni
);
6160 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
6161 ifp
->name
, ifp
->ifindex
, vni
);
6165 assert(zvni
->vxlan_if
== ifp
);
6166 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6167 zif
->brslave_info
.br_if
);
6169 zvni
->vrf_id
= vlan_if
->vrf_id
;
6170 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6172 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6175 /* If part of a bridge, inform BGP about this VNI. */
6176 /* Also, read and populate local MACs and neighbors. */
6177 if (zif
->brslave_info
.br_if
) {
6178 zvni_send_add_to_client(zvni
);
6179 zvni_read_mac_neigh(zvni
, ifp
);
6187 * Handle VxLAN interface delete. Locate and remove entry in hash table
6188 * and update BGP, if required.
6190 int zebra_vxlan_if_del(struct interface
*ifp
)
6193 struct zebra_if
*zif
= NULL
;
6194 struct zebra_l2info_vxlan
*vxl
= NULL
;
6195 zebra_vni_t
*zvni
= NULL
;
6196 zebra_l3vni_t
*zl3vni
= NULL
;
6198 /* Check if EVPN is enabled. */
6199 if (!is_evpn_enabled())
6204 vxl
= &zif
->l2info
.vxl
;
6207 zl3vni
= zl3vni_lookup(vni
);
6210 if (IS_ZEBRA_DEBUG_VXLAN
)
6211 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
6214 /* process oper-down for l3-vni */
6215 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6217 /* remove the association with vxlan_if */
6218 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
6219 zl3vni
->vxlan_if
= NULL
;
6222 /* process if-del for l2-vni*/
6223 if (IS_ZEBRA_DEBUG_VXLAN
)
6224 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
6227 /* Locate hash entry; it is expected to exist. */
6228 zvni
= zvni_lookup(vni
);
6231 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6232 ifp
->name
, ifp
->ifindex
, vni
);
6236 /* remove from l3-vni list */
6237 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
6239 listnode_delete(zl3vni
->l2vnis
, zvni
);
6241 /* Delete VNI from BGP. */
6242 zvni_send_del_to_client(zvni
->vni
);
6244 /* Free up all neighbors and MAC, if any. */
6245 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
6246 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
6248 /* Free up all remote VTEPs, if any. */
6249 zvni_vtep_del_all(zvni
, 0);
6251 /* Delete the hash entry. */
6252 if (zvni_del(zvni
)) {
6253 flog_err(ZEBRA_ERR_VNI_DEL_FAILED
,
6254 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
6255 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
6263 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6265 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
6268 struct zebra_if
*zif
= NULL
;
6269 struct zebra_l2info_vxlan
*vxl
= NULL
;
6270 zebra_vni_t
*zvni
= NULL
;
6271 zebra_l3vni_t
*zl3vni
= NULL
;
6273 /* Check if EVPN is enabled. */
6274 if (!is_evpn_enabled())
6279 vxl
= &zif
->l2info
.vxl
;
6282 zl3vni
= zl3vni_lookup(vni
);
6285 if (IS_ZEBRA_DEBUG_VXLAN
)
6287 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6288 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6289 inet_ntoa(vxl
->vtep_ip
),
6290 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6292 /* Removed from bridge? Cleanup and return */
6293 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6294 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6295 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6299 /* access-vlan change - process oper down, associate with new
6300 * svi_if and then process oper up again
6302 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6303 if (if_is_operative(ifp
)) {
6304 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6305 zl3vni
->svi_if
= NULL
;
6306 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6307 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6308 if (is_l3vni_oper_up(zl3vni
))
6309 zebra_vxlan_process_l3vni_oper_up(
6315 * local-ip change - process oper down, associate with new
6316 * local-ip and then process oper up again
6318 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
6319 if (if_is_operative(ifp
)) {
6320 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6321 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6322 if (is_l3vni_oper_up(zl3vni
))
6323 zebra_vxlan_process_l3vni_oper_up(
6328 /* Update local tunnel IP. */
6329 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6331 /* if we have a valid new master, process l3-vni oper up */
6332 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
6333 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
6334 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6338 /* Update VNI hash. */
6339 zvni
= zvni_lookup(vni
);
6342 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6343 ifp
->name
, ifp
->ifindex
, vni
);
6347 if (IS_ZEBRA_DEBUG_VXLAN
)
6349 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6350 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6351 inet_ntoa(vxl
->vtep_ip
),
6352 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6354 /* Removed from bridge? Cleanup and return */
6355 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6356 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6357 /* Delete from client, remove all remote VTEPs */
6358 /* Also, free up all MACs and neighbors. */
6359 zvni_send_del_to_client(zvni
->vni
);
6360 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6361 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6362 zvni_vtep_del_all(zvni
, 1);
6366 /* Handle other changes. */
6367 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6368 /* Remove all existing local neigh and MACs for this VNI
6369 * (including from BGP)
6371 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6372 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6375 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6376 zvni
->vxlan_if
= ifp
;
6378 /* Take further actions needed.
6379 * Note that if we are here, there is a change of interest.
6381 /* If down or not mapped to a bridge, we're done. */
6382 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6385 /* Inform BGP, if there is a change of interest. */
6387 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
6388 zvni_send_add_to_client(zvni
);
6390 /* If there is a valid new master or a VLAN mapping change,
6391 * read and populate local MACs and neighbors.
6392 * Also, reinstall any remote MACs and neighbors
6393 * for this VNI (based on new VLAN).
6395 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6396 zvni_read_mac_neigh(zvni
, ifp
);
6397 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6398 struct mac_walk_ctx m_wctx
;
6399 struct neigh_walk_ctx n_wctx
;
6401 zvni_read_mac_neigh(zvni
, ifp
);
6403 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6405 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
6408 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6410 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6419 * Handle VxLAN interface add.
6421 int zebra_vxlan_if_add(struct interface
*ifp
)
6424 struct zebra_if
*zif
= NULL
;
6425 struct zebra_l2info_vxlan
*vxl
= NULL
;
6426 zebra_vni_t
*zvni
= NULL
;
6427 zebra_l3vni_t
*zl3vni
= NULL
;
6429 /* Check if EVPN is enabled. */
6430 if (!is_evpn_enabled())
6435 vxl
= &zif
->l2info
.vxl
;
6438 zl3vni
= zl3vni_lookup(vni
);
6441 /* process if-add for l3-vni*/
6442 if (IS_ZEBRA_DEBUG_VXLAN
)
6444 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6445 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6446 inet_ntoa(vxl
->vtep_ip
),
6447 zif
->brslave_info
.bridge_ifindex
);
6449 /* associate with vxlan_if */
6450 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6451 zl3vni
->vxlan_if
= ifp
;
6453 /* Associate with SVI, if any. We can associate with svi-if only
6454 * after association with vxlan_if is complete */
6455 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6457 if (is_l3vni_oper_up(zl3vni
))
6458 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6461 /* process if-add for l2-vni */
6462 struct interface
*vlan_if
= NULL
;
6464 /* Create or update VNI hash. */
6465 zvni
= zvni_lookup(vni
);
6467 zvni
= zvni_add(vni
);
6470 ZEBRA_ERR_VNI_ADD_FAILED
,
6471 "Failed to add VNI hash, IF %s(%u) VNI %u",
6472 ifp
->name
, ifp
->ifindex
, vni
);
6477 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6478 zvni
->vxlan_if
= ifp
;
6479 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6480 zif
->brslave_info
.br_if
);
6482 zvni
->vrf_id
= vlan_if
->vrf_id
;
6483 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6485 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6488 if (IS_ZEBRA_DEBUG_VXLAN
)
6490 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6492 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
6494 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6495 inet_ntoa(vxl
->vtep_ip
),
6496 zif
->brslave_info
.bridge_ifindex
);
6498 /* If down or not mapped to a bridge, we're done. */
6499 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6503 zvni_send_add_to_client(zvni
);
6505 /* Read and populate local MACs and neighbors */
6506 zvni_read_mac_neigh(zvni
, ifp
);
6512 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
6513 char *err
, int err_str_sz
, int filter
,
6516 zebra_l3vni_t
*zl3vni
= NULL
;
6517 struct zebra_vrf
*zvrf_default
= NULL
;
6519 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
6523 if (IS_ZEBRA_DEBUG_VXLAN
)
6524 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
6525 add
? "ADD" : "DEL");
6529 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6531 /* check if the vni is already present under zvrf */
6533 snprintf(err
, err_str_sz
,
6534 "VNI is already configured under the vrf");
6538 /* check if this VNI is already present in the system */
6539 zl3vni
= zl3vni_lookup(vni
);
6541 snprintf(err
, err_str_sz
,
6542 "VNI is already configured as L3-VNI");
6546 /* add the L3-VNI to the global table */
6547 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
6549 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
6553 /* associate the vrf with vni */
6556 /* set the filter in l3vni to denote if we are using l3vni only
6560 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
6562 /* associate with vxlan-intf;
6563 * we need to associate with the vxlan-intf first
6565 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
6567 /* associate with corresponding SVI interface, we can associate
6568 * with svi-if only after vxlan interface association is
6571 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6573 /* formulate l2vni list */
6574 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
6577 if (is_l3vni_oper_up(zl3vni
))
6578 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6581 zl3vni
= zl3vni_lookup(vni
);
6583 snprintf(err
, err_str_sz
, "VNI doesn't exist");
6587 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
6588 snprintf(err
, ERR_STR_SZ
,
6589 "prefix-routes-only is not set for the vni");
6593 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6595 /* delete and uninstall all rmacs */
6596 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
6599 /* delete and uninstall all next-hops */
6600 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
6606 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6611 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
6613 zebra_l3vni_t
*zl3vni
= NULL
;
6616 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6620 zl3vni
->vrf_id
= zvrf_id(zvrf
);
6621 if (is_l3vni_oper_up(zl3vni
))
6622 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6626 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
6628 zebra_l3vni_t
*zl3vni
= NULL
;
6631 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6635 zl3vni
->vrf_id
= VRF_UNKNOWN
;
6636 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6640 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
6642 zebra_l3vni_t
*zl3vni
= NULL
;
6646 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6652 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
6658 * Handle message from client to enable/disable advertisement of g/w macip
6661 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
6666 zebra_vni_t
*zvni
= NULL
;
6667 struct interface
*ifp
= NULL
;
6668 struct zebra_if
*zif
= NULL
;
6669 struct zebra_l2info_vxlan zl2_info
;
6670 struct interface
*vlan_if
= NULL
;
6672 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6673 zlog_warn("EVPN GW-MACIP Adv for non-default VRF %u",
6679 STREAM_GETC(s
, advertise
);
6680 vni
= stream_get3(s
);
6682 zvni
= zvni_lookup(vni
);
6686 if (zvni
->advertise_subnet
== advertise
)
6689 if (IS_ZEBRA_DEBUG_VXLAN
)
6690 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
6691 advertise
? "enabled" : "disabled", vni
,
6692 zvni
->advertise_subnet
? "enabled" : "disabled");
6695 zvni
->advertise_subnet
= advertise
;
6697 ifp
= zvni
->vxlan_if
;
6703 /* If down or not mapped to a bridge, we're done. */
6704 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6707 zl2_info
= zif
->l2info
.vxl
;
6710 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
6714 if (zvni
->advertise_subnet
)
6715 zvni_advertise_subnet(zvni
, vlan_if
, 1);
6717 zvni_advertise_subnet(zvni
, vlan_if
, 0);
6724 * Handle message from client to enable/disable advertisement of g/w macip
6727 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
6732 zebra_vni_t
*zvni
= NULL
;
6733 struct interface
*ifp
= NULL
;
6735 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6736 zlog_warn("EVPN GW-MACIP Adv for non-default VRF %u",
6742 STREAM_GETC(s
, advertise
);
6743 STREAM_GETL(s
, vni
);
6746 if (IS_ZEBRA_DEBUG_VXLAN
)
6747 zlog_debug("EVPN gateway macip Adv %s, currently %s",
6748 advertise
? "enabled" : "disabled",
6749 advertise_gw_macip_enabled(NULL
)
6753 if (zvrf
->advertise_gw_macip
== advertise
)
6756 zvrf
->advertise_gw_macip
= advertise
;
6758 if (advertise_gw_macip_enabled(zvni
))
6759 hash_iterate(zvrf
->vni_table
,
6760 zvni_gw_macip_add_for_vni_hash
, NULL
);
6762 hash_iterate(zvrf
->vni_table
,
6763 zvni_gw_macip_del_for_vni_hash
, NULL
);
6766 struct zebra_if
*zif
= NULL
;
6767 struct zebra_l2info_vxlan zl2_info
;
6768 struct interface
*vlan_if
= NULL
;
6769 struct interface
*vrr_if
= NULL
;
6771 zvni
= zvni_lookup(vni
);
6775 if (IS_ZEBRA_DEBUG_VXLAN
)
6777 "EVPN gateway macip Adv %s on VNI %d , currently %s",
6778 advertise
? "enabled" : "disabled", vni
,
6779 advertise_gw_macip_enabled(zvni
) ? "enabled"
6782 if (zvni
->advertise_gw_macip
== advertise
)
6785 zvni
->advertise_gw_macip
= advertise
;
6787 ifp
= zvni
->vxlan_if
;
6793 /* If down or not mapped to a bridge, we're done. */
6794 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6797 zl2_info
= zif
->l2info
.vxl
;
6799 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
6800 zif
->brslave_info
.br_if
);
6804 if (advertise_gw_macip_enabled(zvni
)) {
6805 /* Add primary SVI MAC-IP */
6806 zvni_add_macip_for_intf(vlan_if
, zvni
);
6808 /* Add VRR MAC-IP - if any*/
6809 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6811 zvni_add_macip_for_intf(vrr_if
, zvni
);
6813 /* Del primary MAC-IP */
6814 zvni_del_macip_for_intf(vlan_if
, zvni
);
6816 /* Del VRR MAC-IP - if any*/
6817 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6819 zvni_del_macip_for_intf(vrr_if
, zvni
);
6829 * Handle message from client to learn (or stop learning) about VNIs and MACs.
6830 * When enabled, the VNI hash table will be built and MAC FDB table read;
6831 * when disabled, the entries should be deleted and remote VTEPs and MACs
6832 * uninstalled from the kernel.
6834 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
6836 struct stream
*s
= NULL
;
6838 struct zebra_ns
*zns
= NULL
;
6840 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6841 zlog_warn("EVPN VNI Adv for non-default VRF %u", zvrf_id(zvrf
));
6846 STREAM_GETC(s
, advertise
);
6848 if (IS_ZEBRA_DEBUG_VXLAN
)
6849 zlog_debug("EVPN VNI Adv %s, currently %s",
6850 advertise
? "enabled" : "disabled",
6851 is_evpn_enabled() ? "enabled" : "disabled");
6853 if (zvrf
->advertise_all_vni
== advertise
)
6856 zvrf
->advertise_all_vni
= advertise
;
6857 if (is_evpn_enabled()) {
6858 /* Build VNI hash table and inform BGP. */
6859 zvni_build_hash_table();
6861 /* Add all SVI (L3 GW) MACs to BGP*/
6862 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
6865 /* Read the MAC FDB */
6866 macfdb_read(zvrf
->zns
);
6868 /* Read neighbors */
6869 neigh_read(zvrf
->zns
);
6871 /* Cleanup VTEPs for all VNIs - uninstall from
6872 * kernel and free entries.
6874 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6876 /* cleanup all l3vnis */
6877 zns
= zebra_ns_lookup(NS_DEFAULT
);
6881 hash_iterate(zns
->l3vni_table
, zl3vni_cleanup_all
, NULL
);
6889 * Allocate VNI hash table for this VRF and do other initialization.
6890 * NOTE: Currently supported only for default VRF.
6892 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
6896 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
6897 "Zebra VRF VNI Table");
6900 /* Cleanup VNI info, but don't free the table. */
6901 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
6905 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6908 /* Close all VNI handling */
6909 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
6913 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6914 hash_free(zvrf
->vni_table
);
6917 /* init the l3vni table */
6918 void zebra_vxlan_ns_init(struct zebra_ns
*zns
)
6920 zns
->l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
6921 "Zebra VRF L3 VNI table");
6924 /* free l3vni table */
6925 void zebra_vxlan_ns_disable(struct zebra_ns
*zns
)
6927 hash_free(zns
->l3vni_table
);
6930 /* get the l3vni svi ifindex */
6931 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
6933 zebra_l3vni_t
*zl3vni
= NULL
;
6935 zl3vni
= zl3vni_from_vrf(vrf_id
);
6936 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
6939 return zl3vni
->svi_if
->ifindex
;