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
,
82 uint32_t seq
, uint16_t cmd
);
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
,
96 uint8_t flags
, uint32_t seq
);
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
,
150 uint8_t flags
, uint32_t seq
);
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
);
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 int remote_neigh_count(zebra_mac_t
*zmac
);
184 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
)
210 } else if (hle1
->p
.family
== AF_INET6
) {
211 return memcmp(&hle1
->p
.u
.prefix6
, &hle2
->p
.u
.prefix6
,
214 zlog_debug("%s: Unexpected family type: %d",
215 __PRETTY_FUNCTION__
, hle1
->p
.family
);
219 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
221 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
223 struct host_rb_entry
*hle
;
226 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
233 * Return number of valid MACs in a VNI's MAC hash table - all
234 * remote MACs and non-internal (auto) local MACs count.
236 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
239 uint32_t num_macs
= 0;
241 struct hash_backet
*hb
;
244 hash
= zvni
->mac_table
;
247 for (i
= 0; i
< hash
->size
; i
++) {
248 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
249 mac
= (zebra_mac_t
*)hb
->data
;
250 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
251 || CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
252 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
260 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
262 struct zebra_vrf
*zvrf
;
264 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
265 if (zvrf
&& zvrf
->advertise_gw_macip
)
268 if (zvni
&& zvni
->advertise_gw_macip
)
275 * Helper function to determine maximum width of neighbor IP address for
276 * display - just because we're dealing with IPv6 addresses that can
279 static void zvni_find_neigh_addr_width(struct hash_backet
*backet
, void *ctxt
)
282 char buf
[INET6_ADDRSTRLEN
];
283 struct neigh_walk_ctx
*wctx
= ctxt
;
286 n
= (zebra_neigh_t
*)backet
->data
;
288 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
290 if (width
> wctx
->addr_width
)
291 wctx
->addr_width
= width
;
296 * Print a specific neighbor entry.
298 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
301 char buf1
[ETHER_ADDR_STRLEN
];
302 char buf2
[INET6_ADDRSTRLEN
];
303 const char *type_str
;
304 const char *state_str
;
305 bool flags_present
= false;
307 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
308 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
309 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
311 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
312 vty
= (struct vty
*)ctxt
;
314 vty_out(vty
, "IP: %s\n",
315 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
316 vty_out(vty
, " Type: %s\n", type_str
);
317 vty_out(vty
, " State: %s\n", state_str
);
318 vty_out(vty
, " MAC: %s\n",
319 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
321 json_object_string_add(json
, "ip", buf2
);
322 json_object_string_add(json
, "type", type_str
);
323 json_object_string_add(json
, "state", state_str
);
324 json_object_string_add(json
, "mac", buf1
);
326 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
328 vty_out(vty
, " Remote VTEP: %s\n",
329 inet_ntoa(n
->r_vtep_ip
));
331 json_object_string_add(json
, "remoteVtep",
332 inet_ntoa(n
->r_vtep_ip
));
334 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
336 vty_out(vty
, " Flags: Default-gateway");
337 flags_present
= true;
339 json_object_boolean_true_add(json
, "defaultGateway");
341 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
344 flags_present
? " ,Router" : " Flags: Router");
345 flags_present
= true;
351 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
352 n
->loc_seq
, n
->rem_seq
);
354 json_object_int_add(json
, "localSequence", n
->loc_seq
);
355 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
360 * Print neighbor hash entry - called for display of all neighbors.
362 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
365 json_object
*json_vni
= NULL
, *json_row
= NULL
;
367 char buf1
[ETHER_ADDR_STRLEN
];
368 char buf2
[INET6_ADDRSTRLEN
];
369 struct neigh_walk_ctx
*wctx
= ctxt
;
370 const char *state_str
;
373 json_vni
= wctx
->json
;
374 n
= (zebra_neigh_t
*)backet
->data
;
377 json_row
= json_object_new_object();
379 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
380 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
381 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
382 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
383 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
386 if (json_vni
== NULL
) {
387 vty_out(vty
, "%*s %-6s %-8s %-17s\n",
388 -wctx
->addr_width
, buf2
, "local",
391 json_object_string_add(json_row
, "type", "local");
392 json_object_string_add(json_row
, "state", state_str
);
393 json_object_string_add(json_row
, "mac", buf1
);
394 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
395 json_object_boolean_true_add(
396 json_row
, "defaultGateway");
397 json_object_int_add(json_row
, "localSequence",
399 json_object_int_add(json_row
, "remoteSequence",
403 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
404 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
405 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
408 if (json_vni
== NULL
) {
409 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
412 "%*s %-6s %-8s %-17s %-21s\n",
413 -wctx
->addr_width
, "Neighbor", "Type",
414 "State", "MAC", "Remote VTEP");
415 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
416 -wctx
->addr_width
, buf2
, "remote", state_str
,
417 buf1
, inet_ntoa(n
->r_vtep_ip
));
419 json_object_string_add(json_row
, "type", "remote");
420 json_object_string_add(json_row
, "state", state_str
);
421 json_object_string_add(json_row
, "mac", buf1
);
422 json_object_string_add(json_row
, "remoteVtep",
423 inet_ntoa(n
->r_vtep_ip
));
424 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
425 json_object_boolean_true_add(json_row
,
427 json_object_int_add(json_row
, "localSequence",
429 json_object_int_add(json_row
, "remoteSequence",
436 json_object_object_add(json_vni
, buf2
, json_row
);
440 * Print neighbors for all VNI.
442 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
446 json_object
*json
= NULL
, *json_vni
= NULL
;
449 struct neigh_walk_ctx wctx
;
450 char vni_str
[VNI_STR_LEN
];
452 vty
= (struct vty
*)args
[0];
453 json
= (json_object
*)args
[1];
455 zvni
= (zebra_vni_t
*)backet
->data
;
457 num_neigh
= hashcount(zvni
->neigh_table
);
460 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
461 zvni
->vni
, num_neigh
);
463 json_vni
= json_object_new_object();
464 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
465 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
469 json_object_object_add(json
, vni_str
, json_vni
);
473 /* Since we have IPv6 addresses to deal with which can vary widely in
474 * size, we try to be a bit more elegant in display by first computing
477 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
480 wctx
.addr_width
= 15;
481 wctx
.json
= json_vni
;
482 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
485 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
486 -wctx
.addr_width
, "IP", "Type",
487 "State", "MAC", "Remote VTEP");
489 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
492 json_object_object_add(json
, vni_str
, json_vni
);
495 /* print a specific next hop for an l3vni */
496 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
499 char buf1
[ETHER_ADDR_STRLEN
];
500 char buf2
[INET6_ADDRSTRLEN
];
501 json_object
*json_hosts
= NULL
;
502 struct host_rb_entry
*hle
;
505 vty_out(vty
, "Ip: %s\n",
506 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
507 vty_out(vty
, " RMAC: %s\n",
508 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
509 vty_out(vty
, " Refcount: %d\n",
510 rb_host_count(&n
->host_rb
));
511 vty_out(vty
, " Prefixes:\n");
512 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
513 vty_out(vty
, " %s\n",
514 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
516 json_hosts
= json_object_new_array();
517 json_object_string_add(
518 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
519 json_object_string_add(
521 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
522 json_object_int_add(json
, "refCount",
523 rb_host_count(&n
->host_rb
));
524 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
525 json_object_array_add(json_hosts
,
526 json_object_new_string(prefix2str(
527 &hle
->p
, buf2
, sizeof(buf2
))));
528 json_object_object_add(json
, "prefixList", json_hosts
);
532 /* Print a specific RMAC entry */
533 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
536 char buf1
[ETHER_ADDR_STRLEN
];
537 char buf2
[PREFIX_STRLEN
];
538 json_object
*json_hosts
= NULL
;
539 struct host_rb_entry
*hle
;
542 vty_out(vty
, "MAC: %s\n",
543 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
544 vty_out(vty
, " Remote VTEP: %s\n",
545 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
546 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
547 vty_out(vty
, " Prefixes:\n");
548 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
549 vty_out(vty
, " %s\n",
550 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
552 json_hosts
= json_object_new_array();
553 json_object_string_add(
555 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
556 json_object_string_add(json
, "vtepIp",
557 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
558 json_object_int_add(json
, "refCount",
559 rb_host_count(&zrmac
->host_rb
));
560 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
561 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
562 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
563 json_object_array_add(
565 json_object_new_string(prefix2str(
566 &hle
->p
, buf2
, sizeof(buf2
))));
567 json_object_object_add(json
, "prefixList", json_hosts
);
572 * Print a specific MAC entry.
574 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
)
577 zebra_neigh_t
*n
= NULL
;
578 struct listnode
*node
= NULL
;
580 char buf2
[INET6_ADDRSTRLEN
];
582 vty
= (struct vty
*)ctxt
;
583 vty_out(vty
, "MAC: %s",
584 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
)));
585 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
586 struct zebra_ns
*zns
;
587 struct interface
*ifp
;
590 ifindex
= mac
->fwd_info
.local
.ifindex
;
591 zns
= zebra_ns_lookup(NS_DEFAULT
);
592 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
593 if (!ifp
) // unexpected
595 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
596 if (mac
->fwd_info
.local
.vid
)
597 vty_out(vty
, " VLAN: %u", mac
->fwd_info
.local
.vid
);
598 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
599 vty_out(vty
, " Remote VTEP: %s",
600 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
601 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
602 vty_out(vty
, " Auto Mac ");
605 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
606 vty_out(vty
, " Sticky Mac ");
608 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
609 vty_out(vty
, " Default-gateway Mac ");
611 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
612 vty_out(vty
, " Remote-gateway Mac ");
615 vty_out(vty
, " Local Seq: %u Remote Seq: %u",
616 mac
->loc_seq
, mac
->rem_seq
);
619 /* print all the associated neigh */
620 vty_out(vty
, " Neighbors:\n");
621 if (!listcount(mac
->neigh_list
))
622 vty_out(vty
, " No Neighbors\n");
624 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
625 vty_out(vty
, " %s %s\n",
626 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
627 (IS_ZEBRA_NEIGH_ACTIVE(n
)
628 ? "Active" : "Inactive"));
636 * Print MAC hash entry - called for display of all MACs.
638 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
641 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
644 struct mac_walk_ctx
*wctx
= ctxt
;
647 json_mac_hdr
= wctx
->json
;
648 mac
= (zebra_mac_t
*)backet
->data
;
650 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
653 json_mac
= json_object_new_object();
655 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
656 struct zebra_ns
*zns
;
658 struct interface
*ifp
;
661 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
664 zns
= zebra_ns_lookup(NS_DEFAULT
);
665 ifindex
= mac
->fwd_info
.local
.ifindex
;
666 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
667 if (!ifp
) // unexpected
669 vid
= mac
->fwd_info
.local
.vid
;
670 if (json_mac_hdr
== NULL
)
671 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
674 json_object_string_add(json_mac
, "type", "local");
675 json_object_string_add(json_mac
, "intf", ifp
->name
);
678 if (json_mac_hdr
== NULL
)
679 vty_out(vty
, " %-5u", vid
);
681 json_object_int_add(json_mac
, "vlan", vid
);
683 if (json_mac_hdr
== NULL
) {
686 json_object_int_add(json_mac
, "localSequence",
688 json_object_int_add(json_mac
, "remoteSequence",
690 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
695 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
697 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
698 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
702 if (json_mac_hdr
== NULL
) {
703 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
704 (wctx
->count
== 0)) {
705 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
706 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC",
707 "Type", "Intf/Remote VTEP", "VLAN");
709 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
, "remote",
710 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
712 json_object_string_add(json_mac
, "type", "remote");
713 json_object_string_add(json_mac
, "remoteVtep",
714 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
715 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
716 json_object_int_add(json_mac
, "localSequence",
718 json_object_int_add(json_mac
, "remoteSequence",
727 * Print MACs for all VNI.
729 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
732 json_object
*json
= NULL
, *json_vni
= NULL
;
733 json_object
*json_mac
= NULL
;
736 struct mac_walk_ctx
*wctx
= ctxt
;
737 char vni_str
[VNI_STR_LEN
];
739 vty
= (struct vty
*)wctx
->vty
;
740 json
= (struct json_object
*)wctx
->json
;
742 zvni
= (zebra_vni_t
*)backet
->data
;
745 /*We are iterating over a new VNI, set the count to 0*/
748 num_macs
= num_valid_macs(zvni
);
753 json_vni
= json_object_new_object();
754 json_mac
= json_object_new_object();
755 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
758 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
760 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
761 zvni
->vni
, num_macs
);
762 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
763 "Intf/Remote VTEP", "VLAN");
765 json_object_int_add(json_vni
, "numMacs", num_macs
);
767 /* assign per-vni to wctx->json object to fill macs
768 * under the vni. Re-assign primary json object to fill
769 * next vni information.
771 wctx
->json
= json_mac
;
772 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
776 json_object_object_add(json_vni
, "macs", json_mac
);
777 json_object_object_add(json
, vni_str
, json_vni
);
781 static void zl3vni_print_nh_hash(struct hash_backet
*backet
, void *ctx
)
783 struct nh_walk_ctx
*wctx
= NULL
;
784 struct vty
*vty
= NULL
;
785 struct json_object
*json_vni
= NULL
;
786 struct json_object
*json_nh
= NULL
;
787 zebra_neigh_t
*n
= NULL
;
788 char buf1
[ETHER_ADDR_STRLEN
];
789 char buf2
[INET6_ADDRSTRLEN
];
791 wctx
= (struct nh_walk_ctx
*)ctx
;
793 json_vni
= wctx
->json
;
795 json_nh
= json_object_new_object();
796 n
= (zebra_neigh_t
*)backet
->data
;
799 vty_out(vty
, "%-15s %-17s\n",
800 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
801 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
803 json_object_string_add(json_nh
, "nexthopIp",
804 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
805 json_object_string_add(
806 json_nh
, "routerMac",
807 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
808 json_object_object_add(json_vni
,
809 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
814 static void zl3vni_print_nh_hash_all_vni(struct hash_backet
*backet
,
817 struct vty
*vty
= NULL
;
818 json_object
*json
= NULL
;
819 json_object
*json_vni
= NULL
;
820 zebra_l3vni_t
*zl3vni
= NULL
;
822 struct nh_walk_ctx wctx
;
823 char vni_str
[VNI_STR_LEN
];
825 vty
= (struct vty
*)args
[0];
826 json
= (struct json_object
*)args
[1];
828 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
830 num_nh
= hashcount(zl3vni
->nh_table
);
835 json_vni
= json_object_new_object();
836 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
840 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
841 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
843 json_object_int_add(json_vni
, "numNextHops", num_nh
);
845 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
847 wctx
.json
= json_vni
;
848 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
850 json_object_object_add(json
, vni_str
, json_vni
);
853 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet
*backet
,
856 struct vty
*vty
= NULL
;
857 json_object
*json
= NULL
;
858 json_object
*json_vni
= NULL
;
859 zebra_l3vni_t
*zl3vni
= NULL
;
861 struct rmac_walk_ctx wctx
;
862 char vni_str
[VNI_STR_LEN
];
864 vty
= (struct vty
*)args
[0];
865 json
= (struct json_object
*)args
[1];
867 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
869 num_rmacs
= hashcount(zl3vni
->rmac_table
);
874 json_vni
= json_object_new_object();
875 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
879 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
880 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
882 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
884 /* assign per-vni to wctx->json object to fill macs
885 * under the vni. Re-assign primary json object to fill
886 * next vni information.
888 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
890 wctx
.json
= json_vni
;
891 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
893 json_object_object_add(json
, vni_str
, json_vni
);
896 static void zl3vni_print_rmac_hash(struct hash_backet
*backet
, void *ctx
)
898 zebra_mac_t
*zrmac
= NULL
;
899 struct rmac_walk_ctx
*wctx
= NULL
;
900 struct vty
*vty
= NULL
;
901 struct json_object
*json
= NULL
;
902 struct json_object
*json_rmac
= NULL
;
903 char buf
[ETHER_ADDR_STRLEN
];
905 wctx
= (struct rmac_walk_ctx
*)ctx
;
909 json_rmac
= json_object_new_object();
910 zrmac
= (zebra_mac_t
*)backet
->data
;
913 vty_out(vty
, "%-17s %-21s\n",
914 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
915 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
917 json_object_string_add(
918 json_rmac
, "routerMac",
919 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
920 json_object_string_add(json_rmac
, "vtepIp",
921 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
922 json_object_object_add(
923 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
928 /* print a specific L3 VNI entry */
929 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
931 char buf
[ETHER_ADDR_STRLEN
];
932 struct vty
*vty
= NULL
;
933 json_object
*json
= NULL
;
934 zebra_vni_t
*zvni
= NULL
;
935 json_object
*json_vni_list
= NULL
;
936 struct listnode
*node
= NULL
, *nnode
= NULL
;
942 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
943 vty_out(vty
, " Type: %s\n", "L3");
944 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
945 vty_out(vty
, " Local Vtep Ip: %s\n",
946 inet_ntoa(zl3vni
->local_vtep_ip
));
947 vty_out(vty
, " Vxlan-Intf: %s\n",
948 zl3vni_vxlan_if_name(zl3vni
));
949 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
950 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
951 vty_out(vty
, " VNI Filter: %s\n",
952 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
953 ? "prefix-routes-only"
955 vty_out(vty
, " Router MAC: %s\n",
956 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
957 vty_out(vty
, " L2 VNIs: ");
958 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
959 vty_out(vty
, "%u ", zvni
->vni
);
962 json_vni_list
= json_object_new_array();
963 json_object_int_add(json
, "vni", zl3vni
->vni
);
964 json_object_string_add(json
, "type", "L3");
965 json_object_string_add(json
, "localVtepIp",
966 inet_ntoa(zl3vni
->local_vtep_ip
));
967 json_object_string_add(json
, "vxlanIntf",
968 zl3vni_vxlan_if_name(zl3vni
));
969 json_object_string_add(json
, "sviIntf",
970 zl3vni_svi_if_name(zl3vni
));
971 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
972 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
973 json_object_string_add(
975 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
976 json_object_string_add(
978 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
979 ? "prefix-routes-only"
981 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
982 json_object_array_add(json_vni_list
,
983 json_object_new_int(zvni
->vni
));
985 json_object_object_add(json
, "l2Vnis", json_vni_list
);
990 * Print a specific VNI entry.
992 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
998 json_object
*json
= NULL
;
999 json_object
*json_vtep_list
= NULL
;
1000 json_object
*json_ip_str
= NULL
;
1006 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1007 vty_out(vty
, " Type: %s\n", "L2");
1008 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1010 json_object_int_add(json
, "vni", zvni
->vni
);
1011 json_object_string_add(json
, "type", "L2");
1012 json_object_string_add(json
, "vrf",
1013 vrf_id_to_name(zvni
->vrf_id
));
1016 if (!zvni
->vxlan_if
) { // unexpected
1018 vty_out(vty
, " VxLAN interface: unknown\n");
1021 num_macs
= num_valid_macs(zvni
);
1022 num_neigh
= hashcount(zvni
->neigh_table
);
1024 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1025 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1026 vty_out(vty
, " Local VTEP IP: %s\n",
1027 inet_ntoa(zvni
->local_vtep_ip
));
1029 json_object_string_add(json
, "vxlanInterface",
1030 zvni
->vxlan_if
->name
);
1031 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1032 json_object_string_add(json
, "vtepIp",
1033 inet_ntoa(zvni
->local_vtep_ip
));
1034 json_object_string_add(json
, "advertiseGatewayMacip",
1035 zvni
->advertise_gw_macip
? "Yes" : "No");
1036 json_object_int_add(json
, "numMacs", num_macs
);
1037 json_object_int_add(json
, "numArpNd", num_neigh
);
1041 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1044 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1046 json_vtep_list
= json_object_new_array();
1047 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1049 vty_out(vty
, " %s\n",
1050 inet_ntoa(zvtep
->vtep_ip
));
1052 json_ip_str
= json_object_new_string(
1053 inet_ntoa(zvtep
->vtep_ip
));
1054 json_object_array_add(json_vtep_list
,
1059 json_object_object_add(json
, "numRemoteVteps",
1064 " Number of MACs (local and remote) known for this VNI: %u\n",
1067 " Number of ARPs (IPv4 and IPv6, local and remote) "
1068 "known for this VNI: %u\n",
1070 vty_out(vty
, " Advertise-gw-macip: %s\n",
1071 zvni
->advertise_gw_macip
? "Yes" : "No");
1075 /* print a L3 VNI hash entry */
1076 static void zl3vni_print_hash(struct hash_backet
*backet
, void *ctx
[])
1078 struct vty
*vty
= NULL
;
1079 json_object
*json
= NULL
;
1080 json_object
*json_vni
= NULL
;
1081 zebra_l3vni_t
*zl3vni
= NULL
;
1083 vty
= (struct vty
*)ctx
[0];
1084 json
= (json_object
*)ctx
[1];
1086 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1089 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1090 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1091 hashcount(zl3vni
->rmac_table
),
1092 hashcount(zl3vni
->nh_table
), "n/a",
1093 zl3vni_vrf_name(zl3vni
));
1095 char vni_str
[VNI_STR_LEN
];
1097 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1098 json_vni
= json_object_new_object();
1099 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1100 json_object_string_add(json_vni
, "vxlanIf",
1101 zl3vni_vxlan_if_name(zl3vni
));
1102 json_object_int_add(json_vni
, "numMacs",
1103 hashcount(zl3vni
->rmac_table
));
1104 json_object_int_add(json_vni
, "numArpNd",
1105 hashcount(zl3vni
->nh_table
));
1106 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1107 json_object_string_add(json_vni
, "type", "L3");
1108 json_object_string_add(json_vni
, "tenantVrf",
1109 zl3vni_vrf_name(zl3vni
));
1110 json_object_object_add(json
, vni_str
, json_vni
);
1115 * Print a VNI hash entry - called for display of all VNIs.
1117 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1121 zebra_vtep_t
*zvtep
;
1122 uint32_t num_vteps
= 0;
1123 uint32_t num_macs
= 0;
1124 uint32_t num_neigh
= 0;
1125 json_object
*json
= NULL
;
1126 json_object
*json_vni
= NULL
;
1127 json_object
*json_ip_str
= NULL
;
1128 json_object
*json_vtep_list
= NULL
;
1133 zvni
= (zebra_vni_t
*)backet
->data
;
1135 zvtep
= zvni
->vteps
;
1138 zvtep
= zvtep
->next
;
1141 num_macs
= num_valid_macs(zvni
);
1142 num_neigh
= hashcount(zvni
->neigh_table
);
1144 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1146 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1147 num_macs
, num_neigh
, num_vteps
,
1148 vrf_id_to_name(zvni
->vrf_id
));
1150 char vni_str
[VNI_STR_LEN
];
1151 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1152 json_vni
= json_object_new_object();
1153 json_object_int_add(json_vni
, "vni", zvni
->vni
);
1154 json_object_string_add(json_vni
, "type", "L2");
1155 json_object_string_add(json_vni
, "vxlanIf",
1156 zvni
->vxlan_if
? zvni
->vxlan_if
->name
1158 json_object_int_add(json_vni
, "numMacs", num_macs
);
1159 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1160 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
1161 json_object_string_add(json_vni
, "tenantVrf",
1162 vrf_id_to_name(zvni
->vrf_id
));
1164 json_vtep_list
= json_object_new_array();
1165 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1166 json_ip_str
= json_object_new_string(
1167 inet_ntoa(zvtep
->vtep_ip
));
1168 json_object_array_add(json_vtep_list
,
1171 json_object_object_add(json_vni
, "remoteVteps",
1174 json_object_object_add(json
, vni_str
, json_vni
);
1179 * Inform BGP about local MACIP.
1181 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
1182 struct ipaddr
*ip
, uint8_t flags
,
1183 uint32_t seq
, uint16_t cmd
)
1185 char buf
[ETHER_ADDR_STRLEN
];
1186 char buf2
[INET6_ADDRSTRLEN
];
1188 struct zserv
*client
= NULL
;
1189 struct stream
*s
= NULL
;
1191 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
1192 /* BGP may not be running. */
1196 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
1198 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
1199 stream_putl(s
, vni
);
1200 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
1203 if (IS_IPADDR_V4(ip
))
1204 ipa_len
= IPV4_MAX_BYTELEN
;
1205 else if (IS_IPADDR_V6(ip
))
1206 ipa_len
= IPV6_MAX_BYTELEN
;
1208 stream_putl(s
, ipa_len
); /* IP address length */
1210 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
1212 stream_putl(s
, 0); /* Just MAC. */
1214 if (cmd
== ZEBRA_MACIP_ADD
) {
1215 stream_putc(s
, flags
); /* sticky mac/gateway mac */
1216 stream_putl(s
, seq
); /* sequence number */
1220 /* Write packet size. */
1221 stream_putw_at(s
, 0, stream_get_endp(s
));
1223 if (IS_ZEBRA_DEBUG_VXLAN
)
1225 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
1226 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
1227 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1228 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
1229 zebra_route_string(client
->proto
));
1231 if (cmd
== ZEBRA_MACIP_ADD
)
1232 client
->macipadd_cnt
++;
1234 client
->macipdel_cnt
++;
1236 return zserv_send_message(client
, s
);
1240 * Make hash key for neighbors.
1242 static unsigned int neigh_hash_keymake(void *p
)
1244 zebra_neigh_t
*n
= p
;
1245 struct ipaddr
*ip
= &n
->ip
;
1247 if (IS_IPADDR_V4(ip
))
1248 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
1250 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
1251 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
1255 * Compare two neighbor hash structures.
1257 static int neigh_cmp(const void *p1
, const void *p2
)
1259 const zebra_neigh_t
*n1
= p1
;
1260 const zebra_neigh_t
*n2
= p2
;
1262 if (n1
== NULL
&& n2
== NULL
)
1265 if (n1
== NULL
|| n2
== NULL
)
1268 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
1272 * Callback to allocate neighbor hash entry.
1274 static void *zvni_neigh_alloc(void *p
)
1276 const zebra_neigh_t
*tmp_n
= p
;
1279 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
1286 * Add neighbor entry.
1288 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
1289 struct ethaddr
*mac
)
1291 zebra_neigh_t tmp_n
;
1292 zebra_neigh_t
*n
= NULL
;
1293 zebra_mac_t
*zmac
= NULL
;
1295 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
1296 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1297 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
1300 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1301 n
->state
= ZEBRA_NEIGH_INACTIVE
;
1303 /* Associate the neigh to mac */
1304 zmac
= zvni_mac_lookup(zvni
, mac
);
1306 listnode_add_sort(zmac
->neigh_list
, n
);
1312 * Delete neighbor entry.
1314 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1316 zebra_neigh_t
*tmp_n
;
1317 zebra_mac_t
*zmac
= NULL
;
1319 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
1321 listnode_delete(zmac
->neigh_list
, n
);
1323 /* Free the VNI hash entry and allocated memory. */
1324 tmp_n
= hash_release(zvni
->neigh_table
, n
);
1326 XFREE(MTYPE_NEIGH
, tmp_n
);
1332 * Free neighbor hash entry (callback)
1334 static void zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
1336 struct neigh_walk_ctx
*wctx
= arg
;
1337 zebra_neigh_t
*n
= backet
->data
;
1339 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1340 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
1341 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
1342 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
1343 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
1344 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
1345 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1346 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
1349 if (wctx
->uninstall
)
1350 zvni_neigh_uninstall(wctx
->zvni
, n
);
1352 zvni_neigh_del(wctx
->zvni
, n
);
1359 * Delete all neighbor entries from specific VTEP for a particular VNI.
1361 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
1362 struct in_addr
*r_vtep_ip
)
1364 struct neigh_walk_ctx wctx
;
1366 if (!zvni
->neigh_table
)
1369 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1371 wctx
.uninstall
= uninstall
;
1372 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
1373 wctx
.r_vtep_ip
= *r_vtep_ip
;
1375 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1379 * Delete all neighbor entries for this VNI.
1381 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
1384 struct neigh_walk_ctx wctx
;
1386 if (!zvni
->neigh_table
)
1389 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1391 wctx
.uninstall
= uninstall
;
1392 wctx
.upd_client
= upd_client
;
1395 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1399 * Look up neighbor hash entry.
1401 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
1406 memset(&tmp
, 0, sizeof(tmp
));
1407 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
1408 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
1414 * Process all neighbors associated with a MAC upon the MAC being learnt
1415 * locally or undergoing any other change (such as sequence number).
1417 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
1421 zebra_neigh_t
*n
= NULL
;
1422 struct listnode
*node
= NULL
;
1423 char buf
[ETHER_ADDR_STRLEN
];
1425 if (IS_ZEBRA_DEBUG_VXLAN
)
1426 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
1427 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
1428 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
1430 /* Walk all neighbors and mark any inactive local neighbors as
1431 * active and/or update sequence number upon a move, and inform BGP.
1432 * The action for remote neighbors is TBD.
1433 * NOTE: We can't simply uninstall remote neighbors as the kernel may
1434 * accidentally end up deleting a just-learnt local neighbor.
1436 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1437 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1438 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
1439 ZEBRA_NEIGH_SET_ACTIVE(n
);
1440 n
->loc_seq
= zmac
->loc_seq
;
1441 zvni_neigh_send_add_to_client(
1442 zvni
->vni
, &n
->ip
, &n
->emac
,
1443 n
->flags
, n
->loc_seq
);
1450 * Process all neighbors associated with a local MAC upon the MAC being
1453 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
1456 zebra_neigh_t
*n
= NULL
;
1457 struct listnode
*node
= NULL
;
1458 char buf
[ETHER_ADDR_STRLEN
];
1460 if (IS_ZEBRA_DEBUG_VXLAN
)
1461 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
1462 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
1465 /* Walk all local neighbors and mark as inactive and inform
1467 * TBD: There is currently no handling for remote neighbors. We
1468 * don't expect them to exist, if they do, do we install the MAC
1469 * as a remote MAC and the neighbor as remote?
1471 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1472 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1473 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1474 ZEBRA_NEIGH_SET_INACTIVE(n
);
1476 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1484 * Process all neighbors associated with a MAC upon the MAC being remotely
1487 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
1490 zebra_neigh_t
*n
= NULL
;
1491 struct listnode
*node
= NULL
;
1492 char buf
[ETHER_ADDR_STRLEN
];
1494 if (IS_ZEBRA_DEBUG_VXLAN
)
1495 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
1496 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
1499 /* Walk all local neighbors and mark as inactive and inform
1502 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1503 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1504 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1505 ZEBRA_NEIGH_SET_INACTIVE(n
);
1507 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1515 * Process all neighbors associated with a remote MAC upon the MAC being
1518 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
1521 /* NOTE: Currently a NO-OP. */
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
,
1534 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
1535 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
1536 /* Set router flag (R-bit) based on local neigh entry add */
1537 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
1538 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
1540 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1541 seq
, ZEBRA_MACIP_ADD
);
1545 * Inform BGP about local neighbor deletion.
1547 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
1548 struct ethaddr
*macaddr
, uint8_t flags
)
1550 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1551 0, ZEBRA_MACIP_DEL
);
1555 * Install remote neighbor into the kernel.
1557 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1559 struct zebra_if
*zif
;
1560 struct zebra_l2info_vxlan
*vxl
;
1561 struct interface
*vlan_if
;
1567 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1570 zif
= zvni
->vxlan_if
->info
;
1573 vxl
= &zif
->l2info
.vxl
;
1575 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1579 flags
= NTF_EXT_LEARNED
;
1580 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
1581 flags
|= NTF_ROUTER
;
1582 ZEBRA_NEIGH_SET_ACTIVE(n
);
1583 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
1589 * Uninstall remote neighbor from the kernel.
1591 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1593 struct zebra_if
*zif
;
1594 struct zebra_l2info_vxlan
*vxl
;
1595 struct interface
*vlan_if
;
1597 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1600 if (!zvni
->vxlan_if
) {
1601 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
1606 zif
= zvni
->vxlan_if
->info
;
1609 vxl
= &zif
->l2info
.vxl
;
1610 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1614 ZEBRA_NEIGH_SET_INACTIVE(n
);
1616 return kernel_del_neigh(vlan_if
, &n
->ip
);
1620 * Install neighbor hash entry - called upon access VLAN change.
1622 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
1625 struct neigh_walk_ctx
*wctx
= ctxt
;
1627 n
= (zebra_neigh_t
*)backet
->data
;
1629 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
1630 zvni_neigh_install(wctx
->zvni
, n
);
1633 /* Get the VRR interface for SVI if any */
1634 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
1636 struct zebra_vrf
*zvrf
= NULL
;
1637 struct interface
*tmp_if
= NULL
;
1638 struct zebra_if
*zif
= NULL
;
1640 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1643 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
1648 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
1651 if (zif
->link
== ifp
)
1658 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1660 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1661 struct connected
*c
= NULL
;
1662 struct ethaddr macaddr
;
1664 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1666 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1669 memset(&ip
, 0, sizeof(struct ipaddr
));
1670 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1673 if (c
->address
->family
== AF_INET
) {
1674 ip
.ipa_type
= IPADDR_V4
;
1675 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1676 sizeof(struct in_addr
));
1677 } else if (c
->address
->family
== AF_INET6
) {
1678 ip
.ipa_type
= IPADDR_V6
;
1679 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1680 sizeof(struct in6_addr
));
1685 zvni_gw_macip_del(ifp
, zvni
, &ip
);
1691 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1693 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1694 struct connected
*c
= NULL
;
1695 struct ethaddr macaddr
;
1697 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1699 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1702 memset(&ip
, 0, sizeof(struct ipaddr
));
1703 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1706 if (c
->address
->family
== AF_INET
) {
1707 ip
.ipa_type
= IPADDR_V4
;
1708 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1709 sizeof(struct in_addr
));
1710 } else if (c
->address
->family
== AF_INET6
) {
1711 ip
.ipa_type
= IPADDR_V6
;
1712 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1713 sizeof(struct in6_addr
));
1718 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
1724 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
1727 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1728 struct connected
*c
= NULL
;
1729 struct ethaddr macaddr
;
1731 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1733 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1736 memcpy(&p
, c
->address
, sizeof(struct prefix
));
1738 /* skip link local address */
1739 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
1744 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1745 ZEBRA_IP_PREFIX_ROUTE_ADD
);
1747 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1748 ZEBRA_IP_PREFIX_ROUTE_DEL
);
1754 * zvni_gw_macip_add_to_client
1756 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
1757 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
1759 char buf
[ETHER_ADDR_STRLEN
];
1760 char buf2
[INET6_ADDRSTRLEN
];
1761 zebra_neigh_t
*n
= NULL
;
1762 zebra_mac_t
*mac
= NULL
;
1763 struct zebra_if
*zif
= NULL
;
1764 struct zebra_l2info_vxlan
*vxl
= NULL
;
1766 zif
= zvni
->vxlan_if
->info
;
1770 vxl
= &zif
->l2info
.vxl
;
1772 mac
= zvni_mac_lookup(zvni
, macaddr
);
1774 mac
= zvni_mac_add(zvni
, macaddr
);
1776 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
1777 "Failed to add MAC %s intf %s(%u) VID %u",
1778 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1779 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
1784 /* Set "local" forwarding info. */
1785 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
1786 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
1787 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
1788 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
1789 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
1790 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
1792 n
= zvni_neigh_lookup(zvni
, ip
);
1794 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
1797 EC_ZEBRA_MAC_ADD_FAILED
,
1798 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1799 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
1800 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1801 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
1806 /* Set "local" forwarding info. */
1807 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
1808 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
1809 ZEBRA_NEIGH_SET_ACTIVE(n
);
1810 /* Set Router flag (R-bit) */
1811 if (ip
->ipa_type
== IPADDR_V6
)
1812 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
1813 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
1814 n
->ifindex
= ifp
->ifindex
;
1816 /* Only advertise in BGP if the knob is enabled */
1817 if (!advertise_gw_macip_enabled(zvni
))
1820 if (IS_ZEBRA_DEBUG_VXLAN
)
1822 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
1823 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1824 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1825 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
1827 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
1828 n
->flags
, n
->loc_seq
);
1834 * zvni_gw_macip_del_from_client
1836 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
1839 char buf1
[ETHER_ADDR_STRLEN
];
1840 char buf2
[INET6_ADDRSTRLEN
];
1841 zebra_neigh_t
*n
= NULL
;
1842 zebra_mac_t
*mac
= NULL
;
1844 /* If the neigh entry is not present nothing to do*/
1845 n
= zvni_neigh_lookup(zvni
, ip
);
1849 /* mac entry should be present */
1850 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
1852 zlog_debug("MAC %s doesnt exists for neigh %s on VNI %u",
1853 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
1854 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1858 /* If the entry is not local nothing to do*/
1859 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
1862 /* only need to delete the entry from bgp if we sent it before */
1863 if (IS_ZEBRA_DEBUG_VXLAN
)
1865 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
1866 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1867 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
1868 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1870 /* Remove neighbor from BGP. */
1871 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
1872 ZEBRA_MACIP_TYPE_GW
);
1874 /* Delete this neighbor entry. */
1875 zvni_neigh_del(zvni
, n
);
1877 /* see if the mac needs to be deleted as well*/
1879 zvni_deref_ip2mac(zvni
, mac
);
1884 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
1887 zebra_vni_t
*zvni
= NULL
;
1888 struct zebra_if
*zif
= NULL
;
1889 struct zebra_l2info_vxlan zl2_info
;
1890 struct interface
*vlan_if
= NULL
;
1891 struct interface
*vrr_if
= NULL
;
1892 struct interface
*ifp
;
1894 /* Add primary SVI MAC*/
1895 zvni
= (zebra_vni_t
*)backet
->data
;
1897 ifp
= zvni
->vxlan_if
;
1902 /* If down or not mapped to a bridge, we're done. */
1903 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1906 zl2_info
= zif
->l2info
.vxl
;
1909 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1913 /* Del primary MAC-IP */
1914 zvni_del_macip_for_intf(vlan_if
, zvni
);
1916 /* Del VRR MAC-IP - if any*/
1917 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1919 zvni_del_macip_for_intf(vrr_if
, zvni
);
1924 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
1927 zebra_vni_t
*zvni
= NULL
;
1928 struct zebra_if
*zif
= NULL
;
1929 struct zebra_l2info_vxlan zl2_info
;
1930 struct interface
*vlan_if
= NULL
;
1931 struct interface
*vrr_if
= NULL
;
1932 struct interface
*ifp
= NULL
;
1934 zvni
= (zebra_vni_t
*)backet
->data
;
1936 ifp
= zvni
->vxlan_if
;
1941 /* If down or not mapped to a bridge, we're done. */
1942 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1944 zl2_info
= zif
->l2info
.vxl
;
1947 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1951 /* Add primary SVI MAC-IP */
1952 zvni_add_macip_for_intf(vlan_if
, zvni
);
1954 /* Add VRR MAC-IP - if any*/
1955 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1957 zvni_add_macip_for_intf(vrr_if
, zvni
);
1962 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
1963 struct interface
*ifp
,
1965 struct ethaddr
*macaddr
,
1968 char buf
[ETHER_ADDR_STRLEN
];
1969 char buf2
[INET6_ADDRSTRLEN
];
1970 zebra_neigh_t
*n
= NULL
;
1971 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
1972 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
1973 bool upd_mac_seq
= false;
1974 bool neigh_mac_change
= false;
1975 bool check_rbit
= false;
1977 /* Check if the MAC exists. */
1978 zmac
= zvni_mac_lookup(zvni
, macaddr
);
1980 /* create a dummy MAC if the MAC is not already present */
1981 if (IS_ZEBRA_DEBUG_VXLAN
)
1983 "AUTO MAC %s created for neigh %s on VNI %u",
1984 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1985 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1987 zmac
= zvni_mac_add(zvni
, macaddr
);
1989 zlog_debug("Failed to add MAC %s VNI %u",
1990 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1995 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
1996 memset(&zmac
->flags
, 0, sizeof(uint32_t));
1997 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
1999 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2001 * We don't change the MAC to local upon a neighbor
2002 * learn event, we wait for the explicit local MAC
2003 * learn. However, we have to compute its sequence
2004 * number in preparation for when it actually turns
2011 /* Check if the neighbor exists. */
2012 n
= zvni_neigh_lookup(zvni
, ip
);
2014 /* New neighbor - create */
2015 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2018 EC_ZEBRA_MAC_ADD_FAILED
,
2019 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2020 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2021 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2022 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2025 /* Set "local" forwarding info. */
2026 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2027 n
->ifindex
= ifp
->ifindex
;
2030 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2034 /* Note any changes and see if of interest to BGP. */
2035 mac_different
= (memcmp(n
->emac
.octet
,
2036 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
2037 cur_is_router
= !!CHECK_FLAG(n
->flags
,
2038 ZEBRA_NEIGH_ROUTER_FLAG
);
2039 if (!mac_different
&& is_router
== cur_is_router
) {
2040 n
->ifindex
= ifp
->ifindex
;
2044 if (!mac_different
) {
2045 /* Only the router flag has changed. */
2048 ZEBRA_NEIGH_ROUTER_FLAG
);
2050 UNSET_FLAG(n
->flags
,
2051 ZEBRA_NEIGH_ROUTER_FLAG
);
2053 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
2054 return zvni_neigh_send_add_to_client(
2055 zvni
->vni
, ip
, macaddr
,
2056 n
->flags
, n
->loc_seq
);
2060 /* The MAC has changed, need to issue a delete
2061 * first as this means a different MACIP route.
2062 * Also, need to do some unlinking/relinking.
2063 * We also need to update the MAC's sequence number
2064 * in different situations.
2066 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
2067 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2069 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2071 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
2073 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
2074 neigh_mac_change
= upd_mac_seq
= true;
2075 listnode_delete(old_zmac
->neigh_list
, n
);
2076 zvni_deref_ip2mac(zvni
, old_zmac
);
2079 /* Update the forwarding info. */
2080 n
->ifindex
= ifp
->ifindex
;
2081 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2083 /* Link to new MAC */
2084 listnode_add_sort(zmac
->neigh_list
, n
);
2085 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2087 * Neighbor has moved from remote to local. Its
2088 * MAC could have also changed as part of the move.
2090 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2092 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2094 old_mac_seq
= CHECK_FLAG(
2099 neigh_mac_change
= upd_mac_seq
= true;
2100 listnode_delete(old_zmac
->neigh_list
,
2102 zvni_deref_ip2mac(zvni
, old_zmac
);
2105 /* Link to new MAC */
2106 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2107 listnode_add_sort(zmac
->neigh_list
, n
);
2110 /* Mark appropriately */
2111 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2112 n
->r_vtep_ip
.s_addr
= 0;
2113 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2114 n
->ifindex
= ifp
->ifindex
;
2119 /* If MAC was previously remote, or the neighbor had a different
2120 * MAC earlier, recompute the sequence number.
2123 uint32_t seq1
, seq2
;
2125 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
2126 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
2127 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
2128 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
2129 MAX(seq1
, seq2
) : zmac
->loc_seq
;
2132 /*Mark Router flag (R-bit) */
2134 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2136 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2138 /* Before we program this in BGP, we need to check if MAC is locally
2139 * learnt. If not, force neighbor to be inactive and reset its seq.
2141 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
2142 ZEBRA_NEIGH_SET_INACTIVE(n
);
2144 zmac
->loc_seq
= mac_new_seq
;
2151 /* If the MAC's sequence number has changed, inform the MAC and all
2152 * neighbors associated with the MAC to BGP, else just inform this
2155 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
2156 if (IS_ZEBRA_DEBUG_VXLAN
)
2157 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
2158 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2159 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
2160 zmac
->loc_seq
= mac_new_seq
;
2161 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
2162 zmac
->flags
, zmac
->loc_seq
))
2164 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
2168 ZEBRA_NEIGH_SET_ACTIVE(n
);
2169 n
->loc_seq
= zmac
->loc_seq
;
2171 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2172 n
->flags
, n
->loc_seq
);
2175 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
2176 struct interface
*ifp
,
2178 struct ethaddr
*macaddr
,
2181 char buf
[ETHER_ADDR_STRLEN
];
2182 char buf2
[INET6_ADDRSTRLEN
];
2183 zebra_neigh_t
*n
= NULL
;
2184 zebra_mac_t
*zmac
= NULL
;
2186 /* If the neighbor is unknown, there is no further action. */
2187 n
= zvni_neigh_lookup(zvni
, ip
);
2191 /* If a remote entry, see if it needs to be refreshed */
2192 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2194 if (state
& NUD_STALE
)
2195 zvni_neigh_install(zvni
, n
);
2198 /* We got a "remote" neighbor notification for an entry
2199 * we think is local. This can happen in a multihoming
2200 * scenario - but only if the MAC is already "remote".
2201 * Just mark our entry as "remote".
2203 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2204 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2206 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
2207 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
2208 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2213 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2214 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2215 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
2222 * Make hash key for MAC.
2224 static unsigned int mac_hash_keymake(void *p
)
2226 zebra_mac_t
*pmac
= p
;
2227 const void *pnt
= (void *)pmac
->macaddr
.octet
;
2229 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
2233 * Compare two MAC addresses.
2235 static int mac_cmp(const void *p1
, const void *p2
)
2237 const zebra_mac_t
*pmac1
= p1
;
2238 const zebra_mac_t
*pmac2
= p2
;
2240 if (pmac1
== NULL
&& pmac2
== NULL
)
2243 if (pmac1
== NULL
|| pmac2
== NULL
)
2246 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
2251 * Callback to allocate MAC hash entry.
2253 static void *zvni_mac_alloc(void *p
)
2255 const zebra_mac_t
*tmp_mac
= p
;
2258 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2261 return ((void *)mac
);
2267 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
2269 zebra_mac_t tmp_mac
;
2270 zebra_mac_t
*mac
= NULL
;
2272 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
2273 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
2274 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
2277 mac
->neigh_list
= list_new();
2278 mac
->neigh_list
->cmp
= (int (*)(void *, void *))neigh_cmp
;
2286 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2288 zebra_mac_t
*tmp_mac
;
2290 list_delete_and_null(&mac
->neigh_list
);
2292 /* Free the VNI hash entry and allocated memory. */
2293 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
2295 XFREE(MTYPE_MAC
, tmp_mac
);
2301 * Free MAC hash entry (callback)
2303 static void zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2305 struct mac_walk_ctx
*wctx
= arg
;
2306 zebra_mac_t
*mac
= backet
->data
;
2308 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
2309 || ((wctx
->flags
& DEL_REMOTE_MAC
)
2310 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
2311 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
2312 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
2313 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
2314 &wctx
->r_vtep_ip
))) {
2315 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
2316 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
2317 &mac
->macaddr
, mac
->flags
);
2320 if (wctx
->uninstall
)
2321 zvni_mac_uninstall(wctx
->zvni
, mac
);
2323 zvni_mac_del(wctx
->zvni
, mac
);
2330 * Delete all MAC entries from specific VTEP for a particular VNI.
2332 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2333 struct in_addr
*r_vtep_ip
)
2335 struct mac_walk_ctx wctx
;
2337 if (!zvni
->mac_table
)
2340 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2342 wctx
.uninstall
= uninstall
;
2343 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
2344 wctx
.r_vtep_ip
= *r_vtep_ip
;
2346 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2350 * Delete all MAC entries for this VNI.
2352 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2355 struct mac_walk_ctx wctx
;
2357 if (!zvni
->mac_table
)
2360 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2362 wctx
.uninstall
= uninstall
;
2363 wctx
.upd_client
= upd_client
;
2366 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2370 * Look up MAC hash entry.
2372 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
2377 memset(&tmp
, 0, sizeof(tmp
));
2378 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
2379 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
2385 * Inform BGP about local MAC addition.
2387 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2388 uint8_t mac_flags
, uint32_t seq
)
2392 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2393 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2394 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2395 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2397 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2398 seq
, ZEBRA_MACIP_ADD
);
2402 * Inform BGP about local MAC deletion.
2404 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2409 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2410 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2411 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2412 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2414 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2415 0, ZEBRA_MACIP_DEL
);
2419 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2420 * notifications, to see if they are of interest.
2422 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
2423 struct interface
*br_if
, vlanid_t vid
)
2425 struct zebra_ns
*zns
;
2426 struct route_node
*rn
;
2427 struct interface
*tmp_if
= NULL
;
2428 struct zebra_if
*zif
;
2429 struct zebra_l2info_bridge
*br
;
2430 struct zebra_l2info_vxlan
*vxl
= NULL
;
2431 uint8_t bridge_vlan_aware
;
2435 /* Determine if bridge is VLAN-aware or not */
2438 br
= &zif
->l2info
.br
;
2439 bridge_vlan_aware
= br
->vlan_aware
;
2441 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2442 /* TODO: Optimize with a hash. */
2443 zns
= zebra_ns_lookup(NS_DEFAULT
);
2444 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2445 tmp_if
= (struct interface
*)rn
->info
;
2449 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2451 if (!if_is_operative(tmp_if
))
2453 vxl
= &zif
->l2info
.vxl
;
2455 if (zif
->brslave_info
.br_if
!= br_if
)
2458 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2467 zvni
= zvni_lookup(vxl
->vni
);
2472 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2473 * neighbor notifications, to see if they are of interest.
2475 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
2476 struct interface
*br_if
)
2478 struct zebra_ns
*zns
;
2479 struct route_node
*rn
;
2480 struct interface
*tmp_if
= NULL
;
2481 struct zebra_if
*zif
;
2482 struct zebra_l2info_bridge
*br
;
2483 struct zebra_l2info_vxlan
*vxl
= NULL
;
2484 uint8_t bridge_vlan_aware
;
2492 /* Make sure the linked interface is a bridge. */
2493 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
2496 /* Determine if bridge is VLAN-aware or not */
2499 br
= &zif
->l2info
.br
;
2500 bridge_vlan_aware
= br
->vlan_aware
;
2501 if (bridge_vlan_aware
) {
2502 struct zebra_l2info_vlan
*vl
;
2504 if (!IS_ZEBRA_IF_VLAN(ifp
))
2509 vl
= &zif
->l2info
.vl
;
2513 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2514 /* TODO: Optimize with a hash. */
2515 zns
= zebra_ns_lookup(NS_DEFAULT
);
2516 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2517 tmp_if
= (struct interface
*)rn
->info
;
2521 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2523 if (!if_is_operative(tmp_if
))
2525 vxl
= &zif
->l2info
.vxl
;
2527 if (zif
->brslave_info
.br_if
!= br_if
)
2530 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2539 zvni
= zvni_lookup(vxl
->vni
);
2543 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
2545 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
2546 * linked to the bridge
2547 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
2550 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
2552 struct zebra_ns
*zns
;
2553 struct route_node
*rn
;
2554 struct interface
*tmp_if
= NULL
;
2555 struct zebra_if
*zif
;
2556 struct zebra_l2info_bridge
*br
;
2557 struct zebra_l2info_vlan
*vl
;
2558 uint8_t bridge_vlan_aware
;
2561 /* Defensive check, caller expected to invoke only with valid bridge. */
2565 /* Determine if bridge is VLAN-aware or not */
2568 br
= &zif
->l2info
.br
;
2569 bridge_vlan_aware
= br
->vlan_aware
;
2571 /* Check oper status of the SVI. */
2572 if (!bridge_vlan_aware
)
2573 return if_is_operative(br_if
) ? br_if
: NULL
;
2575 /* Identify corresponding VLAN interface. */
2576 /* TODO: Optimize with a hash. */
2577 zns
= zebra_ns_lookup(NS_DEFAULT
);
2578 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2579 tmp_if
= (struct interface
*)rn
->info
;
2580 /* Check oper status of the SVI. */
2581 if (!tmp_if
|| !if_is_operative(tmp_if
))
2584 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
2585 || zif
->link
!= br_if
)
2587 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
2589 if (vl
->vid
== vid
) {
2595 return found
? tmp_if
: NULL
;
2599 * Install remote MAC into the kernel.
2601 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2603 struct zebra_if
*zif
;
2604 struct zebra_l2info_vxlan
*vxl
;
2607 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2610 zif
= zvni
->vxlan_if
->info
;
2613 vxl
= &zif
->l2info
.vxl
;
2615 sticky
= !!CHECK_FLAG(mac
->flags
,
2616 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
2618 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
2619 mac
->fwd_info
.r_vtep_ip
, sticky
);
2623 * Uninstall remote MAC from the kernel.
2625 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2627 struct zebra_if
*zif
;
2628 struct zebra_l2info_vxlan
*vxl
;
2629 struct in_addr vtep_ip
= {.s_addr
= 0};
2630 struct interface
*ifp
;
2632 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2635 if (!zvni
->vxlan_if
) {
2636 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2641 zif
= zvni
->vxlan_if
->info
;
2644 vxl
= &zif
->l2info
.vxl
;
2646 ifp
= zvni
->vxlan_if
;
2647 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
2649 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
2653 * Install MAC hash entry - called upon access VLAN change.
2655 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
2658 struct mac_walk_ctx
*wctx
= ctxt
;
2660 mac
= (zebra_mac_t
*)backet
->data
;
2662 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
2663 zvni_mac_install(wctx
->zvni
, mac
);
2667 * Count of remote neighbors referencing this MAC.
2669 static int remote_neigh_count(zebra_mac_t
*zmac
)
2671 zebra_neigh_t
*n
= NULL
;
2672 struct listnode
*node
= NULL
;
2675 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2676 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2684 * Decrement neighbor refcount of MAC; uninstall and free it if
2687 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2689 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
2692 /* If all remote neighbors referencing a remote MAC go away,
2693 * we need to uninstall the MAC.
2695 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
2696 remote_neigh_count(mac
) == 0) {
2697 zvni_mac_uninstall(zvni
, mac
);
2698 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
2701 /* If no neighbors, delete the MAC. */
2702 if (list_isempty(mac
->neigh_list
))
2703 zvni_mac_del(zvni
, mac
);
2707 * Read and populate local MACs and neighbors corresponding to this VNI.
2709 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
2711 struct zebra_ns
*zns
;
2712 struct zebra_if
*zif
;
2713 struct interface
*vlan_if
;
2714 struct zebra_l2info_vxlan
*vxl
;
2715 struct interface
*vrr_if
;
2718 vxl
= &zif
->l2info
.vxl
;
2719 zns
= zebra_ns_lookup(NS_DEFAULT
);
2721 if (IS_ZEBRA_DEBUG_VXLAN
)
2723 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2724 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2725 zif
->brslave_info
.bridge_ifindex
);
2727 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
2728 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2731 /* Add SVI MAC-IP */
2732 zvni_add_macip_for_intf(vlan_if
, zvni
);
2734 /* Add VRR MAC-IP - if any*/
2735 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2737 zvni_add_macip_for_intf(vrr_if
, zvni
);
2739 neigh_read_for_vlan(zns
, vlan_if
);
2744 * Hash function for VNI.
2746 static unsigned int vni_hash_keymake(void *p
)
2748 const zebra_vni_t
*zvni
= p
;
2750 return (jhash_1word(zvni
->vni
, 0));
2754 * Compare 2 VNI hash entries.
2756 static int vni_hash_cmp(const void *p1
, const void *p2
)
2758 const zebra_vni_t
*zvni1
= p1
;
2759 const zebra_vni_t
*zvni2
= p2
;
2761 return (zvni1
->vni
== zvni2
->vni
);
2765 * Callback to allocate VNI hash entry.
2767 static void *zvni_alloc(void *p
)
2769 const zebra_vni_t
*tmp_vni
= p
;
2772 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
2773 zvni
->vni
= tmp_vni
->vni
;
2774 return ((void *)zvni
);
2778 * Look up VNI hash entry.
2780 static zebra_vni_t
*zvni_lookup(vni_t vni
)
2782 struct zebra_vrf
*zvrf
;
2783 zebra_vni_t tmp_vni
;
2784 zebra_vni_t
*zvni
= NULL
;
2786 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2788 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
2790 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
2796 * Add VNI hash entry.
2798 static zebra_vni_t
*zvni_add(vni_t vni
)
2800 struct zebra_vrf
*zvrf
;
2801 zebra_vni_t tmp_zvni
;
2802 zebra_vni_t
*zvni
= NULL
;
2804 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2806 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
2808 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
2811 /* Create hash table for MAC */
2813 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
2815 /* Create hash table for neighbors */
2816 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
2817 "Zebra VNI Neighbor Table");
2823 * Delete VNI hash entry.
2825 static int zvni_del(zebra_vni_t
*zvni
)
2827 struct zebra_vrf
*zvrf
;
2828 zebra_vni_t
*tmp_zvni
;
2830 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2833 zvni
->vxlan_if
= NULL
;
2835 /* Free the neighbor hash table. */
2836 hash_free(zvni
->neigh_table
);
2837 zvni
->neigh_table
= NULL
;
2839 /* Free the MAC hash table. */
2840 hash_free(zvni
->mac_table
);
2841 zvni
->mac_table
= NULL
;
2843 /* Free the VNI hash entry and allocated memory. */
2844 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
2846 XFREE(MTYPE_ZVNI
, tmp_zvni
);
2852 * Inform BGP about local VNI addition.
2854 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
2856 struct zserv
*client
;
2859 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2860 /* BGP may not be running. */
2864 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2866 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
2867 stream_putl(s
, zvni
->vni
);
2868 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
2869 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
2871 /* Write packet size. */
2872 stream_putw_at(s
, 0, stream_get_endp(s
));
2874 if (IS_ZEBRA_DEBUG_VXLAN
)
2875 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
2876 inet_ntoa(zvni
->local_vtep_ip
),
2877 vrf_id_to_name(zvni
->vrf_id
),
2878 zebra_route_string(client
->proto
));
2880 client
->vniadd_cnt
++;
2881 return zserv_send_message(client
, s
);
2885 * Inform BGP about local VNI deletion.
2887 static int zvni_send_del_to_client(vni_t vni
)
2889 struct zserv
*client
;
2892 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2893 /* BGP may not be running. */
2897 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2900 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
2901 stream_putl(s
, vni
);
2903 /* Write packet size. */
2904 stream_putw_at(s
, 0, stream_get_endp(s
));
2906 if (IS_ZEBRA_DEBUG_VXLAN
)
2907 zlog_debug("Send VNI_DEL %u to %s", vni
,
2908 zebra_route_string(client
->proto
));
2910 client
->vnidel_cnt
++;
2911 return zserv_send_message(client
, s
);
2915 * Build the VNI hash table by going over the VxLAN interfaces. This
2916 * is called when EVPN (advertise-all-vni) is enabled.
2918 static void zvni_build_hash_table()
2920 struct zebra_ns
*zns
;
2921 struct route_node
*rn
;
2922 struct interface
*ifp
;
2924 /* Walk VxLAN interfaces and create VNI hash. */
2925 zns
= zebra_ns_lookup(NS_DEFAULT
);
2926 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2928 zebra_vni_t
*zvni
= NULL
;
2929 zebra_l3vni_t
*zl3vni
= NULL
;
2930 struct zebra_if
*zif
;
2931 struct zebra_l2info_vxlan
*vxl
;
2933 ifp
= (struct interface
*)rn
->info
;
2937 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2940 vxl
= &zif
->l2info
.vxl
;
2943 /* L3-VNI and L2-VNI are handled seperately */
2944 zl3vni
= zl3vni_lookup(vni
);
2947 if (IS_ZEBRA_DEBUG_VXLAN
)
2949 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
2950 ifp
->name
, ifp
->ifindex
, vni
);
2952 /* associate with vxlan_if */
2953 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
2954 zl3vni
->vxlan_if
= ifp
;
2957 * we need to associate with SVI.
2958 * we can associate with svi-if only after association
2959 * with vxlan-intf is complete
2961 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
2963 if (is_l3vni_oper_up(zl3vni
))
2964 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
2967 struct interface
*vlan_if
= NULL
;
2969 if (IS_ZEBRA_DEBUG_VXLAN
)
2971 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
2972 ifp
->name
, ifp
->ifindex
, vni
,
2973 inet_ntoa(vxl
->vtep_ip
));
2975 /* VNI hash entry is not expected to exist. */
2976 zvni
= zvni_lookup(vni
);
2979 "VNI hash already present for IF %s(%u) L2-VNI %u",
2980 ifp
->name
, ifp
->ifindex
, vni
);
2984 zvni
= zvni_add(vni
);
2987 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
2988 ifp
->name
, ifp
->ifindex
, vni
);
2992 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
2993 zvni
->vxlan_if
= ifp
;
2994 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
2995 zif
->brslave_info
.br_if
);
2997 zvni
->vrf_id
= vlan_if
->vrf_id
;
2998 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
3000 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3004 /* Inform BGP if intf is up and mapped to bridge. */
3005 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
3006 zvni_send_add_to_client(zvni
);
3012 * See if remote VTEP matches with prefix.
3014 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
3016 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
3020 * Locate remote VTEP in VNI hash table.
3022 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3024 zebra_vtep_t
*zvtep
;
3029 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
3030 if (zvni_vtep_match(vtep_ip
, zvtep
))
3038 * Add remote VTEP to VNI hash table.
3040 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3042 zebra_vtep_t
*zvtep
;
3044 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
3046 zvtep
->vtep_ip
= *vtep_ip
;
3049 zvni
->vteps
->prev
= zvtep
;
3050 zvtep
->next
= zvni
->vteps
;
3051 zvni
->vteps
= zvtep
;
3057 * Remove remote VTEP from VNI hash table.
3059 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
3062 zvtep
->next
->prev
= zvtep
->prev
;
3064 zvtep
->prev
->next
= zvtep
->next
;
3066 zvni
->vteps
= zvtep
->next
;
3068 zvtep
->prev
= zvtep
->next
= NULL
;
3069 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
3075 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
3076 * uninstall from kernel if asked to.
3078 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
3080 zebra_vtep_t
*zvtep
, *zvtep_next
;
3085 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
3086 zvtep_next
= zvtep
->next
;
3088 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
3089 zvni_vtep_del(zvni
, zvtep
);
3096 * Install remote VTEP into the kernel.
3098 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3100 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3104 * Uninstall remote VTEP from the kernel.
3106 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3108 if (!zvni
->vxlan_if
) {
3109 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3114 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3118 * Cleanup VNI/VTEP and update kernel
3120 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
3122 zebra_vni_t
*zvni
= NULL
;
3123 zebra_l3vni_t
*zl3vni
= NULL
;
3124 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
3126 zvni
= (zebra_vni_t
*)backet
->data
;
3128 /* remove from l3-vni list */
3130 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
3132 listnode_delete(zl3vni
->l2vnis
, zvni
);
3134 /* Free up all neighbors and MACs, if any. */
3135 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
3136 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
3138 /* Free up all remote VTEPs, if any. */
3139 zvni_vtep_del_all(zvni
, 1);
3141 /* Delete the hash entry. */
3146 static void zl3vni_cleanup_all(struct hash_backet
*backet
, void *args
)
3148 zebra_l3vni_t
*zl3vni
= NULL
;
3150 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
3152 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
3155 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
3156 struct prefix
*host
)
3158 struct host_rb_entry lookup
;
3159 struct host_rb_entry
*hle
;
3161 memset(&lookup
, 0, sizeof(lookup
));
3162 memcpy(&lookup
.p
, host
, sizeof(*host
));
3164 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3168 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
3169 memcpy(hle
, &lookup
, sizeof(lookup
));
3171 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
3174 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
3176 struct host_rb_entry lookup
;
3177 struct host_rb_entry
*hle
;
3179 memset(&lookup
, 0, sizeof(lookup
));
3180 memcpy(&lookup
.p
, host
, sizeof(*host
));
3182 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3184 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
3185 XFREE(MTYPE_HOST_PREFIX
, hle
);
3192 * Look up MAC hash entry.
3194 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
3195 struct ethaddr
*rmac
)
3200 memset(&tmp
, 0, sizeof(tmp
));
3201 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
3202 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
3208 * Callback to allocate RMAC hash entry.
3210 static void *zl3vni_rmac_alloc(void *p
)
3212 const zebra_mac_t
*tmp_rmac
= p
;
3215 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3218 return ((void *)zrmac
);
3222 * Add RMAC entry to l3-vni
3224 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
3226 zebra_mac_t tmp_rmac
;
3227 zebra_mac_t
*zrmac
= NULL
;
3229 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
3230 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
3231 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
3234 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
3236 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
3237 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
3245 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3247 zebra_mac_t
*tmp_rmac
;
3248 struct host_rb_entry
*hle
;
3250 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3251 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
3253 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
3254 XFREE(MTYPE_HOST_PREFIX
, hle
);
3257 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
3259 XFREE(MTYPE_MAC
, tmp_rmac
);
3265 * Install remote RMAC into the kernel.
3267 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3269 struct zebra_if
*zif
= NULL
;
3270 struct zebra_l2info_vxlan
*vxl
= NULL
;
3272 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3273 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3276 zif
= zl3vni
->vxlan_if
->info
;
3280 vxl
= &zif
->l2info
.vxl
;
3282 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3283 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3287 * Uninstall remote RMAC from the kernel.
3289 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3291 char buf
[ETHER_ADDR_STRLEN
];
3292 struct zebra_if
*zif
= NULL
;
3293 struct zebra_l2info_vxlan
*vxl
= NULL
;
3295 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3296 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3299 if (!zl3vni
->vxlan_if
) {
3301 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
3302 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
3303 zl3vni
->vni
, zl3vni
);
3307 zif
= zl3vni
->vxlan_if
->info
;
3311 vxl
= &zif
->l2info
.vxl
;
3313 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3314 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
3317 /* handle rmac add */
3318 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
3319 struct ipaddr
*vtep_ip
,
3320 struct prefix
*host_prefix
)
3322 char buf
[ETHER_ADDR_STRLEN
];
3323 char buf1
[INET6_ADDRSTRLEN
];
3324 zebra_mac_t
*zrmac
= NULL
;
3326 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3329 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
3332 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
3333 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3335 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
3338 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
3339 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
3341 /* install rmac in kernel */
3342 zl3vni_rmac_install(zl3vni
, zrmac
);
3345 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
3351 /* handle rmac delete */
3352 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
3353 struct prefix
*host_prefix
)
3355 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
3357 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3358 /* uninstall from kernel */
3359 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3361 /* del the rmac entry */
3362 zl3vni_rmac_del(zl3vni
, zrmac
);
3367 * Look up nh hash entry on a l3-vni.
3369 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3374 memset(&tmp
, 0, sizeof(tmp
));
3375 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
3376 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
3383 * Callback to allocate NH hash entry on L3-VNI.
3385 static void *zl3vni_nh_alloc(void *p
)
3387 const zebra_neigh_t
*tmp_n
= p
;
3390 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
3397 * Add neighbor entry.
3399 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3400 struct ethaddr
*mac
)
3402 zebra_neigh_t tmp_n
;
3403 zebra_neigh_t
*n
= NULL
;
3405 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
3406 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
3407 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
3410 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
3412 memcpy(&n
->emac
, mac
, ETH_ALEN
);
3413 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3414 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
3420 * Delete neighbor entry.
3422 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3424 zebra_neigh_t
*tmp_n
;
3425 struct host_rb_entry
*hle
;
3427 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
3428 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
3430 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
3431 XFREE(MTYPE_HOST_PREFIX
, hle
);
3434 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
3436 XFREE(MTYPE_NEIGH
, tmp_n
);
3442 * Install remote nh as neigh into the kernel.
3444 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3451 if (!is_l3vni_oper_up(zl3vni
))
3454 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3455 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3458 flags
= NTF_EXT_LEARNED
;
3459 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
3460 flags
|= NTF_ROUTER
;
3461 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
3467 * Uninstall remote nh from the kernel.
3469 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3471 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3472 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3475 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
3478 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
3481 /* add remote vtep as a neigh entry */
3482 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
3483 struct ethaddr
*rmac
,
3484 struct prefix
*host_prefix
)
3486 char buf
[ETHER_ADDR_STRLEN
];
3487 char buf1
[INET6_ADDRSTRLEN
];
3488 zebra_neigh_t
*nh
= NULL
;
3490 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3492 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
3496 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
3497 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
3498 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3503 /* install the nh neigh in kernel */
3504 zl3vni_nh_install(zl3vni
, nh
);
3507 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
3512 /* handle nh neigh delete */
3513 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
3514 struct prefix
*host_prefix
)
3516 rb_delete_host(&nh
->host_rb
, host_prefix
);
3518 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
3519 /* uninstall from kernel */
3520 zl3vni_nh_uninstall(zl3vni
, nh
);
3522 /* delete the nh entry */
3523 zl3vni_nh_del(zl3vni
, nh
);
3527 /* handle neigh update from kernel - the only thing of interest is to
3528 * readd stale entries.
3530 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3534 zebra_neigh_t
*n
= NULL
;
3536 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3540 /* all next hop neigh are remote and installed by frr.
3541 * If the kernel has aged this entry, re-install.
3543 if (state
& NUD_STALE
)
3544 zl3vni_nh_install(zl3vni
, n
);
3549 /* handle neigh delete from kernel */
3550 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3552 zebra_neigh_t
*n
= NULL
;
3554 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3558 /* all next hop neigh are remote and installed by frr.
3559 * If we get an age out notification for these neigh entries, we have to
3562 zl3vni_nh_install(zl3vni
, n
);
3568 * Hash function for L3 VNI.
3570 static unsigned int l3vni_hash_keymake(void *p
)
3572 const zebra_l3vni_t
*zl3vni
= p
;
3574 return jhash_1word(zl3vni
->vni
, 0);
3578 * Compare 2 L3 VNI hash entries.
3580 static int l3vni_hash_cmp(const void *p1
, const void *p2
)
3582 const zebra_l3vni_t
*zl3vni1
= p1
;
3583 const zebra_l3vni_t
*zl3vni2
= p2
;
3585 return (zl3vni1
->vni
== zl3vni2
->vni
);
3589 * Callback to allocate L3 VNI hash entry.
3591 static void *zl3vni_alloc(void *p
)
3593 zebra_l3vni_t
*zl3vni
= NULL
;
3594 const zebra_l3vni_t
*tmp_l3vni
= p
;
3596 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
3597 zl3vni
->vni
= tmp_l3vni
->vni
;
3598 return ((void *)zl3vni
);
3602 * Look up L3 VNI hash entry.
3604 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
3606 struct zebra_ns
*zns
;
3607 zebra_l3vni_t tmp_l3vni
;
3608 zebra_l3vni_t
*zl3vni
= NULL
;
3610 zns
= zebra_ns_lookup(NS_DEFAULT
);
3612 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
3613 tmp_l3vni
.vni
= vni
;
3614 zl3vni
= hash_lookup(zns
->l3vni_table
, &tmp_l3vni
);
3620 * Add L3 VNI hash entry.
3622 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
3624 zebra_l3vni_t tmp_zl3vni
;
3625 struct zebra_ns
*zns
= NULL
;
3626 zebra_l3vni_t
*zl3vni
= NULL
;
3628 zns
= zebra_ns_lookup(NS_DEFAULT
);
3631 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
3632 tmp_zl3vni
.vni
= vni
;
3634 zl3vni
= hash_get(zns
->l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
3637 zl3vni
->vrf_id
= vrf_id
;
3638 zl3vni
->svi_if
= NULL
;
3639 zl3vni
->vxlan_if
= NULL
;
3640 zl3vni
->l2vnis
= list_new();
3641 zl3vni
->l2vnis
->cmp
= (int (*)(void *, void *))vni_hash_cmp
;
3643 /* Create hash table for remote RMAC */
3644 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
3645 "Zebra L3-VNI RMAC-Table");
3647 /* Create hash table for neighbors */
3648 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3649 "Zebra L3-VNI next-hop table");
3655 * Delete L3 VNI hash entry.
3657 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
3659 struct zebra_ns
*zns
;
3660 zebra_l3vni_t
*tmp_zl3vni
;
3662 zns
= zebra_ns_lookup(NS_DEFAULT
);
3665 /* free the list of l2vnis */
3666 list_delete_and_null(&zl3vni
->l2vnis
);
3667 zl3vni
->l2vnis
= NULL
;
3669 /* Free the rmac table */
3670 hash_free(zl3vni
->rmac_table
);
3671 zl3vni
->rmac_table
= NULL
;
3673 /* Free the nh table */
3674 hash_free(zl3vni
->nh_table
);
3675 zl3vni
->nh_table
= NULL
;
3677 /* Free the VNI hash entry and allocated memory. */
3678 tmp_zl3vni
= hash_release(zns
->l3vni_table
, zl3vni
);
3680 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
3685 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
3687 struct zebra_ns
*zns
= NULL
;
3688 struct route_node
*rn
= NULL
;
3689 struct interface
*ifp
= NULL
;
3691 /* loop through all vxlan-interface */
3692 zns
= zebra_ns_lookup(NS_DEFAULT
);
3693 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3695 struct zebra_if
*zif
= NULL
;
3696 struct zebra_l2info_vxlan
*vxl
= NULL
;
3698 ifp
= (struct interface
*)rn
->info
;
3703 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3706 vxl
= &zif
->l2info
.vxl
;
3707 if (vxl
->vni
== zl3vni
->vni
) {
3708 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3716 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
3718 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
3719 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
3724 if (!zl3vni
->vxlan_if
)
3727 zif
= zl3vni
->vxlan_if
->info
;
3731 vxl
= &zif
->l2info
.vxl
;
3733 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3736 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
3738 struct zebra_vrf
*zvrf
= NULL
;
3740 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
3744 return zl3vni_lookup(zvrf
->l3vni
);
3748 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3749 * neighbor notifications, to see if they are of interest.
3751 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
3752 struct interface
*br_if
)
3756 uint8_t bridge_vlan_aware
= 0;
3757 zebra_l3vni_t
*zl3vni
= NULL
;
3758 struct zebra_ns
*zns
= NULL
;
3759 struct route_node
*rn
= NULL
;
3760 struct zebra_if
*zif
= NULL
;
3761 struct interface
*tmp_if
= NULL
;
3762 struct zebra_l2info_bridge
*br
= NULL
;
3763 struct zebra_l2info_vxlan
*vxl
= NULL
;
3768 /* Make sure the linked interface is a bridge. */
3769 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3772 /* Determine if bridge is VLAN-aware or not */
3775 br
= &zif
->l2info
.br
;
3776 bridge_vlan_aware
= br
->vlan_aware
;
3777 if (bridge_vlan_aware
) {
3778 struct zebra_l2info_vlan
*vl
;
3780 if (!IS_ZEBRA_IF_VLAN(ifp
))
3785 vl
= &zif
->l2info
.vl
;
3789 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3790 /* TODO: Optimize with a hash. */
3791 zns
= zebra_ns_lookup(NS_DEFAULT
);
3792 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3793 tmp_if
= (struct interface
*)rn
->info
;
3797 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3799 if (!if_is_operative(tmp_if
))
3801 vxl
= &zif
->l2info
.vxl
;
3803 if (zif
->brslave_info
.br_if
!= br_if
)
3806 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3815 zl3vni
= zl3vni_lookup(vxl
->vni
);
3820 * Inform BGP about l3-vni.
3822 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
3824 struct stream
*s
= NULL
;
3825 struct zserv
*client
= NULL
;
3826 struct ethaddr rmac
;
3827 char buf
[ETHER_ADDR_STRLEN
];
3829 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3830 /* BGP may not be running. */
3835 memset(&rmac
, 0, sizeof(struct ethaddr
));
3836 zl3vni_get_rmac(zl3vni
, &rmac
);
3838 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3840 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
3841 stream_putl(s
, zl3vni
->vni
);
3842 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
3843 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
3844 stream_put(s
, &zl3vni
->filter
, sizeof(int));
3846 /* Write packet size. */
3847 stream_putw_at(s
, 0, stream_get_endp(s
));
3849 if (IS_ZEBRA_DEBUG_VXLAN
)
3851 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
3852 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3853 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
3854 inet_ntoa(zl3vni
->local_vtep_ip
),
3855 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
3856 ? "prefix-routes-only"
3858 zebra_route_string(client
->proto
));
3860 client
->l3vniadd_cnt
++;
3861 return zserv_send_message(client
, s
);
3865 * Inform BGP about local l3-VNI deletion.
3867 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
3869 struct stream
*s
= NULL
;
3870 struct zserv
*client
= NULL
;
3872 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3873 /* BGP may not be running. */
3877 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3879 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
3880 stream_putl(s
, zl3vni
->vni
);
3882 /* Write packet size. */
3883 stream_putw_at(s
, 0, stream_get_endp(s
));
3885 if (IS_ZEBRA_DEBUG_VXLAN
)
3886 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
3887 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3888 zebra_route_string(client
->proto
));
3890 client
->l3vnidel_cnt
++;
3891 return zserv_send_message(client
, s
);
3894 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
3899 /* send l3vni add to BGP */
3900 zl3vni_send_add_to_client(zl3vni
);
3903 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
3908 /* send l3-vni del to BGP*/
3909 zl3vni_send_del_to_client(zl3vni
);
3912 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
, void *ctxt
)
3914 zebra_vni_t
*zvni
= (zebra_vni_t
*)backet
->data
;
3915 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
3917 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
3918 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3922 * handle transition of vni from l2 to l3 and vice versa
3924 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
3927 zebra_vni_t
*zvni
= NULL
;
3929 /* There is a possibility that VNI notification was already received
3930 * from kernel and we programmed it as L2-VNI
3931 * In such a case we need to delete this L2-VNI first, so
3932 * that it can be reprogrammed as L3-VNI in the system. It is also
3933 * possible that the vrf-vni mapping is removed from FRR while the vxlan
3934 * interface is still present in kernel. In this case to keep it
3935 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
3938 /* Locate hash entry */
3939 zvni
= zvni_lookup(vni
);
3943 if (IS_ZEBRA_DEBUG_VXLAN
)
3944 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
3946 /* Delete VNI from BGP. */
3947 zvni_send_del_to_client(zvni
->vni
);
3949 /* Free up all neighbors and MAC, if any. */
3950 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
3951 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
3953 /* Free up all remote VTEPs, if any. */
3954 zvni_vtep_del_all(zvni
, 0);
3956 /* Delete the hash entry. */
3957 if (zvni_del(zvni
)) {
3958 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
3959 "Failed to del VNI hash %p, VNI %u", zvni
,
3964 /* TODO_MITESH: This needs to be thought through. We don't have
3965 * enough information at this point to reprogram the vni as
3966 * l2-vni. One way is to store the required info in l3-vni and
3967 * used it solely for this purpose
3974 /* delete and uninstall rmac hash entry */
3975 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
, void *ctx
)
3977 zebra_mac_t
*zrmac
= NULL
;
3978 zebra_l3vni_t
*zl3vni
= NULL
;
3980 zrmac
= (zebra_mac_t
*)backet
->data
;
3981 zl3vni
= (zebra_l3vni_t
*)ctx
;
3982 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3983 zl3vni_rmac_del(zl3vni
, zrmac
);
3986 /* delete and uninstall nh hash entry */
3987 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
, void *ctx
)
3989 zebra_neigh_t
*n
= NULL
;
3990 zebra_l3vni_t
*zl3vni
= NULL
;
3992 n
= (zebra_neigh_t
*)backet
->data
;
3993 zl3vni
= (zebra_l3vni_t
*)ctx
;
3994 zl3vni_nh_uninstall(zl3vni
, n
);
3995 zl3vni_nh_del(zl3vni
, n
);
3998 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
4001 struct zserv
*client
= NULL
;
4002 struct stream
*s
= NULL
;
4003 char buf
[PREFIX_STRLEN
];
4005 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4006 /* BGP may not be running. */
4010 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4012 zclient_create_header(s
, cmd
, vrf_id
);
4013 stream_put(s
, p
, sizeof(struct prefix
));
4015 /* Write packet size. */
4016 stream_putw_at(s
, 0, stream_get_endp(s
));
4018 if (IS_ZEBRA_DEBUG_VXLAN
)
4019 zlog_debug("Send ip prefix %s %s on vrf %s",
4020 prefix2str(p
, buf
, sizeof(buf
)),
4021 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
4022 vrf_id_to_name(vrf_id
));
4024 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
4025 client
->prefixadd_cnt
++;
4027 client
->prefixdel_cnt
++;
4029 return zserv_send_message(client
, s
);
4032 /* re-add remote rmac if needed */
4033 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
4034 struct ethaddr
*rmac
)
4036 char buf
[ETHER_ADDR_STRLEN
];
4037 zebra_mac_t
*zrmac
= NULL
;
4039 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4043 if (IS_ZEBRA_DEBUG_VXLAN
)
4044 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
4045 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
4047 zl3vni_rmac_install(zl3vni
, zrmac
);
4051 /* Process a remote MACIP add from BGP. */
4052 static void process_remote_macip_add(vni_t vni
,
4053 struct ethaddr
*macaddr
,
4055 struct ipaddr
*ipaddr
,
4058 struct in_addr vtep_ip
)
4061 zebra_vtep_t
*zvtep
;
4062 zebra_mac_t
*mac
, *old_mac
;
4063 zebra_neigh_t
*n
= NULL
;
4064 int update_mac
= 0, update_neigh
= 0;
4065 char buf
[ETHER_ADDR_STRLEN
];
4066 char buf1
[INET6_ADDRSTRLEN
];
4067 struct interface
*ifp
= NULL
;
4068 struct zebra_if
*zif
= NULL
;
4074 /* Locate VNI hash entry - expected to exist. */
4075 zvni
= zvni_lookup(vni
);
4077 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
4081 ifp
= zvni
->vxlan_if
;
4085 !if_is_operative(ifp
) ||
4087 !zif
->brslave_info
.br_if
) {
4088 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
4093 /* The remote VTEP specified should normally exist, but it is
4094 * possible that when peering comes up, peer may advertise MACIP
4095 * routes before advertising type-3 routes.
4097 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
4099 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
4101 EC_ZEBRA_VTEP_ADD_FAILED
,
4102 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
4107 zvni_vtep_install(zvni
, &vtep_ip
);
4110 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
4111 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
4112 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
4114 mac
= zvni_mac_lookup(zvni
, macaddr
);
4116 /* Ignore if the mac is already present as a gateway mac */
4118 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
4119 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
4120 if (IS_ZEBRA_DEBUG_VXLAN
)
4121 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
4123 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4124 ipa_len
? " IP " : "",
4126 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
4130 /* check if the remote MAC is unknown or has a change.
4131 * If so, that needs to be updated first. Note that client could
4132 * install MAC and MACIP separately or just install the latter.
4135 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
4136 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
4137 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
4138 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
4139 || seq
!= mac
->rem_seq
)
4144 mac
= zvni_mac_add(zvni
, macaddr
);
4147 "Failed to add MAC %s VNI %u Remote VTEP %s",
4148 prefix_mac2str(macaddr
, buf
,
4150 vni
, inet_ntoa(vtep_ip
));
4154 /* Is this MAC created for a MACIP? */
4156 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
4158 const char *mac_type
;
4160 /* When host moves but changes its (MAC,IP)
4161 * binding, BGP may install a MACIP entry that
4162 * corresponds to "older" location of the host
4163 * in transient situations (because {IP1,M1}
4164 * is a different route from {IP1,M2}). Check
4165 * the sequence number and ignore this update
4168 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
4169 tmp_seq
= mac
->loc_seq
;
4172 tmp_seq
= mac
->rem_seq
;
4173 mac_type
= "remote";
4175 if (seq
< tmp_seq
) {
4176 if (IS_ZEBRA_DEBUG_VXLAN
)
4177 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
4179 prefix_mac2str(macaddr
,
4181 ipa_len
? " IP " : "",
4184 buf1
, sizeof(buf1
)) : "",
4191 /* Set "auto" and "remote" forwarding info. */
4192 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
4193 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
4194 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
4195 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
4198 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
4200 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
4203 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
4205 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
4207 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
4209 /* Install the entry. */
4210 zvni_mac_install(zvni
, mac
);
4213 /* Update seq number. */
4216 /* If there is no IP, return after clearing AUTO flag of MAC. */
4218 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
4222 /* Check if the remote neighbor itself is unknown or has a
4223 * change. If so, create or update and then install the entry.
4225 n
= zvni_neigh_lookup(zvni
, ipaddr
);
4227 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
4228 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
4229 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
4230 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
4231 || seq
!= n
->rem_seq
)
4236 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
4239 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
4240 ipaddr2str(ipaddr
, buf1
,
4242 prefix_mac2str(macaddr
, buf
,
4244 vni
, inet_ntoa(vtep_ip
));
4251 /* When host moves but changes its (MAC,IP)
4252 * binding, BGP may install a MACIP entry that
4253 * corresponds to "older" location of the host
4254 * in transient situations (because {IP1,M1}
4255 * is a different route from {IP1,M2}). Check
4256 * the sequence number and ignore this update
4259 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
4260 tmp_seq
= n
->loc_seq
;
4263 tmp_seq
= n
->rem_seq
;
4266 if (seq
< tmp_seq
) {
4267 if (IS_ZEBRA_DEBUG_VXLAN
)
4268 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
4270 prefix_mac2str(macaddr
,
4272 ipa_len
? " IP " : "",
4275 buf1
, sizeof(buf1
)) : "",
4280 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
4281 /* MAC change, send a delete for old
4282 * neigh if learnt locally.
4284 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
4285 IS_ZEBRA_NEIGH_ACTIVE(n
))
4286 zvni_neigh_send_del_to_client(
4290 /* update neigh list for macs */
4291 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
4293 listnode_delete(old_mac
->neigh_list
, n
);
4294 zvni_deref_ip2mac(zvni
, old_mac
);
4296 listnode_add_sort(mac
->neigh_list
, n
);
4297 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
4301 /* Set "remote" forwarding info. */
4302 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
4303 n
->r_vtep_ip
= vtep_ip
;
4304 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4306 /* Set router flag (R-bit) to this Neighbor entry */
4307 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
4308 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
4310 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
4312 /* Install the entry. */
4313 zvni_neigh_install(zvni
, n
);
4316 /* Update seq number. */
4320 /* Process a remote MACIP delete from BGP. */
4321 static void process_remote_macip_del(vni_t vni
,
4322 struct ethaddr
*macaddr
,
4324 struct ipaddr
*ipaddr
,
4325 struct in_addr vtep_ip
)
4328 zebra_mac_t
*mac
= NULL
;
4329 zebra_neigh_t
*n
= NULL
;
4330 struct interface
*ifp
= NULL
;
4331 struct zebra_if
*zif
= NULL
;
4332 char buf
[ETHER_ADDR_STRLEN
];
4333 char buf1
[INET6_ADDRSTRLEN
];
4335 /* Locate VNI hash entry - expected to exist. */
4336 zvni
= zvni_lookup(vni
);
4338 if (IS_ZEBRA_DEBUG_VXLAN
)
4339 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
4343 ifp
= zvni
->vxlan_if
;
4347 !if_is_operative(ifp
) ||
4349 !zif
->brslave_info
.br_if
) {
4350 if (IS_ZEBRA_DEBUG_VXLAN
)
4351 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
4356 /* The remote VTEP specified is normally expected to exist, but
4357 * it is possible that the peer may delete the VTEP before deleting
4358 * any MACs referring to the VTEP, in which case the handler (see
4359 * remote_vtep_del) would have already deleted the MACs.
4361 if (!zvni_vtep_find(zvni
, &vtep_ip
))
4364 mac
= zvni_mac_lookup(zvni
, macaddr
);
4366 n
= zvni_neigh_lookup(zvni
, ipaddr
);
4369 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
4370 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4371 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
4375 /* If the remote mac or neighbor doesn't exist there is nothing
4376 * more to do. Otherwise, uninstall the entry and then remove it.
4381 /* Ignore the delete if this mac is a gateway mac-ip */
4383 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
4384 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
4386 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
4388 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4389 ipa_len
? " IP " : "",
4391 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
4395 /* Uninstall remote neighbor or MAC. */
4397 /* When the MAC changes for an IP, it is possible the
4398 * client may update the new MAC before trying to delete the
4399 * "old" neighbor (as these are two different MACIP routes).
4400 * Do the delete only if the MAC matches.
4402 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
4403 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
4404 zvni_neigh_uninstall(zvni
, n
);
4405 zvni_neigh_del(zvni
, n
);
4406 zvni_deref_ip2mac(zvni
, mac
);
4409 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
4410 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
4412 /* If all remote neighbors referencing a remote MAC
4413 * go away, we need to uninstall the MAC.
4415 if (remote_neigh_count(mac
) == 0) {
4416 zvni_mac_uninstall(zvni
, mac
);
4417 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
4419 if (list_isempty(mac
->neigh_list
))
4420 zvni_mac_del(zvni
, mac
);
4422 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
4428 /* Public functions */
4430 int is_l3vni_for_prefix_routes_only(vni_t vni
)
4432 zebra_l3vni_t
*zl3vni
= NULL
;
4434 zl3vni
= zl3vni_lookup(vni
);
4438 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
4441 /* handle evpn route in vrf table */
4442 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
4443 struct ipaddr
*vtep_ip
,
4444 struct prefix
*host_prefix
)
4446 zebra_l3vni_t
*zl3vni
= NULL
;
4447 struct ipaddr ipv4_vtep
;
4449 zl3vni
= zl3vni_from_vrf(vrf_id
);
4450 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
4454 * add the next hop neighbor -
4455 * neigh to be installed is the ipv6 nexthop neigh
4457 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
4460 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
4461 * address. Rmac is programmed against the ipv4 vtep because we only
4462 * support ipv4 tunnels in the h/w right now
4464 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
4465 ipv4_vtep
.ipa_type
= IPADDR_V4
;
4466 if (vtep_ip
->ipa_type
== IPADDR_V6
)
4467 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
4468 &(ipv4_vtep
.ipaddr_v4
));
4470 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
4471 sizeof(struct in_addr
));
4474 * add the rmac - remote rmac to be installed is against the ipv4
4477 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
4480 /* handle evpn vrf route delete */
4481 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
4482 struct ipaddr
*vtep_ip
,
4483 struct prefix
*host_prefix
)
4485 zebra_l3vni_t
*zl3vni
= NULL
;
4486 zebra_neigh_t
*nh
= NULL
;
4487 zebra_mac_t
*zrmac
= NULL
;
4489 zl3vni
= zl3vni_from_vrf(vrf_id
);
4493 /* find the next hop entry and rmac entry */
4494 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4497 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
4499 /* delete the next hop entry */
4500 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
4502 /* delete the rmac entry */
4504 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
4508 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
4509 struct ethaddr
*rmac
, bool use_json
)
4511 zebra_l3vni_t
*zl3vni
= NULL
;
4512 zebra_mac_t
*zrmac
= NULL
;
4513 json_object
*json
= NULL
;
4515 if (!is_evpn_enabled()) {
4517 vty_out(vty
, "{}\n");
4522 json
= json_object_new_object();
4524 zl3vni
= zl3vni_lookup(l3vni
);
4527 vty_out(vty
, "{}\n");
4529 vty_out(vty
, "%% L3-VNI %u doesnt exist\n", l3vni
);
4533 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4536 vty_out(vty
, "{}\n");
4539 "%% Requested RMAC doesnt exist in L3-VNI %u",
4544 zl3vni_print_rmac(zrmac
, vty
, json
);
4547 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4548 json
, JSON_C_TO_STRING_PRETTY
));
4549 json_object_free(json
);
4553 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
4555 zebra_l3vni_t
*zl3vni
;
4557 struct rmac_walk_ctx wctx
;
4558 json_object
*json
= NULL
;
4560 if (!is_evpn_enabled())
4563 zl3vni
= zl3vni_lookup(l3vni
);
4566 vty_out(vty
, "{}\n");
4568 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4571 num_rmacs
= hashcount(zl3vni
->rmac_table
);
4576 json
= json_object_new_object();
4578 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
4582 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
4584 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
4586 json_object_int_add(json
, "numRmacs", num_rmacs
);
4588 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
4591 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4592 json
, JSON_C_TO_STRING_PRETTY
));
4593 json_object_free(json
);
4597 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
4599 struct zebra_ns
*zns
= NULL
;
4600 json_object
*json
= NULL
;
4603 if (!is_evpn_enabled()) {
4605 vty_out(vty
, "{}\n");
4609 zns
= zebra_ns_lookup(NS_DEFAULT
);
4612 vty_out(vty
, "{}\n");
4617 json
= json_object_new_object();
4621 hash_iterate(zns
->l3vni_table
,
4622 (void (*)(struct hash_backet
*,
4623 void *))zl3vni_print_rmac_hash_all_vni
,
4627 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4628 json
, JSON_C_TO_STRING_PRETTY
));
4629 json_object_free(json
);
4633 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
4634 struct ipaddr
*ip
, bool use_json
)
4636 zebra_l3vni_t
*zl3vni
= NULL
;
4637 zebra_neigh_t
*n
= NULL
;
4638 json_object
*json
= NULL
;
4640 if (!is_evpn_enabled()) {
4642 vty_out(vty
, "{}\n");
4647 json
= json_object_new_object();
4649 zl3vni
= zl3vni_lookup(l3vni
);
4652 vty_out(vty
, "{}\n");
4654 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4658 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4661 vty_out(vty
, "{}\n");
4664 "%% Requested next-hop not present for L3-VNI %u",
4669 zl3vni_print_nh(n
, vty
, json
);
4672 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4673 json
, JSON_C_TO_STRING_PRETTY
));
4674 json_object_free(json
);
4678 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
4681 struct nh_walk_ctx wctx
;
4682 json_object
*json
= NULL
;
4683 zebra_l3vni_t
*zl3vni
= NULL
;
4685 if (!is_evpn_enabled())
4688 zl3vni
= zl3vni_lookup(l3vni
);
4691 vty_out(vty
, "{}\n");
4693 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4697 num_nh
= hashcount(zl3vni
->nh_table
);
4702 json
= json_object_new_object();
4707 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
4709 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
4711 json_object_int_add(json
, "numNextHops", num_nh
);
4713 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
4716 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4717 json
, JSON_C_TO_STRING_PRETTY
));
4718 json_object_free(json
);
4722 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
4724 struct zebra_ns
*zns
= NULL
;
4725 json_object
*json
= NULL
;
4728 if (!is_evpn_enabled()) {
4730 vty_out(vty
, "{}\n");
4734 zns
= zebra_ns_lookup(NS_DEFAULT
);
4739 json
= json_object_new_object();
4743 hash_iterate(zns
->l3vni_table
,
4744 (void (*)(struct hash_backet
*,
4745 void *))zl3vni_print_nh_hash_all_vni
,
4749 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4750 json
, JSON_C_TO_STRING_PRETTY
));
4751 json_object_free(json
);
4756 * Display L3 VNI information (VTY command handler).
4758 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
4761 json_object
*json
= NULL
;
4762 zebra_l3vni_t
*zl3vni
= NULL
;
4764 if (!is_evpn_enabled()) {
4766 vty_out(vty
, "{}\n");
4770 zl3vni
= zl3vni_lookup(vni
);
4773 vty_out(vty
, "{}\n");
4775 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4780 json
= json_object_new_object();
4784 zl3vni_print(zl3vni
, (void *)args
);
4787 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4788 json
, JSON_C_TO_STRING_PRETTY
));
4789 json_object_free(json
);
4793 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4794 json_object
*json_vrfs
)
4796 char buf
[ETHER_ADDR_STRLEN
];
4797 zebra_l3vni_t
*zl3vni
= NULL
;
4799 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4804 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
4805 zvrf_name(zvrf
), zl3vni
->vni
,
4806 zl3vni_vxlan_if_name(zl3vni
),
4807 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
4808 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4810 json_object
*json_vrf
= NULL
;
4812 json_vrf
= json_object_new_object();
4813 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
4814 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
4815 json_object_string_add(json_vrf
, "vxlanIntf",
4816 zl3vni_vxlan_if_name(zl3vni
));
4817 json_object_string_add(json_vrf
, "sviIntf",
4818 zl3vni_svi_if_name(zl3vni
));
4819 json_object_string_add(json_vrf
, "state",
4820 zl3vni_state2str(zl3vni
));
4821 json_object_string_add(
4822 json_vrf
, "routerMac",
4823 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4824 json_object_array_add(json_vrfs
, json_vrf
);
4829 * Display Neighbors for a VNI (VTY command handler).
4831 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4832 vni_t vni
, bool use_json
)
4836 struct neigh_walk_ctx wctx
;
4837 json_object
*json
= NULL
;
4839 if (!is_evpn_enabled())
4841 zvni
= zvni_lookup(vni
);
4844 vty_out(vty
, "{}\n");
4846 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4849 num_neigh
= hashcount(zvni
->neigh_table
);
4854 json
= json_object_new_object();
4856 /* Since we have IPv6 addresses to deal with which can vary widely in
4857 * size, we try to be a bit more elegant in display by first computing
4858 * the maximum width.
4860 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4863 wctx
.addr_width
= 15;
4865 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4869 "Number of ARPs (local and remote) known for this VNI: %u\n",
4871 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
4872 -wctx
.addr_width
, "IP", "Type",
4873 "State", "MAC", "Remote VTEP");
4875 json_object_int_add(json
, "numArpNd", num_neigh
);
4877 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4879 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4880 json
, JSON_C_TO_STRING_PRETTY
));
4881 json_object_free(json
);
4886 * Display neighbors across all VNIs (VTY command handler).
4888 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4891 json_object
*json
= NULL
;
4894 if (!is_evpn_enabled())
4898 json
= json_object_new_object();
4902 hash_iterate(zvrf
->vni_table
,
4903 (void (*)(struct hash_backet
*,
4904 void *))zvni_print_neigh_hash_all_vni
,
4907 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4908 json
, JSON_C_TO_STRING_PRETTY
));
4909 json_object_free(json
);
4914 * Display specific neighbor for a VNI, if present (VTY command handler).
4916 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
4917 struct zebra_vrf
*zvrf
, vni_t vni
,
4918 struct ipaddr
*ip
, bool use_json
)
4922 json_object
*json
= NULL
;
4924 if (!is_evpn_enabled())
4926 zvni
= zvni_lookup(vni
);
4929 vty_out(vty
, "{}\n");
4931 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4934 n
= zvni_neigh_lookup(zvni
, ip
);
4938 "%% Requested neighbor does not exist in VNI %u\n",
4943 json
= json_object_new_object();
4945 zvni_print_neigh(n
, vty
, json
);
4948 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4949 json
, JSON_C_TO_STRING_PRETTY
));
4950 json_object_free(json
);
4955 * Display neighbors for a VNI from specific VTEP (VTY command handler).
4956 * By definition, these are remote neighbors.
4958 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4959 vni_t vni
, struct in_addr vtep_ip
,
4964 struct neigh_walk_ctx wctx
;
4965 json_object
*json
= NULL
;
4967 if (!is_evpn_enabled())
4969 zvni
= zvni_lookup(vni
);
4972 vty_out(vty
, "{}\n");
4974 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4977 num_neigh
= hashcount(zvni
->neigh_table
);
4981 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4984 wctx
.addr_width
= 15;
4985 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
4986 wctx
.r_vtep_ip
= vtep_ip
;
4988 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4989 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4992 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4993 json
, JSON_C_TO_STRING_PRETTY
));
4994 json_object_free(json
);
4999 * Display MACs for a VNI (VTY command handler).
5001 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5002 vni_t vni
, bool use_json
)
5006 struct mac_walk_ctx wctx
;
5007 json_object
*json
= NULL
;
5008 json_object
*json_mac
= NULL
;
5010 if (!is_evpn_enabled())
5012 zvni
= zvni_lookup(vni
);
5015 vty_out(vty
, "{}\n");
5017 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5020 num_macs
= num_valid_macs(zvni
);
5025 json
= json_object_new_object();
5026 json_mac
= json_object_new_object();
5029 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5032 wctx
.json
= json_mac
;
5036 "Number of MACs (local and remote) known for this VNI: %u\n",
5038 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
5039 "Intf/Remote VTEP", "VLAN");
5041 json_object_int_add(json
, "numMacs", num_macs
);
5043 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
5046 json_object_object_add(json
, "macs", json_mac
);
5047 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5048 json
, JSON_C_TO_STRING_PRETTY
));
5049 json_object_free(json
);
5054 * Display MACs for all VNIs (VTY command handler).
5056 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5059 struct mac_walk_ctx wctx
;
5060 json_object
*json
= NULL
;
5062 if (!is_evpn_enabled()) {
5064 vty_out(vty
, "{}\n");
5068 json
= json_object_new_object();
5070 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5073 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
5076 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5077 json
, JSON_C_TO_STRING_PRETTY
));
5078 json_object_free(json
);
5083 * Display MACs for all VNIs (VTY command handler).
5085 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
5086 struct zebra_vrf
*zvrf
,
5087 struct in_addr vtep_ip
, bool use_json
)
5089 struct mac_walk_ctx wctx
;
5090 json_object
*json
= NULL
;
5092 if (!is_evpn_enabled())
5096 json
= json_object_new_object();
5098 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5100 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
5101 wctx
.r_vtep_ip
= vtep_ip
;
5103 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
5106 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5107 json
, JSON_C_TO_STRING_PRETTY
));
5108 json_object_free(json
);
5113 * Display specific MAC for a VNI, if present (VTY command handler).
5115 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5116 vni_t vni
, struct ethaddr
*macaddr
)
5121 if (!is_evpn_enabled())
5123 zvni
= zvni_lookup(vni
);
5125 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5128 mac
= zvni_mac_lookup(zvni
, macaddr
);
5130 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
5135 zvni_print_mac(mac
, vty
);
5139 * Display MACs for a VNI from specific VTEP (VTY command handler).
5141 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5142 vni_t vni
, struct in_addr vtep_ip
,
5147 struct mac_walk_ctx wctx
;
5148 json_object
*json
= NULL
;
5149 json_object
*json_mac
= NULL
;
5151 if (!is_evpn_enabled())
5153 zvni
= zvni_lookup(vni
);
5156 vty_out(vty
, "{}\n");
5158 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5161 num_macs
= num_valid_macs(zvni
);
5166 json
= json_object_new_object();
5167 json_mac
= json_object_new_object();
5170 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5173 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
5174 wctx
.r_vtep_ip
= vtep_ip
;
5175 wctx
.json
= json_mac
;
5176 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
5179 json_object_int_add(json
, "numMacs", wctx
.count
);
5181 json_object_object_add(json
, "macs", json_mac
);
5182 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5183 json
, JSON_C_TO_STRING_PRETTY
));
5184 json_object_free(json
);
5190 * Display VNI information (VTY command handler).
5192 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
5195 json_object
*json
= NULL
;
5197 zebra_l3vni_t
*zl3vni
= NULL
;
5198 zebra_vni_t
*zvni
= NULL
;
5200 if (!is_evpn_enabled())
5204 json
= json_object_new_object();
5208 zl3vni
= zl3vni_lookup(vni
);
5210 zl3vni_print(zl3vni
, (void *)args
);
5212 zvni
= zvni_lookup(vni
);
5215 vty_out(vty
, "{}\n");
5217 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5221 zvni_print(zvni
, (void *)args
);
5225 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5226 json
, JSON_C_TO_STRING_PRETTY
));
5227 json_object_free(json
);
5231 /* Display all global details for EVPN */
5232 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
5237 json_object
*json
= NULL
;
5238 struct zebra_ns
*zns
= NULL
;
5239 struct zebra_vrf
*zvrf
= NULL
;
5241 if (!is_evpn_enabled())
5244 zns
= zebra_ns_lookup(NS_DEFAULT
);
5248 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
5252 num_l3vnis
= hashcount(zns
->l3vni_table
);
5253 num_l2vnis
= hashcount(zvrf
->vni_table
);
5254 num_vnis
= num_l2vnis
+ num_l3vnis
;
5257 json
= json_object_new_object();
5258 json_object_string_add(json
, "advertiseGatewayMacip",
5259 zvrf
->advertise_gw_macip
? "Yes" : "No");
5260 json_object_int_add(json
, "numVnis", num_vnis
);
5261 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
5262 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
5264 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
5265 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
5266 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
5267 zvrf
->advertise_gw_macip
? "Yes" : "No");
5271 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5272 json
, JSON_C_TO_STRING_PRETTY
));
5273 json_object_free(json
);
5278 * Display VNI hash table (VTY command handler).
5280 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5283 json_object
*json
= NULL
;
5284 struct zebra_ns
*zns
= NULL
;
5287 if (!is_evpn_enabled())
5290 zns
= zebra_ns_lookup(NS_DEFAULT
);
5296 json
= json_object_new_object();
5298 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
5299 "Type", "VxLAN IF", "# MACs", "# ARPs",
5300 "# Remote VTEPs", "Tenant VRF");
5305 /* Display all L2-VNIs */
5306 hash_iterate(zvrf
->vni_table
,
5307 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
5310 /* Display all L3-VNIs */
5311 hash_iterate(zns
->l3vni_table
,
5312 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
5316 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5317 json
, JSON_C_TO_STRING_PRETTY
));
5318 json_object_free(json
);
5323 * Handle neighbor delete notification from the kernel (on a VLAN device
5324 * / L3 interface). This may result in either the neighbor getting deleted
5325 * from our database or being re-added to the kernel (if it is a valid
5328 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
5329 struct interface
*link_if
,
5332 char buf
[INET6_ADDRSTRLEN
];
5333 char buf2
[ETHER_ADDR_STRLEN
];
5334 zebra_neigh_t
*n
= NULL
;
5335 zebra_vni_t
*zvni
= NULL
;
5336 zebra_mac_t
*zmac
= NULL
;
5337 zebra_l3vni_t
*zl3vni
= NULL
;
5339 /* check if this is a remote neigh entry corresponding to remote
5342 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5344 return zl3vni_local_nh_del(zl3vni
, ip
);
5346 /* We are only interested in neighbors on an SVI that resides on top
5347 * of a VxLAN bridge.
5349 zvni
= zvni_from_svi(ifp
, link_if
);
5353 if (!zvni
->vxlan_if
) {
5355 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
5360 if (IS_ZEBRA_DEBUG_VXLAN
)
5361 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
5362 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
5363 ifp
->ifindex
, zvni
->vni
);
5365 /* If entry doesn't exist, nothing to do. */
5366 n
= zvni_neigh_lookup(zvni
, ip
);
5370 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
5372 if (IS_ZEBRA_DEBUG_VXLAN
)
5374 "Trying to del a neigh %s without a mac %s on VNI %u",
5375 ipaddr2str(ip
, buf
, sizeof(buf
)),
5376 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
5382 /* If it is a remote entry, the kernel has aged this out or someone has
5383 * deleted it, it needs to be re-installed as Quagga is the owner.
5385 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
5386 zvni_neigh_install(zvni
, n
);
5390 /* Remove neighbor from BGP. */
5391 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
5392 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0);
5394 /* Delete this neighbor entry. */
5395 zvni_neigh_del(zvni
, n
);
5397 /* see if the AUTO mac needs to be deleted */
5398 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
5399 && !listcount(zmac
->neigh_list
))
5400 zvni_mac_del(zvni
, zmac
);
5406 * Handle neighbor add or update notification from the kernel (on a VLAN
5407 * device / L3 interface). This is typically for a local neighbor but can
5408 * also be for a remote neighbor (e.g., ageout notification). It could
5409 * also be a "move" scenario.
5411 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
5412 struct interface
*link_if
,
5414 struct ethaddr
*macaddr
,
5419 char buf
[ETHER_ADDR_STRLEN
];
5420 char buf2
[INET6_ADDRSTRLEN
];
5421 zebra_vni_t
*zvni
= NULL
;
5422 zebra_l3vni_t
*zl3vni
= NULL
;
5424 /* check if this is a remote neigh entry corresponding to remote
5427 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5429 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
5431 /* We are only interested in neighbors on an SVI that resides on top
5432 * of a VxLAN bridge.
5434 zvni
= zvni_from_svi(ifp
, link_if
);
5438 if (IS_ZEBRA_DEBUG_VXLAN
)
5440 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
5441 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
5442 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5443 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
5444 is_router
? "router " : "",
5447 /* Is this about a local neighbor or a remote one? */
5449 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
5452 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
5457 * Handle message from client to delete a remote MACIP for a VNI.
5459 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
5463 struct ethaddr macaddr
;
5465 struct in_addr vtep_ip
;
5466 uint16_t l
= 0, ipa_len
;
5467 char buf
[ETHER_ADDR_STRLEN
];
5468 char buf1
[INET6_ADDRSTRLEN
];
5470 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5471 memset(&ip
, 0, sizeof(struct ipaddr
));
5472 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5476 while (l
< hdr
->length
) {
5477 /* Obtain each remote MACIP and process. */
5478 /* Message contains VNI, followed by MAC followed by IP (if any)
5479 * followed by remote VTEP IP.
5481 memset(&ip
, 0, sizeof(ip
));
5482 STREAM_GETL(s
, vni
);
5483 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5484 STREAM_GETL(s
, ipa_len
);
5486 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5488 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5490 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5491 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5492 l
+= IPV4_MAX_BYTELEN
;
5494 if (IS_ZEBRA_DEBUG_VXLAN
)
5496 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
5498 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5499 ipa_len
? " IP " : "",
5501 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
5503 zebra_route_string(client
->proto
));
5505 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
5513 * Handle message from client to add a remote MACIP for a VNI. This
5514 * could be just the add of a MAC address or the add of a neighbor
5517 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
5521 struct ethaddr macaddr
;
5523 struct in_addr vtep_ip
;
5524 uint16_t l
= 0, ipa_len
;
5527 char buf
[ETHER_ADDR_STRLEN
];
5528 char buf1
[INET6_ADDRSTRLEN
];
5530 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5531 memset(&ip
, 0, sizeof(struct ipaddr
));
5532 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5534 if (!EVPN_ENABLED(zvrf
)) {
5535 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
5541 while (l
< hdr
->length
) {
5542 /* Obtain each remote MACIP and process. */
5543 /* Message contains VNI, followed by MAC followed by IP (if any)
5544 * followed by remote VTEP IP.
5546 memset(&ip
, 0, sizeof(ip
));
5547 STREAM_GETL(s
, vni
);
5548 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5549 STREAM_GETL(s
, ipa_len
);
5551 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5553 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5555 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5556 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5557 l
+= IPV4_MAX_BYTELEN
;
5559 /* Get flags - sticky mac and/or gateway mac */
5560 STREAM_GETC(s
, flags
);
5562 STREAM_GETL(s
, seq
);
5565 if (IS_ZEBRA_DEBUG_VXLAN
)
5567 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
5569 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5570 ipa_len
? " IP " : "",
5572 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
5573 flags
, seq
, inet_ntoa(vtep_ip
),
5574 zebra_route_string(client
->proto
));
5576 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
5577 flags
, seq
, vtep_ip
);
5585 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5586 * us, this must involve a multihoming scenario. Treat this as implicit delete
5587 * of any prior local MAC.
5589 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
5590 struct interface
*br_if
,
5591 struct ethaddr
*macaddr
, vlanid_t vid
)
5593 struct zebra_if
*zif
;
5594 struct zebra_l2info_vxlan
*vxl
;
5598 char buf
[ETHER_ADDR_STRLEN
];
5602 vxl
= &zif
->l2info
.vxl
;
5605 /* Check if EVPN is enabled. */
5606 if (!is_evpn_enabled())
5609 /* Locate hash entry; it is expected to exist. */
5610 zvni
= zvni_lookup(vni
);
5614 /* If entry doesn't exist, nothing to do. */
5615 mac
= zvni_mac_lookup(zvni
, macaddr
);
5619 /* Is it a local entry? */
5620 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5623 if (IS_ZEBRA_DEBUG_VXLAN
)
5625 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5626 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5629 /* Remove MAC from BGP. */
5630 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5633 * If there are no neigh associated with the mac delete the mac
5634 * else mark it as AUTO for forward reference
5636 if (!listcount(mac
->neigh_list
)) {
5637 zvni_mac_del(zvni
, mac
);
5639 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5640 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5647 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5648 * This can happen because the remote MAC entries are also added as "dynamic",
5649 * so the kernel can ageout the entry.
5651 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
5652 struct interface
*br_if
,
5653 struct ethaddr
*macaddr
, vlanid_t vid
)
5655 struct zebra_if
*zif
= NULL
;
5656 struct zebra_l2info_vxlan
*vxl
= NULL
;
5658 zebra_vni_t
*zvni
= NULL
;
5659 zebra_l3vni_t
*zl3vni
= NULL
;
5660 zebra_mac_t
*mac
= NULL
;
5661 char buf
[ETHER_ADDR_STRLEN
];
5665 vxl
= &zif
->l2info
.vxl
;
5668 /* Check if EVPN is enabled. */
5669 if (!is_evpn_enabled())
5672 /* check if this is a remote RMAC and readd simillar to remote macs */
5673 zl3vni
= zl3vni_lookup(vni
);
5675 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
5677 /* Locate hash entry; it is expected to exist. */
5678 zvni
= zvni_lookup(vni
);
5682 /* If entry doesn't exist, nothing to do. */
5683 mac
= zvni_mac_lookup(zvni
, macaddr
);
5687 /* Is it a remote entry? */
5688 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
5691 if (IS_ZEBRA_DEBUG_VXLAN
)
5692 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
5693 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5696 zvni_mac_install(zvni
, mac
);
5701 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
5703 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
5704 struct ethaddr
*macaddr
, vlanid_t vid
)
5708 char buf
[ETHER_ADDR_STRLEN
];
5710 /* We are interested in MACs only on ports or (port, VLAN) that
5713 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5716 if (!zvni
->vxlan_if
) {
5718 "VNI %u hash %p doesn't have intf upon local MAC DEL",
5723 if (IS_ZEBRA_DEBUG_VXLAN
)
5724 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
5725 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5726 ifp
->ifindex
, vid
, zvni
->vni
);
5728 /* If entry doesn't exist, nothing to do. */
5729 mac
= zvni_mac_lookup(zvni
, macaddr
);
5733 /* Is it a local entry? */
5734 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5737 /* Update all the neigh entries associated with this mac */
5738 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
5740 /* Remove MAC from BGP. */
5741 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5744 * If there are no neigh associated with the mac delete the mac
5745 * else mark it as AUTO for forward reference
5747 if (!listcount(mac
->neigh_list
)) {
5748 zvni_mac_del(zvni
, mac
);
5750 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5751 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5758 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
5760 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
5761 struct interface
*br_if
,
5762 struct ethaddr
*macaddr
, vlanid_t vid
,
5767 char buf
[ETHER_ADDR_STRLEN
];
5768 bool mac_sticky
= false;
5769 bool inform_client
= false;
5770 bool upd_neigh
= false;
5772 /* We are interested in MACs only on ports or (port, VLAN) that
5775 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5777 if (IS_ZEBRA_DEBUG_VXLAN
)
5779 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5780 sticky
? "sticky " : "",
5781 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5782 ifp
->name
, ifp
->ifindex
, vid
);
5786 if (!zvni
->vxlan_if
) {
5788 "VNI %u hash %p doesn't have intf upon local MAC ADD",
5793 /* Check if we need to create or update or it is a NO-OP. */
5794 mac
= zvni_mac_lookup(zvni
, macaddr
);
5796 if (IS_ZEBRA_DEBUG_VXLAN
)
5798 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
5799 sticky
? "sticky " : "",
5800 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5801 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
5803 mac
= zvni_mac_add(zvni
, macaddr
);
5806 EC_ZEBRA_MAC_ADD_FAILED
,
5807 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
5808 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5809 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
5812 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5813 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
5814 mac
->fwd_info
.local
.vid
= vid
;
5816 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5817 inform_client
= true;
5820 if (IS_ZEBRA_DEBUG_VXLAN
)
5822 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
5823 sticky
? "sticky " : "",
5824 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5825 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
5828 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5829 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
5833 * Update any changes and if changes are relevant to
5836 if (mac_sticky
== sticky
5837 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
5838 && mac
->fwd_info
.local
.vid
== vid
) {
5839 if (IS_ZEBRA_DEBUG_VXLAN
)
5841 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
5842 "entry exists and has not changed ",
5843 sticky
? "sticky " : "",
5844 prefix_mac2str(macaddr
, buf
,
5846 ifp
->name
, ifp
->ifindex
, vid
,
5850 if (mac_sticky
!= sticky
) {
5852 SET_FLAG(mac
->flags
,
5855 UNSET_FLAG(mac
->flags
,
5857 inform_client
= true;
5860 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5861 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
5862 mac
->fwd_info
.local
.vid
= vid
;
5864 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
5865 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
5868 * MAC has either moved or was "internally" created due
5869 * to a neighbor learn and is now actually learnt. If
5870 * it was learnt as a remote sticky MAC, this is an
5873 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
5875 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
5876 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
5877 prefix_mac2str(macaddr
, buf
,
5879 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
5884 /* If an actual move, compute MAC's seq number */
5885 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
5886 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
5888 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5889 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5890 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5891 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5892 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
5893 mac
->fwd_info
.local
.vid
= vid
;
5895 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5897 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5899 * We have to inform BGP of this MAC as well as process
5902 inform_client
= true;
5907 /* Inform BGP if required. */
5908 if (inform_client
) {
5909 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
5910 mac
->flags
, mac
->loc_seq
))
5914 /* Process all neighbors associated with this MAC, if required. */
5916 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
5922 * Handle message from client to delete a remote VTEP for a VNI.
5924 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
5927 unsigned short l
= 0;
5929 struct in_addr vtep_ip
;
5931 zebra_vtep_t
*zvtep
;
5932 struct interface
*ifp
;
5933 struct zebra_if
*zif
;
5935 if (!is_evpn_enabled()) {
5937 "%s: EVPN is not enabled yet we have received a vtep del command",
5938 __PRETTY_FUNCTION__
);
5942 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5943 zlog_debug("Recv MACIP DEL for non-default VRF %u",
5950 while (l
< hdr
->length
) {
5951 /* Obtain each remote VTEP and process. */
5952 STREAM_GETL(s
, vni
);
5954 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5955 l
+= IPV4_MAX_BYTELEN
;
5957 if (IS_ZEBRA_DEBUG_VXLAN
)
5958 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
5959 inet_ntoa(vtep_ip
), vni
,
5960 zebra_route_string(client
->proto
));
5962 /* Locate VNI hash entry - expected to exist. */
5963 zvni
= zvni_lookup(vni
);
5965 if (IS_ZEBRA_DEBUG_VXLAN
)
5967 "Failed to locate VNI hash upon remote VTEP DEL, "
5973 ifp
= zvni
->vxlan_if
;
5976 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
5982 /* If down or not mapped to a bridge, we're done. */
5983 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5986 /* If the remote VTEP does not exist, there's nothing more to
5988 * Otherwise, uninstall any remote MACs pointing to this VTEP
5990 * then, the VTEP entry itself and remove it.
5992 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5996 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
5997 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
5998 zvni_vtep_uninstall(zvni
, &vtep_ip
);
5999 zvni_vtep_del(zvni
, zvtep
);
6007 * Handle message from client to add a remote VTEP for a VNI.
6009 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
6012 unsigned short l
= 0;
6014 struct in_addr vtep_ip
;
6016 struct interface
*ifp
;
6017 struct zebra_if
*zif
;
6019 if (!is_evpn_enabled()) {
6021 "%s: EVPN not enabled yet we received a vtep_add zapi call",
6022 __PRETTY_FUNCTION__
);
6026 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6027 zlog_debug("Recv MACIP ADD for non-default VRF %u",
6034 while (l
< hdr
->length
) {
6035 /* Obtain each remote VTEP and process. */
6036 STREAM_GETL(s
, vni
);
6038 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
6039 l
+= IPV4_MAX_BYTELEN
;
6041 if (IS_ZEBRA_DEBUG_VXLAN
)
6042 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
6043 inet_ntoa(vtep_ip
), vni
,
6044 zebra_route_string(client
->proto
));
6046 /* Locate VNI hash entry - expected to exist. */
6047 zvni
= zvni_lookup(vni
);
6050 EC_ZEBRA_VTEP_ADD_FAILED
,
6051 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
6056 ifp
= zvni
->vxlan_if
;
6059 EC_ZEBRA_VTEP_ADD_FAILED
,
6060 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
6067 /* If down or not mapped to a bridge, we're done. */
6068 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6071 /* If the remote VTEP already exists,
6072 there's nothing more to do. */
6073 if (zvni_vtep_find(zvni
, &vtep_ip
))
6076 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
6077 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
6078 "Failed to add remote VTEP, VNI %u zvni %p",
6083 zvni_vtep_install(zvni
, &vtep_ip
);
6091 * Add/Del gateway macip to evpn
6093 * 1. SVI interface on a vlan aware bridge
6094 * 2. SVI interface on a vlan unaware bridge
6095 * 3. vrr interface (MACVLAN) associated to a SVI
6096 * We advertise macip routes for an interface if it is associated to VxLan vlan
6098 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
6102 struct ethaddr macaddr
;
6103 zebra_vni_t
*zvni
= NULL
;
6105 memset(&ip
, 0, sizeof(struct ipaddr
));
6106 memset(&macaddr
, 0, sizeof(struct ethaddr
));
6108 /* Check if EVPN is enabled. */
6109 if (!is_evpn_enabled())
6112 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
6113 struct interface
*svi_if
=
6114 NULL
; /* SVI corresponding to the MACVLAN */
6115 struct zebra_if
*ifp_zif
=
6116 NULL
; /* Zebra daemon specific info for MACVLAN */
6117 struct zebra_if
*svi_if_zif
=
6118 NULL
; /* Zebra daemon specific info for SVI*/
6120 ifp_zif
= ifp
->info
;
6125 * for a MACVLAN interface the link represents the svi_if
6127 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
6128 ifp_zif
->link_ifindex
);
6130 zlog_debug("MACVLAN %s(%u) without link information",
6131 ifp
->name
, ifp
->ifindex
);
6135 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
6137 * If it is a vlan aware bridge then the link gives the
6138 * bridge information
6140 struct interface
*svi_if_link
= NULL
;
6142 svi_if_zif
= svi_if
->info
;
6144 svi_if_link
= if_lookup_by_index_per_ns(
6145 zebra_ns_lookup(NS_DEFAULT
),
6146 svi_if_zif
->link_ifindex
);
6147 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
6149 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
6151 * If it is a vlan unaware bridge then svi is the bridge
6154 zvni
= zvni_from_svi(svi_if
, svi_if
);
6156 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
6157 struct zebra_if
*svi_if_zif
=
6158 NULL
; /* Zebra daemon specific info for SVI */
6159 struct interface
*svi_if_link
=
6160 NULL
; /* link info for the SVI = bridge info */
6162 svi_if_zif
= ifp
->info
;
6164 svi_if_link
= if_lookup_by_index_per_ns(
6165 zebra_ns_lookup(NS_DEFAULT
),
6166 svi_if_zif
->link_ifindex
);
6168 zvni
= zvni_from_svi(ifp
, svi_if_link
);
6170 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
6171 zvni
= zvni_from_svi(ifp
, ifp
);
6177 if (!zvni
->vxlan_if
) {
6178 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
6184 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
6186 if (p
->family
== AF_INET
) {
6187 ip
.ipa_type
= IPADDR_V4
;
6188 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
6189 sizeof(struct in_addr
));
6190 } else if (p
->family
== AF_INET6
) {
6191 ip
.ipa_type
= IPADDR_V6
;
6192 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
6193 sizeof(struct in6_addr
));
6198 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
6200 zvni_gw_macip_del(ifp
, zvni
, &ip
);
6206 * Handle SVI interface going down.
6207 * SVI can be associated to either L3-VNI or L2-VNI.
6208 * For L2-VNI: At this point, this is a NOP since
6209 * the kernel deletes the neighbor entries on this SVI (if any).
6210 * We only need to update the vrf corresponding to zvni.
6211 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
6214 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
6216 zebra_l3vni_t
*zl3vni
= NULL
;
6218 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6221 /* process l3-vni down */
6222 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6224 /* remove association with svi-if */
6225 zl3vni
->svi_if
= NULL
;
6227 zebra_vni_t
*zvni
= NULL
;
6229 /* since we dont have svi corresponding to zvni, we associate it
6230 * to default vrf. Note: the corresponding neigh entries on the
6231 * SVI would have already been deleted */
6232 zvni
= zvni_from_svi(ifp
, link_if
);
6234 zvni
->vrf_id
= VRF_DEFAULT
;
6236 /* update the tenant vrf in BGP */
6237 zvni_send_add_to_client(zvni
);
6244 * Handle SVI interface coming up.
6245 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
6247 * For L2-VNI: we need to install any remote neighbors entried (used for
6249 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
6251 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
6253 zebra_vni_t
*zvni
= NULL
;
6254 zebra_l3vni_t
*zl3vni
= NULL
;
6256 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6259 /* associate with svi */
6260 zl3vni
->svi_if
= ifp
;
6262 /* process oper-up */
6263 if (is_l3vni_oper_up(zl3vni
))
6264 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6267 /* process SVI up for l2-vni */
6268 struct neigh_walk_ctx n_wctx
;
6270 zvni
= zvni_from_svi(ifp
, link_if
);
6274 if (!zvni
->vxlan_if
) {
6276 "VNI %u hash %p doesn't have intf upon SVI up",
6281 if (IS_ZEBRA_DEBUG_VXLAN
)
6283 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
6284 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
6285 vrf_id_to_name(ifp
->vrf_id
));
6287 /* update the vrf information for l2-vni and inform bgp */
6288 zvni
->vrf_id
= ifp
->vrf_id
;
6289 zvni_send_add_to_client(zvni
);
6291 /* Install any remote neighbors for this VNI. */
6292 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6294 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6302 * Handle VxLAN interface down
6304 int zebra_vxlan_if_down(struct interface
*ifp
)
6307 struct zebra_if
*zif
= NULL
;
6308 struct zebra_l2info_vxlan
*vxl
= NULL
;
6309 zebra_l3vni_t
*zl3vni
= NULL
;
6312 /* Check if EVPN is enabled. */
6313 if (!is_evpn_enabled())
6318 vxl
= &zif
->l2info
.vxl
;
6321 zl3vni
= zl3vni_lookup(vni
);
6323 /* process-if-down for l3-vni */
6324 if (IS_ZEBRA_DEBUG_VXLAN
)
6325 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
6328 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6330 /* process if-down for l2-vni */
6331 if (IS_ZEBRA_DEBUG_VXLAN
)
6332 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
6335 /* Locate hash entry; it is expected to exist. */
6336 zvni
= zvni_lookup(vni
);
6339 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
6340 ifp
->name
, ifp
->ifindex
, vni
);
6344 assert(zvni
->vxlan_if
== ifp
);
6346 /* Delete this VNI from BGP. */
6347 zvni_send_del_to_client(zvni
->vni
);
6349 /* Free up all neighbors and MACs, if any. */
6350 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6351 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6353 /* Free up all remote VTEPs, if any. */
6354 zvni_vtep_del_all(zvni
, 1);
6360 * Handle VxLAN interface up - update BGP if required.
6362 int zebra_vxlan_if_up(struct interface
*ifp
)
6365 struct zebra_if
*zif
= NULL
;
6366 struct zebra_l2info_vxlan
*vxl
= NULL
;
6367 zebra_vni_t
*zvni
= NULL
;
6368 zebra_l3vni_t
*zl3vni
= NULL
;
6370 /* Check if EVPN is enabled. */
6371 if (!is_evpn_enabled())
6376 vxl
= &zif
->l2info
.vxl
;
6379 zl3vni
= zl3vni_lookup(vni
);
6382 if (IS_ZEBRA_DEBUG_VXLAN
)
6383 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
6386 /* we need to associate with SVI, if any, we can associate with
6387 * svi-if only after association with vxlan-intf is complete
6389 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6391 if (is_l3vni_oper_up(zl3vni
))
6392 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6394 /* Handle L2-VNI add */
6395 struct interface
*vlan_if
= NULL
;
6397 if (IS_ZEBRA_DEBUG_VXLAN
)
6398 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
6401 /* Locate hash entry; it is expected to exist. */
6402 zvni
= zvni_lookup(vni
);
6405 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
6406 ifp
->name
, ifp
->ifindex
, vni
);
6410 assert(zvni
->vxlan_if
== ifp
);
6411 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6412 zif
->brslave_info
.br_if
);
6414 zvni
->vrf_id
= vlan_if
->vrf_id
;
6415 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6417 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6420 /* If part of a bridge, inform BGP about this VNI. */
6421 /* Also, read and populate local MACs and neighbors. */
6422 if (zif
->brslave_info
.br_if
) {
6423 zvni_send_add_to_client(zvni
);
6424 zvni_read_mac_neigh(zvni
, ifp
);
6432 * Handle VxLAN interface delete. Locate and remove entry in hash table
6433 * and update BGP, if required.
6435 int zebra_vxlan_if_del(struct interface
*ifp
)
6438 struct zebra_if
*zif
= NULL
;
6439 struct zebra_l2info_vxlan
*vxl
= NULL
;
6440 zebra_vni_t
*zvni
= NULL
;
6441 zebra_l3vni_t
*zl3vni
= NULL
;
6443 /* Check if EVPN is enabled. */
6444 if (!is_evpn_enabled())
6449 vxl
= &zif
->l2info
.vxl
;
6452 zl3vni
= zl3vni_lookup(vni
);
6455 if (IS_ZEBRA_DEBUG_VXLAN
)
6456 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
6459 /* process oper-down for l3-vni */
6460 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6462 /* remove the association with vxlan_if */
6463 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
6464 zl3vni
->vxlan_if
= NULL
;
6467 /* process if-del for l2-vni*/
6468 if (IS_ZEBRA_DEBUG_VXLAN
)
6469 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
6472 /* Locate hash entry; it is expected to exist. */
6473 zvni
= zvni_lookup(vni
);
6476 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6477 ifp
->name
, ifp
->ifindex
, vni
);
6481 /* remove from l3-vni list */
6482 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
6484 listnode_delete(zl3vni
->l2vnis
, zvni
);
6486 /* Delete VNI from BGP. */
6487 zvni_send_del_to_client(zvni
->vni
);
6489 /* Free up all neighbors and MAC, if any. */
6490 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
6491 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
6493 /* Free up all remote VTEPs, if any. */
6494 zvni_vtep_del_all(zvni
, 0);
6496 /* Delete the hash entry. */
6497 if (zvni_del(zvni
)) {
6498 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
6499 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
6500 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
6508 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6510 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
6513 struct zebra_if
*zif
= NULL
;
6514 struct zebra_l2info_vxlan
*vxl
= NULL
;
6515 zebra_vni_t
*zvni
= NULL
;
6516 zebra_l3vni_t
*zl3vni
= NULL
;
6518 /* Check if EVPN is enabled. */
6519 if (!is_evpn_enabled())
6524 vxl
= &zif
->l2info
.vxl
;
6527 zl3vni
= zl3vni_lookup(vni
);
6530 if (IS_ZEBRA_DEBUG_VXLAN
)
6532 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6533 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6534 inet_ntoa(vxl
->vtep_ip
),
6535 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6537 /* Removed from bridge? Cleanup and return */
6538 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6539 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6540 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6544 /* access-vlan change - process oper down, associate with new
6545 * svi_if and then process oper up again
6547 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6548 if (if_is_operative(ifp
)) {
6549 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6550 zl3vni
->svi_if
= NULL
;
6551 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6552 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6553 if (is_l3vni_oper_up(zl3vni
))
6554 zebra_vxlan_process_l3vni_oper_up(
6560 * local-ip change - process oper down, associate with new
6561 * local-ip and then process oper up again
6563 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
6564 if (if_is_operative(ifp
)) {
6565 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6566 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6567 if (is_l3vni_oper_up(zl3vni
))
6568 zebra_vxlan_process_l3vni_oper_up(
6573 /* Update local tunnel IP. */
6574 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6576 /* if we have a valid new master, process l3-vni oper up */
6577 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
6578 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
6579 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6583 /* Update VNI hash. */
6584 zvni
= zvni_lookup(vni
);
6587 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6588 ifp
->name
, ifp
->ifindex
, vni
);
6592 if (IS_ZEBRA_DEBUG_VXLAN
)
6594 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6595 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6596 inet_ntoa(vxl
->vtep_ip
),
6597 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6599 /* Removed from bridge? Cleanup and return */
6600 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6601 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6602 /* Delete from client, remove all remote VTEPs */
6603 /* Also, free up all MACs and neighbors. */
6604 zvni_send_del_to_client(zvni
->vni
);
6605 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6606 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6607 zvni_vtep_del_all(zvni
, 1);
6611 /* Handle other changes. */
6612 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6613 /* Remove all existing local neigh and MACs for this VNI
6614 * (including from BGP)
6616 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6617 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6620 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6621 zvni
->vxlan_if
= ifp
;
6623 /* Take further actions needed.
6624 * Note that if we are here, there is a change of interest.
6626 /* If down or not mapped to a bridge, we're done. */
6627 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6630 /* Inform BGP, if there is a change of interest. */
6632 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
6633 zvni_send_add_to_client(zvni
);
6635 /* If there is a valid new master or a VLAN mapping change,
6636 * read and populate local MACs and neighbors.
6637 * Also, reinstall any remote MACs and neighbors
6638 * for this VNI (based on new VLAN).
6640 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6641 zvni_read_mac_neigh(zvni
, ifp
);
6642 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6643 struct mac_walk_ctx m_wctx
;
6644 struct neigh_walk_ctx n_wctx
;
6646 zvni_read_mac_neigh(zvni
, ifp
);
6648 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6650 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
6653 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6655 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6664 * Handle VxLAN interface add.
6666 int zebra_vxlan_if_add(struct interface
*ifp
)
6669 struct zebra_if
*zif
= NULL
;
6670 struct zebra_l2info_vxlan
*vxl
= NULL
;
6671 zebra_vni_t
*zvni
= NULL
;
6672 zebra_l3vni_t
*zl3vni
= NULL
;
6674 /* Check if EVPN is enabled. */
6675 if (!is_evpn_enabled())
6680 vxl
= &zif
->l2info
.vxl
;
6683 zl3vni
= zl3vni_lookup(vni
);
6686 /* process if-add for l3-vni*/
6687 if (IS_ZEBRA_DEBUG_VXLAN
)
6689 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6690 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6691 inet_ntoa(vxl
->vtep_ip
),
6692 zif
->brslave_info
.bridge_ifindex
);
6694 /* associate with vxlan_if */
6695 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6696 zl3vni
->vxlan_if
= ifp
;
6698 /* Associate with SVI, if any. We can associate with svi-if only
6699 * after association with vxlan_if is complete */
6700 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6702 if (is_l3vni_oper_up(zl3vni
))
6703 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6706 /* process if-add for l2-vni */
6707 struct interface
*vlan_if
= NULL
;
6709 /* Create or update VNI hash. */
6710 zvni
= zvni_lookup(vni
);
6712 zvni
= zvni_add(vni
);
6715 EC_ZEBRA_VNI_ADD_FAILED
,
6716 "Failed to add VNI hash, IF %s(%u) VNI %u",
6717 ifp
->name
, ifp
->ifindex
, vni
);
6722 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6723 zvni
->vxlan_if
= ifp
;
6724 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6725 zif
->brslave_info
.br_if
);
6727 zvni
->vrf_id
= vlan_if
->vrf_id
;
6728 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6730 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6733 if (IS_ZEBRA_DEBUG_VXLAN
)
6735 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6737 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
6739 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6740 inet_ntoa(vxl
->vtep_ip
),
6741 zif
->brslave_info
.bridge_ifindex
);
6743 /* If down or not mapped to a bridge, we're done. */
6744 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6748 zvni_send_add_to_client(zvni
);
6750 /* Read and populate local MACs and neighbors */
6751 zvni_read_mac_neigh(zvni
, ifp
);
6757 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
6758 char *err
, int err_str_sz
, int filter
,
6761 zebra_l3vni_t
*zl3vni
= NULL
;
6762 struct zebra_vrf
*zvrf_default
= NULL
;
6764 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
6768 if (IS_ZEBRA_DEBUG_VXLAN
)
6769 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
6770 add
? "ADD" : "DEL");
6774 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6776 /* check if the vni is already present under zvrf */
6778 snprintf(err
, err_str_sz
,
6779 "VNI is already configured under the vrf");
6783 /* check if this VNI is already present in the system */
6784 zl3vni
= zl3vni_lookup(vni
);
6786 snprintf(err
, err_str_sz
,
6787 "VNI is already configured as L3-VNI");
6791 /* add the L3-VNI to the global table */
6792 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
6794 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
6798 /* associate the vrf with vni */
6801 /* set the filter in l3vni to denote if we are using l3vni only
6805 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
6807 /* associate with vxlan-intf;
6808 * we need to associate with the vxlan-intf first
6810 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
6812 /* associate with corresponding SVI interface, we can associate
6813 * with svi-if only after vxlan interface association is
6816 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6818 /* formulate l2vni list */
6819 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
6822 if (is_l3vni_oper_up(zl3vni
))
6823 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6826 zl3vni
= zl3vni_lookup(vni
);
6828 snprintf(err
, err_str_sz
, "VNI doesn't exist");
6832 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
6833 snprintf(err
, ERR_STR_SZ
,
6834 "prefix-routes-only is not set for the vni");
6838 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6840 /* delete and uninstall all rmacs */
6841 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
6844 /* delete and uninstall all next-hops */
6845 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
6851 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6856 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
6858 zebra_l3vni_t
*zl3vni
= NULL
;
6861 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6865 zl3vni
->vrf_id
= zvrf_id(zvrf
);
6866 if (is_l3vni_oper_up(zl3vni
))
6867 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6871 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
6873 zebra_l3vni_t
*zl3vni
= NULL
;
6876 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6880 zl3vni
->vrf_id
= VRF_UNKNOWN
;
6881 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6885 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
6887 zebra_l3vni_t
*zl3vni
= NULL
;
6891 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6897 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
6903 * Handle message from client to enable/disable advertisement of g/w macip
6906 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
6911 zebra_vni_t
*zvni
= NULL
;
6912 struct interface
*ifp
= NULL
;
6913 struct zebra_if
*zif
= NULL
;
6914 struct zebra_l2info_vxlan zl2_info
;
6915 struct interface
*vlan_if
= NULL
;
6917 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6918 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
6924 STREAM_GETC(s
, advertise
);
6925 vni
= stream_get3(s
);
6927 zvni
= zvni_lookup(vni
);
6931 if (zvni
->advertise_subnet
== advertise
)
6934 if (IS_ZEBRA_DEBUG_VXLAN
)
6935 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
6936 advertise
? "enabled" : "disabled", vni
,
6937 zvni
->advertise_subnet
? "enabled" : "disabled");
6940 zvni
->advertise_subnet
= advertise
;
6942 ifp
= zvni
->vxlan_if
;
6948 /* If down or not mapped to a bridge, we're done. */
6949 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6952 zl2_info
= zif
->l2info
.vxl
;
6955 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
6959 if (zvni
->advertise_subnet
)
6960 zvni_advertise_subnet(zvni
, vlan_if
, 1);
6962 zvni_advertise_subnet(zvni
, vlan_if
, 0);
6969 * Handle message from client to enable/disable advertisement of g/w macip
6972 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
6977 zebra_vni_t
*zvni
= NULL
;
6978 struct interface
*ifp
= NULL
;
6980 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6981 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
6987 STREAM_GETC(s
, advertise
);
6988 STREAM_GETL(s
, vni
);
6991 if (IS_ZEBRA_DEBUG_VXLAN
)
6992 zlog_debug("EVPN gateway macip Adv %s, currently %s",
6993 advertise
? "enabled" : "disabled",
6994 advertise_gw_macip_enabled(NULL
)
6998 if (zvrf
->advertise_gw_macip
== advertise
)
7001 zvrf
->advertise_gw_macip
= advertise
;
7003 if (advertise_gw_macip_enabled(zvni
))
7004 hash_iterate(zvrf
->vni_table
,
7005 zvni_gw_macip_add_for_vni_hash
, NULL
);
7007 hash_iterate(zvrf
->vni_table
,
7008 zvni_gw_macip_del_for_vni_hash
, NULL
);
7011 struct zebra_if
*zif
= NULL
;
7012 struct zebra_l2info_vxlan zl2_info
;
7013 struct interface
*vlan_if
= NULL
;
7014 struct interface
*vrr_if
= NULL
;
7016 zvni
= zvni_lookup(vni
);
7020 if (IS_ZEBRA_DEBUG_VXLAN
)
7022 "EVPN gateway macip Adv %s on VNI %d , currently %s",
7023 advertise
? "enabled" : "disabled", vni
,
7024 advertise_gw_macip_enabled(zvni
) ? "enabled"
7027 if (zvni
->advertise_gw_macip
== advertise
)
7030 zvni
->advertise_gw_macip
= advertise
;
7032 ifp
= zvni
->vxlan_if
;
7038 /* If down or not mapped to a bridge, we're done. */
7039 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7042 zl2_info
= zif
->l2info
.vxl
;
7044 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
7045 zif
->brslave_info
.br_if
);
7049 if (advertise_gw_macip_enabled(zvni
)) {
7050 /* Add primary SVI MAC-IP */
7051 zvni_add_macip_for_intf(vlan_if
, zvni
);
7053 /* Add VRR MAC-IP - if any*/
7054 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
7056 zvni_add_macip_for_intf(vrr_if
, zvni
);
7058 /* Del primary MAC-IP */
7059 zvni_del_macip_for_intf(vlan_if
, zvni
);
7061 /* Del VRR MAC-IP - if any*/
7062 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
7064 zvni_del_macip_for_intf(vrr_if
, zvni
);
7074 * Handle message from client to learn (or stop learning) about VNIs and MACs.
7075 * When enabled, the VNI hash table will be built and MAC FDB table read;
7076 * when disabled, the entries should be deleted and remote VTEPs and MACs
7077 * uninstalled from the kernel.
7079 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
7081 struct stream
*s
= NULL
;
7083 struct zebra_ns
*zns
= NULL
;
7085 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7086 zlog_debug("EVPN VNI Adv for non-default VRF %u",
7092 STREAM_GETC(s
, advertise
);
7094 if (IS_ZEBRA_DEBUG_VXLAN
)
7095 zlog_debug("EVPN VNI Adv %s, currently %s",
7096 advertise
? "enabled" : "disabled",
7097 is_evpn_enabled() ? "enabled" : "disabled");
7099 if (zvrf
->advertise_all_vni
== advertise
)
7102 zvrf
->advertise_all_vni
= advertise
;
7103 if (is_evpn_enabled()) {
7104 /* Build VNI hash table and inform BGP. */
7105 zvni_build_hash_table();
7107 /* Add all SVI (L3 GW) MACs to BGP*/
7108 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
7111 /* Read the MAC FDB */
7112 macfdb_read(zvrf
->zns
);
7114 /* Read neighbors */
7115 neigh_read(zvrf
->zns
);
7117 /* Cleanup VTEPs for all VNIs - uninstall from
7118 * kernel and free entries.
7120 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
7122 /* cleanup all l3vnis */
7123 zns
= zebra_ns_lookup(NS_DEFAULT
);
7127 hash_iterate(zns
->l3vni_table
, zl3vni_cleanup_all
, NULL
);
7135 * Allocate VNI hash table for this VRF and do other initialization.
7136 * NOTE: Currently supported only for default VRF.
7138 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
7142 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
7143 "Zebra VRF VNI Table");
7146 /* Cleanup VNI info, but don't free the table. */
7147 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
7151 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
7154 /* Close all VNI handling */
7155 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
7159 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
7160 hash_free(zvrf
->vni_table
);
7163 /* init the l3vni table */
7164 void zebra_vxlan_ns_init(struct zebra_ns
*zns
)
7166 zns
->l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
7167 "Zebra VRF L3 VNI table");
7170 /* free l3vni table */
7171 void zebra_vxlan_ns_disable(struct zebra_ns
*zns
)
7173 hash_free(zns
->l3vni_table
);
7176 /* get the l3vni svi ifindex */
7177 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
7179 zebra_l3vni_t
*zl3vni
= NULL
;
7181 zl3vni
= zl3vni_from_vrf(vrf_id
);
7182 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
7185 return zl3vni
->svi_if
->ifindex
;