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/zebra_router.h"
41 #include "zebra/debug.h"
42 #include "zebra/interface.h"
43 #include "zebra/rib.h"
45 #include "zebra/rt_netlink.h"
46 #include "zebra/zebra_errors.h"
47 #include "zebra/zebra_l2.h"
48 #include "zebra/zebra_memory.h"
49 #include "zebra/zebra_ns.h"
50 #include "zebra/zebra_vrf.h"
51 #include "zebra/zebra_vxlan.h"
52 #include "zebra/zebra_vxlan_private.h"
53 #include "zebra/zserv.h"
55 DEFINE_MTYPE_STATIC(ZEBRA
, HOST_PREFIX
, "host prefix");
56 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI
, "VNI hash");
57 DEFINE_MTYPE_STATIC(ZEBRA
, ZL3VNI
, "L3 VNI hash");
58 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI_VTEP
, "VNI remote VTEP");
59 DEFINE_MTYPE_STATIC(ZEBRA
, MAC
, "VNI MAC");
60 DEFINE_MTYPE_STATIC(ZEBRA
, NEIGH
, "VNI Neighbor");
64 /* static function declarations */
65 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
67 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
68 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
);
69 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
71 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
73 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
75 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
);
76 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
);
77 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
);
78 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
79 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[]);
81 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
82 struct ipaddr
*ip
, uint8_t flags
,
83 uint32_t seq
, uint16_t cmd
);
84 static unsigned int neigh_hash_keymake(void *p
);
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 bool 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
);
152 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
153 struct interface
*br_if
, vlanid_t vid
);
154 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
155 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
156 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
);
158 static unsigned int vni_hash_keymake(void *p
);
159 static void *zvni_alloc(void *p
);
160 static zebra_vni_t
*zvni_lookup(vni_t vni
);
161 static zebra_vni_t
*zvni_add(vni_t vni
);
162 static int zvni_del(zebra_vni_t
*zvni
);
163 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
164 static int zvni_send_del_to_client(vni_t vni
);
165 static void zvni_build_hash_table();
166 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
167 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
168 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
169 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
170 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
171 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
172 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
173 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
174 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
175 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
176 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
177 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
179 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
180 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
181 static int remote_neigh_count(zebra_mac_t
*zmac
);
182 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
184 /* Private functions */
185 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
186 const struct host_rb_entry
*hle2
)
188 if (hle1
->p
.family
< hle2
->p
.family
)
191 if (hle1
->p
.family
> hle2
->p
.family
)
194 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
197 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
200 if (hle1
->p
.family
== AF_INET
) {
201 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
204 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
208 } else if (hle1
->p
.family
== AF_INET6
) {
209 return memcmp(&hle1
->p
.u
.prefix6
, &hle2
->p
.u
.prefix6
,
212 zlog_debug("%s: Unexpected family type: %d",
213 __PRETTY_FUNCTION__
, hle1
->p
.family
);
217 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
219 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
221 struct host_rb_entry
*hle
;
224 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
231 * Return number of valid MACs in a VNI's MAC hash table - all
232 * remote MACs and non-internal (auto) local MACs count.
234 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
237 uint32_t num_macs
= 0;
239 struct hash_backet
*hb
;
242 hash
= zvni
->mac_table
;
245 for (i
= 0; i
< hash
->size
; i
++) {
246 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
247 mac
= (zebra_mac_t
*)hb
->data
;
248 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
249 || CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
250 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
258 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
260 struct zebra_vrf
*zvrf
;
262 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
263 if (zvrf
&& zvrf
->advertise_gw_macip
)
266 if (zvni
&& zvni
->advertise_gw_macip
)
273 * Helper function to determine maximum width of neighbor IP address for
274 * display - just because we're dealing with IPv6 addresses that can
277 static void zvni_find_neigh_addr_width(struct hash_backet
*backet
, void *ctxt
)
280 char buf
[INET6_ADDRSTRLEN
];
281 struct neigh_walk_ctx
*wctx
= ctxt
;
284 n
= (zebra_neigh_t
*)backet
->data
;
286 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
288 if (width
> wctx
->addr_width
)
289 wctx
->addr_width
= width
;
294 * Print a specific neighbor entry.
296 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
299 char buf1
[ETHER_ADDR_STRLEN
];
300 char buf2
[INET6_ADDRSTRLEN
];
301 const char *type_str
;
302 const char *state_str
;
303 bool flags_present
= false;
305 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
306 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
307 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
309 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
310 vty
= (struct vty
*)ctxt
;
312 vty_out(vty
, "IP: %s\n",
313 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
314 vty_out(vty
, " Type: %s\n", type_str
);
315 vty_out(vty
, " State: %s\n", state_str
);
316 vty_out(vty
, " MAC: %s\n",
317 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
319 json_object_string_add(json
, "ip", buf2
);
320 json_object_string_add(json
, "type", type_str
);
321 json_object_string_add(json
, "state", state_str
);
322 json_object_string_add(json
, "mac", buf1
);
324 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
326 vty_out(vty
, " Remote VTEP: %s\n",
327 inet_ntoa(n
->r_vtep_ip
));
329 json_object_string_add(json
, "remoteVtep",
330 inet_ntoa(n
->r_vtep_ip
));
332 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
334 vty_out(vty
, " Flags: Default-gateway");
335 flags_present
= true;
337 json_object_boolean_true_add(json
, "defaultGateway");
339 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
342 flags_present
? " ,Router" : " Flags: Router");
343 flags_present
= true;
349 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
350 n
->loc_seq
, n
->rem_seq
);
352 json_object_int_add(json
, "localSequence", n
->loc_seq
);
353 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
358 * Print neighbor hash entry - called for display of all neighbors.
360 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
363 json_object
*json_vni
= NULL
, *json_row
= NULL
;
365 char buf1
[ETHER_ADDR_STRLEN
];
366 char buf2
[INET6_ADDRSTRLEN
];
367 struct neigh_walk_ctx
*wctx
= ctxt
;
368 const char *state_str
;
371 json_vni
= wctx
->json
;
372 n
= (zebra_neigh_t
*)backet
->data
;
375 json_row
= json_object_new_object();
377 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
378 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
379 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
380 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
381 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
384 if (json_vni
== NULL
) {
385 vty_out(vty
, "%*s %-6s %-8s %-17s\n",
386 -wctx
->addr_width
, buf2
, "local",
389 json_object_string_add(json_row
, "type", "local");
390 json_object_string_add(json_row
, "state", state_str
);
391 json_object_string_add(json_row
, "mac", buf1
);
392 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
393 json_object_boolean_true_add(
394 json_row
, "defaultGateway");
395 json_object_int_add(json_row
, "localSequence",
397 json_object_int_add(json_row
, "remoteSequence",
401 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
402 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
403 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
406 if (json_vni
== NULL
) {
407 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
410 "%*s %-6s %-8s %-17s %-21s\n",
411 -wctx
->addr_width
, "Neighbor", "Type",
412 "State", "MAC", "Remote VTEP");
413 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
414 -wctx
->addr_width
, buf2
, "remote", state_str
,
415 buf1
, inet_ntoa(n
->r_vtep_ip
));
417 json_object_string_add(json_row
, "type", "remote");
418 json_object_string_add(json_row
, "state", state_str
);
419 json_object_string_add(json_row
, "mac", buf1
);
420 json_object_string_add(json_row
, "remoteVtep",
421 inet_ntoa(n
->r_vtep_ip
));
422 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
423 json_object_boolean_true_add(json_row
,
425 json_object_int_add(json_row
, "localSequence",
427 json_object_int_add(json_row
, "remoteSequence",
434 json_object_object_add(json_vni
, buf2
, json_row
);
438 * Print neighbors for all VNI.
440 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
444 json_object
*json
= NULL
, *json_vni
= NULL
;
447 struct neigh_walk_ctx wctx
;
448 char vni_str
[VNI_STR_LEN
];
450 vty
= (struct vty
*)args
[0];
451 json
= (json_object
*)args
[1];
453 zvni
= (zebra_vni_t
*)backet
->data
;
455 num_neigh
= hashcount(zvni
->neigh_table
);
458 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
459 zvni
->vni
, num_neigh
);
461 json_vni
= json_object_new_object();
462 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
463 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
467 json_object_object_add(json
, vni_str
, json_vni
);
471 /* Since we have IPv6 addresses to deal with which can vary widely in
472 * size, we try to be a bit more elegant in display by first computing
475 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
478 wctx
.addr_width
= 15;
479 wctx
.json
= json_vni
;
480 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
483 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
484 -wctx
.addr_width
, "IP", "Type",
485 "State", "MAC", "Remote VTEP");
487 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
490 json_object_object_add(json
, vni_str
, json_vni
);
493 /* print a specific next hop for an l3vni */
494 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
497 char buf1
[ETHER_ADDR_STRLEN
];
498 char buf2
[INET6_ADDRSTRLEN
];
499 json_object
*json_hosts
= NULL
;
500 struct host_rb_entry
*hle
;
503 vty_out(vty
, "Ip: %s\n",
504 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
505 vty_out(vty
, " RMAC: %s\n",
506 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
507 vty_out(vty
, " Refcount: %d\n",
508 rb_host_count(&n
->host_rb
));
509 vty_out(vty
, " Prefixes:\n");
510 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
511 vty_out(vty
, " %s\n",
512 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
514 json_hosts
= json_object_new_array();
515 json_object_string_add(
516 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
517 json_object_string_add(
519 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
520 json_object_int_add(json
, "refCount",
521 rb_host_count(&n
->host_rb
));
522 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
523 json_object_array_add(json_hosts
,
524 json_object_new_string(prefix2str(
525 &hle
->p
, buf2
, sizeof(buf2
))));
526 json_object_object_add(json
, "prefixList", json_hosts
);
530 /* Print a specific RMAC entry */
531 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
534 char buf1
[ETHER_ADDR_STRLEN
];
535 char buf2
[PREFIX_STRLEN
];
536 json_object
*json_hosts
= NULL
;
537 struct host_rb_entry
*hle
;
540 vty_out(vty
, "MAC: %s\n",
541 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
542 vty_out(vty
, " Remote VTEP: %s\n",
543 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
544 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
545 vty_out(vty
, " Prefixes:\n");
546 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
547 vty_out(vty
, " %s\n",
548 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
550 json_hosts
= json_object_new_array();
551 json_object_string_add(
553 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
554 json_object_string_add(json
, "vtepIp",
555 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
556 json_object_int_add(json
, "refCount",
557 rb_host_count(&zrmac
->host_rb
));
558 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
559 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
560 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
561 json_object_array_add(
563 json_object_new_string(prefix2str(
564 &hle
->p
, buf2
, sizeof(buf2
))));
565 json_object_object_add(json
, "prefixList", json_hosts
);
570 * Print a specific MAC entry.
572 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
575 zebra_neigh_t
*n
= NULL
;
576 struct listnode
*node
= NULL
;
578 char buf2
[INET6_ADDRSTRLEN
];
580 vty
= (struct vty
*)ctxt
;
581 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
584 json_object
*json_mac
= json_object_new_object();
586 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
587 struct zebra_ns
*zns
;
588 struct interface
*ifp
;
591 ifindex
= mac
->fwd_info
.local
.ifindex
;
592 zns
= zebra_ns_lookup(NS_DEFAULT
);
593 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
596 json_object_string_add(json_mac
, "type", "local");
597 json_object_string_add(json_mac
, "intf", ifp
->name
);
598 json_object_int_add(json_mac
, "ifindex", ifindex
);
599 if (mac
->fwd_info
.local
.vid
)
600 json_object_int_add(json_mac
, "vlan",
601 mac
->fwd_info
.local
.vid
);
602 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
603 json_object_string_add(json_mac
, "type", "remote");
604 json_object_string_add(
605 json_mac
, "remoteVtep",
606 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
607 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
608 json_object_string_add(json_mac
, "type", "auto");
610 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
611 json_object_boolean_true_add(json_mac
, "stickyMac");
613 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
614 json_object_boolean_true_add(json_mac
,
617 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
618 json_object_boolean_true_add(json_mac
,
621 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
622 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
624 /* print all the associated neigh */
625 if (!listcount(mac
->neigh_list
))
626 json_object_string_add(json_mac
, "neighbors", "none");
628 json_object
*json_active_nbrs
= json_object_new_array();
629 json_object
*json_inactive_nbrs
=
630 json_object_new_array();
631 json_object
*json_nbrs
= json_object_new_object();
633 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
634 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
635 json_object_array_add(
637 json_object_new_string(
642 json_object_array_add(
644 json_object_new_string(
650 json_object_object_add(json_nbrs
, "active",
652 json_object_object_add(json_nbrs
, "inactive",
654 json_object_object_add(json_mac
, "neighbors",
658 json_object_object_add(json
, buf1
, json_mac
);
660 json_object_to_json_string_ext(
661 json
, JSON_C_TO_STRING_PRETTY
));
662 json_object_free(json
);
664 vty_out(vty
, "MAC: %s\n", buf1
);
666 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
667 struct zebra_ns
*zns
;
668 struct interface
*ifp
;
671 ifindex
= mac
->fwd_info
.local
.ifindex
;
672 zns
= zebra_ns_lookup(NS_DEFAULT
);
673 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
676 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
677 if (mac
->fwd_info
.local
.vid
)
678 vty_out(vty
, " VLAN: %u",
679 mac
->fwd_info
.local
.vid
);
680 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
681 vty_out(vty
, " Remote VTEP: %s",
682 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
683 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
684 vty_out(vty
, " Auto Mac ");
687 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
688 vty_out(vty
, " Sticky Mac ");
690 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
691 vty_out(vty
, " Default-gateway Mac ");
693 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
694 vty_out(vty
, " Remote-gateway Mac ");
697 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
701 /* print all the associated neigh */
702 vty_out(vty
, " Neighbors:\n");
703 if (!listcount(mac
->neigh_list
))
704 vty_out(vty
, " No Neighbors\n");
706 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
707 vty_out(vty
, " %s %s\n",
708 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
709 (IS_ZEBRA_NEIGH_ACTIVE(n
)
720 * Print MAC hash entry - called for display of all MACs.
722 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
725 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
728 struct mac_walk_ctx
*wctx
= ctxt
;
731 json_mac_hdr
= wctx
->json
;
732 mac
= (zebra_mac_t
*)backet
->data
;
734 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
737 json_mac
= json_object_new_object();
739 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
740 struct zebra_ns
*zns
;
742 struct interface
*ifp
;
745 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
748 zns
= zebra_ns_lookup(NS_DEFAULT
);
749 ifindex
= mac
->fwd_info
.local
.ifindex
;
750 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
751 if (!ifp
) // unexpected
753 vid
= mac
->fwd_info
.local
.vid
;
754 if (json_mac_hdr
== NULL
)
755 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
758 json_object_string_add(json_mac
, "type", "local");
759 json_object_string_add(json_mac
, "intf", ifp
->name
);
762 if (json_mac_hdr
== NULL
)
763 vty_out(vty
, " %-5u", vid
);
765 json_object_int_add(json_mac
, "vlan", vid
);
767 if (json_mac_hdr
== NULL
) {
770 json_object_int_add(json_mac
, "localSequence",
772 json_object_int_add(json_mac
, "remoteSequence",
774 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
779 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
781 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
782 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
786 if (json_mac_hdr
== NULL
) {
787 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
788 (wctx
->count
== 0)) {
789 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
790 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC",
791 "Type", "Intf/Remote VTEP", "VLAN");
793 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
, "remote",
794 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
796 json_object_string_add(json_mac
, "type", "remote");
797 json_object_string_add(json_mac
, "remoteVtep",
798 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
799 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
800 json_object_int_add(json_mac
, "localSequence",
802 json_object_int_add(json_mac
, "remoteSequence",
811 * Print MACs for all VNI.
813 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
816 json_object
*json
= NULL
, *json_vni
= NULL
;
817 json_object
*json_mac
= NULL
;
820 struct mac_walk_ctx
*wctx
= ctxt
;
821 char vni_str
[VNI_STR_LEN
];
823 vty
= (struct vty
*)wctx
->vty
;
824 json
= (struct json_object
*)wctx
->json
;
826 zvni
= (zebra_vni_t
*)backet
->data
;
829 /*We are iterating over a new VNI, set the count to 0*/
832 num_macs
= num_valid_macs(zvni
);
837 json_vni
= json_object_new_object();
838 json_mac
= json_object_new_object();
839 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
842 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
844 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
845 zvni
->vni
, num_macs
);
846 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
847 "Intf/Remote VTEP", "VLAN");
849 json_object_int_add(json_vni
, "numMacs", num_macs
);
851 /* assign per-vni to wctx->json object to fill macs
852 * under the vni. Re-assign primary json object to fill
853 * next vni information.
855 wctx
->json
= json_mac
;
856 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
860 json_object_object_add(json_vni
, "macs", json_mac
);
861 json_object_object_add(json
, vni_str
, json_vni
);
865 static void zl3vni_print_nh_hash(struct hash_backet
*backet
, void *ctx
)
867 struct nh_walk_ctx
*wctx
= NULL
;
868 struct vty
*vty
= NULL
;
869 struct json_object
*json_vni
= NULL
;
870 struct json_object
*json_nh
= NULL
;
871 zebra_neigh_t
*n
= NULL
;
872 char buf1
[ETHER_ADDR_STRLEN
];
873 char buf2
[INET6_ADDRSTRLEN
];
875 wctx
= (struct nh_walk_ctx
*)ctx
;
877 json_vni
= wctx
->json
;
879 json_nh
= json_object_new_object();
880 n
= (zebra_neigh_t
*)backet
->data
;
883 vty_out(vty
, "%-15s %-17s\n",
884 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
885 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
887 json_object_string_add(json_nh
, "nexthopIp",
888 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
889 json_object_string_add(
890 json_nh
, "routerMac",
891 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
892 json_object_object_add(json_vni
,
893 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
898 static void zl3vni_print_nh_hash_all_vni(struct hash_backet
*backet
,
901 struct vty
*vty
= NULL
;
902 json_object
*json
= NULL
;
903 json_object
*json_vni
= NULL
;
904 zebra_l3vni_t
*zl3vni
= NULL
;
906 struct nh_walk_ctx wctx
;
907 char vni_str
[VNI_STR_LEN
];
909 vty
= (struct vty
*)args
[0];
910 json
= (struct json_object
*)args
[1];
912 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
914 num_nh
= hashcount(zl3vni
->nh_table
);
919 json_vni
= json_object_new_object();
920 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
924 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
925 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
927 json_object_int_add(json_vni
, "numNextHops", num_nh
);
929 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
931 wctx
.json
= json_vni
;
932 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
934 json_object_object_add(json
, vni_str
, json_vni
);
937 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet
*backet
,
940 struct vty
*vty
= NULL
;
941 json_object
*json
= NULL
;
942 json_object
*json_vni
= NULL
;
943 zebra_l3vni_t
*zl3vni
= NULL
;
945 struct rmac_walk_ctx wctx
;
946 char vni_str
[VNI_STR_LEN
];
948 vty
= (struct vty
*)args
[0];
949 json
= (struct json_object
*)args
[1];
951 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
953 num_rmacs
= hashcount(zl3vni
->rmac_table
);
958 json_vni
= json_object_new_object();
959 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
963 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
964 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
966 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
968 /* assign per-vni to wctx->json object to fill macs
969 * under the vni. Re-assign primary json object to fill
970 * next vni information.
972 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
974 wctx
.json
= json_vni
;
975 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
977 json_object_object_add(json
, vni_str
, json_vni
);
980 static void zl3vni_print_rmac_hash(struct hash_backet
*backet
, void *ctx
)
982 zebra_mac_t
*zrmac
= NULL
;
983 struct rmac_walk_ctx
*wctx
= NULL
;
984 struct vty
*vty
= NULL
;
985 struct json_object
*json
= NULL
;
986 struct json_object
*json_rmac
= NULL
;
987 char buf
[ETHER_ADDR_STRLEN
];
989 wctx
= (struct rmac_walk_ctx
*)ctx
;
993 json_rmac
= json_object_new_object();
994 zrmac
= (zebra_mac_t
*)backet
->data
;
997 vty_out(vty
, "%-17s %-21s\n",
998 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
999 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1001 json_object_string_add(
1002 json_rmac
, "routerMac",
1003 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1004 json_object_string_add(json_rmac
, "vtepIp",
1005 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1006 json_object_object_add(
1007 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1012 /* print a specific L3 VNI entry */
1013 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1015 char buf
[ETHER_ADDR_STRLEN
];
1016 struct vty
*vty
= NULL
;
1017 json_object
*json
= NULL
;
1018 zebra_vni_t
*zvni
= NULL
;
1019 json_object
*json_vni_list
= NULL
;
1020 struct listnode
*node
= NULL
, *nnode
= NULL
;
1026 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1027 vty_out(vty
, " Type: %s\n", "L3");
1028 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1029 vty_out(vty
, " Local Vtep Ip: %s\n",
1030 inet_ntoa(zl3vni
->local_vtep_ip
));
1031 vty_out(vty
, " Vxlan-Intf: %s\n",
1032 zl3vni_vxlan_if_name(zl3vni
));
1033 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1034 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1035 vty_out(vty
, " VNI Filter: %s\n",
1036 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1037 ? "prefix-routes-only"
1039 vty_out(vty
, " Router MAC: %s\n",
1040 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1041 vty_out(vty
, " L2 VNIs: ");
1042 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1043 vty_out(vty
, "%u ", zvni
->vni
);
1046 json_vni_list
= json_object_new_array();
1047 json_object_int_add(json
, "vni", zl3vni
->vni
);
1048 json_object_string_add(json
, "type", "L3");
1049 json_object_string_add(json
, "localVtepIp",
1050 inet_ntoa(zl3vni
->local_vtep_ip
));
1051 json_object_string_add(json
, "vxlanIntf",
1052 zl3vni_vxlan_if_name(zl3vni
));
1053 json_object_string_add(json
, "sviIntf",
1054 zl3vni_svi_if_name(zl3vni
));
1055 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1056 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1057 json_object_string_add(
1059 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1060 json_object_string_add(
1062 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1063 ? "prefix-routes-only"
1065 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1066 json_object_array_add(json_vni_list
,
1067 json_object_new_int(zvni
->vni
));
1069 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1074 * Print a specific VNI entry.
1076 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1079 zebra_vtep_t
*zvtep
;
1082 json_object
*json
= NULL
;
1083 json_object
*json_vtep_list
= NULL
;
1084 json_object
*json_ip_str
= NULL
;
1090 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1091 vty_out(vty
, " Type: %s\n", "L2");
1092 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1094 json_object_int_add(json
, "vni", zvni
->vni
);
1095 json_object_string_add(json
, "type", "L2");
1096 json_object_string_add(json
, "vrf",
1097 vrf_id_to_name(zvni
->vrf_id
));
1100 if (!zvni
->vxlan_if
) { // unexpected
1102 vty_out(vty
, " VxLAN interface: unknown\n");
1105 num_macs
= num_valid_macs(zvni
);
1106 num_neigh
= hashcount(zvni
->neigh_table
);
1108 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1109 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1110 vty_out(vty
, " Local VTEP IP: %s\n",
1111 inet_ntoa(zvni
->local_vtep_ip
));
1113 json_object_string_add(json
, "vxlanInterface",
1114 zvni
->vxlan_if
->name
);
1115 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1116 json_object_string_add(json
, "vtepIp",
1117 inet_ntoa(zvni
->local_vtep_ip
));
1118 json_object_string_add(json
, "advertiseGatewayMacip",
1119 zvni
->advertise_gw_macip
? "Yes" : "No");
1120 json_object_int_add(json
, "numMacs", num_macs
);
1121 json_object_int_add(json
, "numArpNd", num_neigh
);
1125 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1128 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1130 json_vtep_list
= json_object_new_array();
1131 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1133 vty_out(vty
, " %s\n",
1134 inet_ntoa(zvtep
->vtep_ip
));
1136 json_ip_str
= json_object_new_string(
1137 inet_ntoa(zvtep
->vtep_ip
));
1138 json_object_array_add(json_vtep_list
,
1143 json_object_object_add(json
, "numRemoteVteps",
1148 " Number of MACs (local and remote) known for this VNI: %u\n",
1151 " Number of ARPs (IPv4 and IPv6, local and remote) "
1152 "known for this VNI: %u\n",
1154 vty_out(vty
, " Advertise-gw-macip: %s\n",
1155 zvni
->advertise_gw_macip
? "Yes" : "No");
1159 /* print a L3 VNI hash entry */
1160 static void zl3vni_print_hash(struct hash_backet
*backet
, void *ctx
[])
1162 struct vty
*vty
= NULL
;
1163 json_object
*json
= NULL
;
1164 json_object
*json_vni
= NULL
;
1165 zebra_l3vni_t
*zl3vni
= NULL
;
1167 vty
= (struct vty
*)ctx
[0];
1168 json
= (json_object
*)ctx
[1];
1170 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1173 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1174 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1175 hashcount(zl3vni
->rmac_table
),
1176 hashcount(zl3vni
->nh_table
), "n/a",
1177 zl3vni_vrf_name(zl3vni
));
1179 char vni_str
[VNI_STR_LEN
];
1181 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1182 json_vni
= json_object_new_object();
1183 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1184 json_object_string_add(json_vni
, "vxlanIf",
1185 zl3vni_vxlan_if_name(zl3vni
));
1186 json_object_int_add(json_vni
, "numMacs",
1187 hashcount(zl3vni
->rmac_table
));
1188 json_object_int_add(json_vni
, "numArpNd",
1189 hashcount(zl3vni
->nh_table
));
1190 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1191 json_object_string_add(json_vni
, "type", "L3");
1192 json_object_string_add(json_vni
, "tenantVrf",
1193 zl3vni_vrf_name(zl3vni
));
1194 json_object_object_add(json
, vni_str
, json_vni
);
1199 * Print a VNI hash entry - called for display of all VNIs.
1201 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1205 zebra_vtep_t
*zvtep
;
1206 uint32_t num_vteps
= 0;
1207 uint32_t num_macs
= 0;
1208 uint32_t num_neigh
= 0;
1209 json_object
*json
= NULL
;
1210 json_object
*json_vni
= NULL
;
1211 json_object
*json_ip_str
= NULL
;
1212 json_object
*json_vtep_list
= NULL
;
1217 zvni
= (zebra_vni_t
*)backet
->data
;
1219 zvtep
= zvni
->vteps
;
1222 zvtep
= zvtep
->next
;
1225 num_macs
= num_valid_macs(zvni
);
1226 num_neigh
= hashcount(zvni
->neigh_table
);
1228 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1230 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1231 num_macs
, num_neigh
, num_vteps
,
1232 vrf_id_to_name(zvni
->vrf_id
));
1234 char vni_str
[VNI_STR_LEN
];
1235 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1236 json_vni
= json_object_new_object();
1237 json_object_int_add(json_vni
, "vni", zvni
->vni
);
1238 json_object_string_add(json_vni
, "type", "L2");
1239 json_object_string_add(json_vni
, "vxlanIf",
1240 zvni
->vxlan_if
? zvni
->vxlan_if
->name
1242 json_object_int_add(json_vni
, "numMacs", num_macs
);
1243 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1244 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
1245 json_object_string_add(json_vni
, "tenantVrf",
1246 vrf_id_to_name(zvni
->vrf_id
));
1248 json_vtep_list
= json_object_new_array();
1249 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1250 json_ip_str
= json_object_new_string(
1251 inet_ntoa(zvtep
->vtep_ip
));
1252 json_object_array_add(json_vtep_list
,
1255 json_object_object_add(json_vni
, "remoteVteps",
1258 json_object_object_add(json
, vni_str
, json_vni
);
1263 * Inform BGP about local MACIP.
1265 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
1266 struct ipaddr
*ip
, uint8_t flags
,
1267 uint32_t seq
, uint16_t cmd
)
1269 char buf
[ETHER_ADDR_STRLEN
];
1270 char buf2
[INET6_ADDRSTRLEN
];
1272 struct zserv
*client
= NULL
;
1273 struct stream
*s
= NULL
;
1275 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
1276 /* BGP may not be running. */
1280 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
1282 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
1283 stream_putl(s
, vni
);
1284 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
1287 if (IS_IPADDR_V4(ip
))
1288 ipa_len
= IPV4_MAX_BYTELEN
;
1289 else if (IS_IPADDR_V6(ip
))
1290 ipa_len
= IPV6_MAX_BYTELEN
;
1292 stream_putl(s
, ipa_len
); /* IP address length */
1294 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
1296 stream_putl(s
, 0); /* Just MAC. */
1298 if (cmd
== ZEBRA_MACIP_ADD
) {
1299 stream_putc(s
, flags
); /* sticky mac/gateway mac */
1300 stream_putl(s
, seq
); /* sequence number */
1304 /* Write packet size. */
1305 stream_putw_at(s
, 0, stream_get_endp(s
));
1307 if (IS_ZEBRA_DEBUG_VXLAN
)
1309 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
1310 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
1311 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1312 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
1313 zebra_route_string(client
->proto
));
1315 if (cmd
== ZEBRA_MACIP_ADD
)
1316 client
->macipadd_cnt
++;
1318 client
->macipdel_cnt
++;
1320 return zserv_send_message(client
, s
);
1324 * Make hash key for neighbors.
1326 static unsigned int neigh_hash_keymake(void *p
)
1328 zebra_neigh_t
*n
= p
;
1329 struct ipaddr
*ip
= &n
->ip
;
1331 if (IS_IPADDR_V4(ip
))
1332 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
1334 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
1335 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
1339 * Compare two neighbor hash structures.
1341 static bool neigh_cmp(const void *p1
, const void *p2
)
1343 const zebra_neigh_t
*n1
= p1
;
1344 const zebra_neigh_t
*n2
= p2
;
1346 if (n1
== NULL
&& n2
== NULL
)
1349 if (n1
== NULL
|| n2
== NULL
)
1352 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
1355 static int neigh_list_cmp(void *p1
, void *p2
)
1357 const zebra_neigh_t
*n1
= p1
;
1358 const zebra_neigh_t
*n2
= p2
;
1360 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
1364 * Callback to allocate neighbor hash entry.
1366 static void *zvni_neigh_alloc(void *p
)
1368 const zebra_neigh_t
*tmp_n
= p
;
1371 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
1378 * Add neighbor entry.
1380 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
1381 struct ethaddr
*mac
)
1383 zebra_neigh_t tmp_n
;
1384 zebra_neigh_t
*n
= NULL
;
1385 zebra_mac_t
*zmac
= NULL
;
1387 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
1388 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1389 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
1392 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1393 n
->state
= ZEBRA_NEIGH_INACTIVE
;
1395 /* Associate the neigh to mac */
1396 zmac
= zvni_mac_lookup(zvni
, mac
);
1398 listnode_add_sort(zmac
->neigh_list
, n
);
1404 * Delete neighbor entry.
1406 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1408 zebra_neigh_t
*tmp_n
;
1409 zebra_mac_t
*zmac
= NULL
;
1411 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
1413 listnode_delete(zmac
->neigh_list
, n
);
1415 /* Free the VNI hash entry and allocated memory. */
1416 tmp_n
= hash_release(zvni
->neigh_table
, n
);
1418 XFREE(MTYPE_NEIGH
, tmp_n
);
1424 * Free neighbor hash entry (callback)
1426 static void zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
1428 struct neigh_walk_ctx
*wctx
= arg
;
1429 zebra_neigh_t
*n
= backet
->data
;
1431 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1432 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
1433 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
1434 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
1435 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
1436 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
1437 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1438 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
1441 if (wctx
->uninstall
)
1442 zvni_neigh_uninstall(wctx
->zvni
, n
);
1444 zvni_neigh_del(wctx
->zvni
, n
);
1451 * Delete all neighbor entries from specific VTEP for a particular VNI.
1453 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
1454 struct in_addr
*r_vtep_ip
)
1456 struct neigh_walk_ctx wctx
;
1458 if (!zvni
->neigh_table
)
1461 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1463 wctx
.uninstall
= uninstall
;
1464 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
1465 wctx
.r_vtep_ip
= *r_vtep_ip
;
1467 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1471 * Delete all neighbor entries for this VNI.
1473 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
1476 struct neigh_walk_ctx wctx
;
1478 if (!zvni
->neigh_table
)
1481 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1483 wctx
.uninstall
= uninstall
;
1484 wctx
.upd_client
= upd_client
;
1487 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1491 * Look up neighbor hash entry.
1493 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
1498 memset(&tmp
, 0, sizeof(tmp
));
1499 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
1500 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
1506 * Process all neighbors associated with a MAC upon the MAC being learnt
1507 * locally or undergoing any other change (such as sequence number).
1509 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
1513 zebra_neigh_t
*n
= NULL
;
1514 struct listnode
*node
= NULL
;
1515 char buf
[ETHER_ADDR_STRLEN
];
1517 if (IS_ZEBRA_DEBUG_VXLAN
)
1518 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
1519 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
1520 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
1522 /* Walk all neighbors and mark any inactive local neighbors as
1523 * active and/or update sequence number upon a move, and inform BGP.
1524 * The action for remote neighbors is TBD.
1525 * NOTE: We can't simply uninstall remote neighbors as the kernel may
1526 * accidentally end up deleting a just-learnt local neighbor.
1528 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1529 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1530 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
1531 ZEBRA_NEIGH_SET_ACTIVE(n
);
1532 n
->loc_seq
= zmac
->loc_seq
;
1533 zvni_neigh_send_add_to_client(
1534 zvni
->vni
, &n
->ip
, &n
->emac
,
1535 n
->flags
, n
->loc_seq
);
1542 * Process all neighbors associated with a local MAC upon the MAC being
1545 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
1548 zebra_neigh_t
*n
= NULL
;
1549 struct listnode
*node
= NULL
;
1550 char buf
[ETHER_ADDR_STRLEN
];
1552 if (IS_ZEBRA_DEBUG_VXLAN
)
1553 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
1554 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
1557 /* Walk all local neighbors and mark as inactive and inform
1559 * TBD: There is currently no handling for remote neighbors. We
1560 * don't expect them to exist, if they do, do we install the MAC
1561 * as a remote MAC and the neighbor as remote?
1563 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1564 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1565 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1566 ZEBRA_NEIGH_SET_INACTIVE(n
);
1568 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1576 * Process all neighbors associated with a MAC upon the MAC being remotely
1579 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
1582 zebra_neigh_t
*n
= NULL
;
1583 struct listnode
*node
= NULL
;
1584 char buf
[ETHER_ADDR_STRLEN
];
1586 if (IS_ZEBRA_DEBUG_VXLAN
)
1587 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
1588 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
1591 /* Walk all local neighbors and mark as inactive and inform
1594 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1595 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1596 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1597 ZEBRA_NEIGH_SET_INACTIVE(n
);
1599 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1607 * Process all neighbors associated with a remote MAC upon the MAC being
1610 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
1613 /* NOTE: Currently a NO-OP. */
1617 * Inform BGP about local neighbor addition.
1619 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
1620 struct ethaddr
*macaddr
,
1621 uint8_t neigh_flags
,
1626 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
1627 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
1628 /* Set router flag (R-bit) based on local neigh entry add */
1629 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
1630 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
1632 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1633 seq
, ZEBRA_MACIP_ADD
);
1637 * Inform BGP about local neighbor deletion.
1639 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
1640 struct ethaddr
*macaddr
, uint8_t flags
)
1642 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1643 0, ZEBRA_MACIP_DEL
);
1647 * Install remote neighbor into the kernel.
1649 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1651 struct zebra_if
*zif
;
1652 struct zebra_l2info_vxlan
*vxl
;
1653 struct interface
*vlan_if
;
1659 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1662 zif
= zvni
->vxlan_if
->info
;
1665 vxl
= &zif
->l2info
.vxl
;
1667 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1671 flags
= NTF_EXT_LEARNED
;
1672 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
1673 flags
|= NTF_ROUTER
;
1674 ZEBRA_NEIGH_SET_ACTIVE(n
);
1675 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
1681 * Uninstall remote neighbor from the kernel.
1683 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1685 struct zebra_if
*zif
;
1686 struct zebra_l2info_vxlan
*vxl
;
1687 struct interface
*vlan_if
;
1689 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1692 if (!zvni
->vxlan_if
) {
1693 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
1698 zif
= zvni
->vxlan_if
->info
;
1701 vxl
= &zif
->l2info
.vxl
;
1702 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1706 ZEBRA_NEIGH_SET_INACTIVE(n
);
1708 return kernel_del_neigh(vlan_if
, &n
->ip
);
1712 * Install neighbor hash entry - called upon access VLAN change.
1714 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
1717 struct neigh_walk_ctx
*wctx
= ctxt
;
1719 n
= (zebra_neigh_t
*)backet
->data
;
1721 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
1722 zvni_neigh_install(wctx
->zvni
, n
);
1725 /* Get the VRR interface for SVI if any */
1726 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
1728 struct zebra_vrf
*zvrf
= NULL
;
1729 struct interface
*tmp_if
= NULL
;
1730 struct zebra_if
*zif
= NULL
;
1732 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1735 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
1740 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
1743 if (zif
->link
== ifp
)
1750 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1752 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1753 struct connected
*c
= NULL
;
1754 struct ethaddr macaddr
;
1756 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1758 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1761 memset(&ip
, 0, sizeof(struct ipaddr
));
1762 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1765 if (c
->address
->family
== AF_INET
) {
1766 ip
.ipa_type
= IPADDR_V4
;
1767 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1768 sizeof(struct in_addr
));
1769 } else if (c
->address
->family
== AF_INET6
) {
1770 ip
.ipa_type
= IPADDR_V6
;
1771 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1772 sizeof(struct in6_addr
));
1777 zvni_gw_macip_del(ifp
, zvni
, &ip
);
1783 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1785 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1786 struct connected
*c
= NULL
;
1787 struct ethaddr macaddr
;
1789 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1791 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1794 memset(&ip
, 0, sizeof(struct ipaddr
));
1795 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1798 if (c
->address
->family
== AF_INET
) {
1799 ip
.ipa_type
= IPADDR_V4
;
1800 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1801 sizeof(struct in_addr
));
1802 } else if (c
->address
->family
== AF_INET6
) {
1803 ip
.ipa_type
= IPADDR_V6
;
1804 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1805 sizeof(struct in6_addr
));
1810 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
1816 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
1819 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1820 struct connected
*c
= NULL
;
1821 struct ethaddr macaddr
;
1823 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1825 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1828 memcpy(&p
, c
->address
, sizeof(struct prefix
));
1830 /* skip link local address */
1831 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
1836 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1837 ZEBRA_IP_PREFIX_ROUTE_ADD
);
1839 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1840 ZEBRA_IP_PREFIX_ROUTE_DEL
);
1846 * zvni_gw_macip_add_to_client
1848 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
1849 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
1851 char buf
[ETHER_ADDR_STRLEN
];
1852 char buf2
[INET6_ADDRSTRLEN
];
1853 zebra_neigh_t
*n
= NULL
;
1854 zebra_mac_t
*mac
= NULL
;
1855 struct zebra_if
*zif
= NULL
;
1856 struct zebra_l2info_vxlan
*vxl
= NULL
;
1858 zif
= zvni
->vxlan_if
->info
;
1862 vxl
= &zif
->l2info
.vxl
;
1864 mac
= zvni_mac_lookup(zvni
, macaddr
);
1866 mac
= zvni_mac_add(zvni
, macaddr
);
1868 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
1869 "Failed to add MAC %s intf %s(%u) VID %u",
1870 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1871 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
1876 /* Set "local" forwarding info. */
1877 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
1878 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
1879 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
1880 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
1881 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
1882 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
1884 n
= zvni_neigh_lookup(zvni
, ip
);
1886 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
1889 EC_ZEBRA_MAC_ADD_FAILED
,
1890 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1891 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
1892 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1893 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
1898 /* Set "local" forwarding info. */
1899 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
1900 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
1901 ZEBRA_NEIGH_SET_ACTIVE(n
);
1902 /* Set Router flag (R-bit) */
1903 if (ip
->ipa_type
== IPADDR_V6
)
1904 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
1905 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
1906 n
->ifindex
= ifp
->ifindex
;
1908 /* Only advertise in BGP if the knob is enabled */
1909 if (!advertise_gw_macip_enabled(zvni
))
1912 if (IS_ZEBRA_DEBUG_VXLAN
)
1914 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
1915 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1916 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1917 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
1919 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
1920 n
->flags
, n
->loc_seq
);
1926 * zvni_gw_macip_del_from_client
1928 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
1931 char buf1
[ETHER_ADDR_STRLEN
];
1932 char buf2
[INET6_ADDRSTRLEN
];
1933 zebra_neigh_t
*n
= NULL
;
1934 zebra_mac_t
*mac
= NULL
;
1936 /* If the neigh entry is not present nothing to do*/
1937 n
= zvni_neigh_lookup(zvni
, ip
);
1941 /* mac entry should be present */
1942 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
1944 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
1945 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
1946 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1950 /* If the entry is not local nothing to do*/
1951 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
1954 /* only need to delete the entry from bgp if we sent it before */
1955 if (IS_ZEBRA_DEBUG_VXLAN
)
1957 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
1958 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1959 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
1960 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1962 /* Remove neighbor from BGP. */
1963 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
1964 ZEBRA_MACIP_TYPE_GW
);
1966 /* Delete this neighbor entry. */
1967 zvni_neigh_del(zvni
, n
);
1969 /* see if the mac needs to be deleted as well*/
1971 zvni_deref_ip2mac(zvni
, mac
);
1976 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
1979 zebra_vni_t
*zvni
= NULL
;
1980 struct zebra_if
*zif
= NULL
;
1981 struct zebra_l2info_vxlan zl2_info
;
1982 struct interface
*vlan_if
= NULL
;
1983 struct interface
*vrr_if
= NULL
;
1984 struct interface
*ifp
;
1986 /* Add primary SVI MAC*/
1987 zvni
= (zebra_vni_t
*)backet
->data
;
1989 ifp
= zvni
->vxlan_if
;
1994 /* If down or not mapped to a bridge, we're done. */
1995 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1998 zl2_info
= zif
->l2info
.vxl
;
2001 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2005 /* Del primary MAC-IP */
2006 zvni_del_macip_for_intf(vlan_if
, zvni
);
2008 /* Del VRR MAC-IP - if any*/
2009 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2011 zvni_del_macip_for_intf(vrr_if
, zvni
);
2016 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
2019 zebra_vni_t
*zvni
= NULL
;
2020 struct zebra_if
*zif
= NULL
;
2021 struct zebra_l2info_vxlan zl2_info
;
2022 struct interface
*vlan_if
= NULL
;
2023 struct interface
*vrr_if
= NULL
;
2024 struct interface
*ifp
= NULL
;
2026 zvni
= (zebra_vni_t
*)backet
->data
;
2028 ifp
= zvni
->vxlan_if
;
2033 /* If down or not mapped to a bridge, we're done. */
2034 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2036 zl2_info
= zif
->l2info
.vxl
;
2039 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2043 /* Add primary SVI MAC-IP */
2044 zvni_add_macip_for_intf(vlan_if
, zvni
);
2046 /* Add VRR MAC-IP - if any*/
2047 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2049 zvni_add_macip_for_intf(vrr_if
, zvni
);
2054 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2055 struct interface
*ifp
,
2057 struct ethaddr
*macaddr
,
2060 char buf
[ETHER_ADDR_STRLEN
];
2061 char buf2
[INET6_ADDRSTRLEN
];
2062 zebra_neigh_t
*n
= NULL
;
2063 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2064 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2065 bool upd_mac_seq
= false;
2066 bool neigh_mac_change
= false;
2067 bool check_rbit
= false;
2069 /* Check if the MAC exists. */
2070 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2072 /* create a dummy MAC if the MAC is not already present */
2073 if (IS_ZEBRA_DEBUG_VXLAN
)
2075 "AUTO MAC %s created for neigh %s on VNI %u",
2076 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2077 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2079 zmac
= zvni_mac_add(zvni
, macaddr
);
2081 zlog_debug("Failed to add MAC %s VNI %u",
2082 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2087 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
2088 memset(&zmac
->flags
, 0, sizeof(uint32_t));
2089 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2091 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2093 * We don't change the MAC to local upon a neighbor
2094 * learn event, we wait for the explicit local MAC
2095 * learn. However, we have to compute its sequence
2096 * number in preparation for when it actually turns
2103 /* Check if the neighbor exists. */
2104 n
= zvni_neigh_lookup(zvni
, ip
);
2106 /* New neighbor - create */
2107 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2110 EC_ZEBRA_MAC_ADD_FAILED
,
2111 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2112 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2113 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2114 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2117 /* Set "local" forwarding info. */
2118 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2119 n
->ifindex
= ifp
->ifindex
;
2122 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2126 /* Note any changes and see if of interest to BGP. */
2127 mac_different
= (memcmp(n
->emac
.octet
,
2128 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
2129 cur_is_router
= !!CHECK_FLAG(n
->flags
,
2130 ZEBRA_NEIGH_ROUTER_FLAG
);
2131 if (!mac_different
&& is_router
== cur_is_router
) {
2132 n
->ifindex
= ifp
->ifindex
;
2136 if (!mac_different
) {
2137 /* Only the router flag has changed. */
2140 ZEBRA_NEIGH_ROUTER_FLAG
);
2142 UNSET_FLAG(n
->flags
,
2143 ZEBRA_NEIGH_ROUTER_FLAG
);
2145 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
2146 return zvni_neigh_send_add_to_client(
2147 zvni
->vni
, ip
, macaddr
,
2148 n
->flags
, n
->loc_seq
);
2152 /* The MAC has changed, need to issue a delete
2153 * first as this means a different MACIP route.
2154 * Also, need to do some unlinking/relinking.
2155 * We also need to update the MAC's sequence number
2156 * in different situations.
2158 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
2159 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2161 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2163 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
2165 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
2166 neigh_mac_change
= upd_mac_seq
= true;
2167 listnode_delete(old_zmac
->neigh_list
, n
);
2168 zvni_deref_ip2mac(zvni
, old_zmac
);
2171 /* Update the forwarding info. */
2172 n
->ifindex
= ifp
->ifindex
;
2173 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2175 /* Link to new MAC */
2176 listnode_add_sort(zmac
->neigh_list
, n
);
2177 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2179 * Neighbor has moved from remote to local. Its
2180 * MAC could have also changed as part of the move.
2182 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2184 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2186 old_mac_seq
= CHECK_FLAG(
2191 neigh_mac_change
= upd_mac_seq
= true;
2192 listnode_delete(old_zmac
->neigh_list
,
2194 zvni_deref_ip2mac(zvni
, old_zmac
);
2197 /* Link to new MAC */
2198 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2199 listnode_add_sort(zmac
->neigh_list
, n
);
2202 /* Mark appropriately */
2203 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2204 n
->r_vtep_ip
.s_addr
= 0;
2205 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2206 n
->ifindex
= ifp
->ifindex
;
2211 /* If MAC was previously remote, or the neighbor had a different
2212 * MAC earlier, recompute the sequence number.
2215 uint32_t seq1
, seq2
;
2217 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
2218 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
2219 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
2220 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
2221 MAX(seq1
, seq2
) : zmac
->loc_seq
;
2224 /*Mark Router flag (R-bit) */
2226 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2228 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2230 /* Before we program this in BGP, we need to check if MAC is locally
2231 * learnt. If not, force neighbor to be inactive and reset its seq.
2233 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
2234 ZEBRA_NEIGH_SET_INACTIVE(n
);
2236 zmac
->loc_seq
= mac_new_seq
;
2243 /* If the MAC's sequence number has changed, inform the MAC and all
2244 * neighbors associated with the MAC to BGP, else just inform this
2247 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
2248 if (IS_ZEBRA_DEBUG_VXLAN
)
2249 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
2250 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2251 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
2252 zmac
->loc_seq
= mac_new_seq
;
2253 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
2254 zmac
->flags
, zmac
->loc_seq
))
2256 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
2260 ZEBRA_NEIGH_SET_ACTIVE(n
);
2261 n
->loc_seq
= zmac
->loc_seq
;
2263 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2264 n
->flags
, n
->loc_seq
);
2267 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
2268 struct interface
*ifp
,
2270 struct ethaddr
*macaddr
,
2273 char buf
[ETHER_ADDR_STRLEN
];
2274 char buf2
[INET6_ADDRSTRLEN
];
2275 zebra_neigh_t
*n
= NULL
;
2276 zebra_mac_t
*zmac
= NULL
;
2278 /* If the neighbor is unknown, there is no further action. */
2279 n
= zvni_neigh_lookup(zvni
, ip
);
2283 /* If a remote entry, see if it needs to be refreshed */
2284 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2286 if (state
& NUD_STALE
)
2287 zvni_neigh_install(zvni
, n
);
2290 /* We got a "remote" neighbor notification for an entry
2291 * we think is local. This can happen in a multihoming
2292 * scenario - but only if the MAC is already "remote".
2293 * Just mark our entry as "remote".
2295 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2296 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2298 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
2299 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
2300 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2305 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2306 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2307 ZEBRA_NEIGH_SET_ACTIVE(n
);
2308 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
2315 * Make hash key for MAC.
2317 static unsigned int mac_hash_keymake(void *p
)
2319 zebra_mac_t
*pmac
= p
;
2320 const void *pnt
= (void *)pmac
->macaddr
.octet
;
2322 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
2326 * Compare two MAC addresses.
2328 static bool mac_cmp(const void *p1
, const void *p2
)
2330 const zebra_mac_t
*pmac1
= p1
;
2331 const zebra_mac_t
*pmac2
= p2
;
2333 if (pmac1
== NULL
&& pmac2
== NULL
)
2336 if (pmac1
== NULL
|| pmac2
== NULL
)
2339 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
2344 * Callback to allocate MAC hash entry.
2346 static void *zvni_mac_alloc(void *p
)
2348 const zebra_mac_t
*tmp_mac
= p
;
2351 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2354 return ((void *)mac
);
2360 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
2362 zebra_mac_t tmp_mac
;
2363 zebra_mac_t
*mac
= NULL
;
2365 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
2366 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
2367 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
2370 mac
->neigh_list
= list_new();
2371 mac
->neigh_list
->cmp
= neigh_list_cmp
;
2379 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2381 zebra_mac_t
*tmp_mac
;
2383 list_delete(&mac
->neigh_list
);
2385 /* Free the VNI hash entry and allocated memory. */
2386 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
2388 XFREE(MTYPE_MAC
, tmp_mac
);
2394 * Free MAC hash entry (callback)
2396 static void zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2398 struct mac_walk_ctx
*wctx
= arg
;
2399 zebra_mac_t
*mac
= backet
->data
;
2401 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
2402 || ((wctx
->flags
& DEL_REMOTE_MAC
)
2403 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
2404 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
2405 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
2406 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
2407 &wctx
->r_vtep_ip
))) {
2408 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
2409 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
2413 if (wctx
->uninstall
)
2414 zvni_mac_uninstall(wctx
->zvni
, mac
);
2416 zvni_mac_del(wctx
->zvni
, mac
);
2423 * Delete all MAC entries from specific VTEP for a particular VNI.
2425 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2426 struct in_addr
*r_vtep_ip
)
2428 struct mac_walk_ctx wctx
;
2430 if (!zvni
->mac_table
)
2433 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2435 wctx
.uninstall
= uninstall
;
2436 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
2437 wctx
.r_vtep_ip
= *r_vtep_ip
;
2439 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2443 * Delete all MAC entries for this VNI.
2445 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2448 struct mac_walk_ctx wctx
;
2450 if (!zvni
->mac_table
)
2453 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2455 wctx
.uninstall
= uninstall
;
2456 wctx
.upd_client
= upd_client
;
2459 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2463 * Look up MAC hash entry.
2465 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
2470 memset(&tmp
, 0, sizeof(tmp
));
2471 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
2472 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
2478 * Inform BGP about local MAC addition.
2480 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2481 uint8_t mac_flags
, uint32_t seq
)
2485 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2486 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2487 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2488 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2490 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2491 seq
, ZEBRA_MACIP_ADD
);
2495 * Inform BGP about local MAC deletion.
2497 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
2499 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
2500 0 /* seq */, ZEBRA_MACIP_DEL
);
2504 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2505 * notifications, to see if they are of interest.
2507 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
2508 struct interface
*br_if
, vlanid_t vid
)
2510 struct zebra_ns
*zns
;
2511 struct route_node
*rn
;
2512 struct interface
*tmp_if
= NULL
;
2513 struct zebra_if
*zif
;
2514 struct zebra_l2info_bridge
*br
;
2515 struct zebra_l2info_vxlan
*vxl
= NULL
;
2516 uint8_t bridge_vlan_aware
;
2520 /* Determine if bridge is VLAN-aware or not */
2523 br
= &zif
->l2info
.br
;
2524 bridge_vlan_aware
= br
->vlan_aware
;
2526 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2527 /* TODO: Optimize with a hash. */
2528 zns
= zebra_ns_lookup(NS_DEFAULT
);
2529 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2530 tmp_if
= (struct interface
*)rn
->info
;
2534 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2536 if (!if_is_operative(tmp_if
))
2538 vxl
= &zif
->l2info
.vxl
;
2540 if (zif
->brslave_info
.br_if
!= br_if
)
2543 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2552 zvni
= zvni_lookup(vxl
->vni
);
2557 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2558 * neighbor notifications, to see if they are of interest.
2560 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
2561 struct interface
*br_if
)
2563 struct zebra_ns
*zns
;
2564 struct route_node
*rn
;
2565 struct interface
*tmp_if
= NULL
;
2566 struct zebra_if
*zif
;
2567 struct zebra_l2info_bridge
*br
;
2568 struct zebra_l2info_vxlan
*vxl
= NULL
;
2569 uint8_t bridge_vlan_aware
;
2577 /* Make sure the linked interface is a bridge. */
2578 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
2581 /* Determine if bridge is VLAN-aware or not */
2584 br
= &zif
->l2info
.br
;
2585 bridge_vlan_aware
= br
->vlan_aware
;
2586 if (bridge_vlan_aware
) {
2587 struct zebra_l2info_vlan
*vl
;
2589 if (!IS_ZEBRA_IF_VLAN(ifp
))
2594 vl
= &zif
->l2info
.vl
;
2598 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2599 /* TODO: Optimize with a hash. */
2600 zns
= zebra_ns_lookup(NS_DEFAULT
);
2601 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2602 tmp_if
= (struct interface
*)rn
->info
;
2606 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2608 if (!if_is_operative(tmp_if
))
2610 vxl
= &zif
->l2info
.vxl
;
2612 if (zif
->brslave_info
.br_if
!= br_if
)
2615 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2624 zvni
= zvni_lookup(vxl
->vni
);
2628 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
2630 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
2631 * linked to the bridge
2632 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
2635 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
2637 struct zebra_ns
*zns
;
2638 struct route_node
*rn
;
2639 struct interface
*tmp_if
= NULL
;
2640 struct zebra_if
*zif
;
2641 struct zebra_l2info_bridge
*br
;
2642 struct zebra_l2info_vlan
*vl
;
2643 uint8_t bridge_vlan_aware
;
2646 /* Defensive check, caller expected to invoke only with valid bridge. */
2650 /* Determine if bridge is VLAN-aware or not */
2653 br
= &zif
->l2info
.br
;
2654 bridge_vlan_aware
= br
->vlan_aware
;
2656 /* Check oper status of the SVI. */
2657 if (!bridge_vlan_aware
)
2658 return if_is_operative(br_if
) ? br_if
: NULL
;
2660 /* Identify corresponding VLAN interface. */
2661 /* TODO: Optimize with a hash. */
2662 zns
= zebra_ns_lookup(NS_DEFAULT
);
2663 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2664 tmp_if
= (struct interface
*)rn
->info
;
2665 /* Check oper status of the SVI. */
2666 if (!tmp_if
|| !if_is_operative(tmp_if
))
2669 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
2670 || zif
->link
!= br_if
)
2672 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
2674 if (vl
->vid
== vid
) {
2680 return found
? tmp_if
: NULL
;
2684 * Install remote MAC into the kernel.
2686 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2688 struct zebra_if
*zif
;
2689 struct zebra_l2info_vxlan
*vxl
;
2692 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2695 zif
= zvni
->vxlan_if
->info
;
2698 vxl
= &zif
->l2info
.vxl
;
2700 sticky
= !!CHECK_FLAG(mac
->flags
,
2701 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
2703 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
2704 mac
->fwd_info
.r_vtep_ip
, sticky
);
2708 * Uninstall remote MAC from the kernel.
2710 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2712 struct zebra_if
*zif
;
2713 struct zebra_l2info_vxlan
*vxl
;
2714 struct in_addr vtep_ip
;
2715 struct interface
*ifp
;
2717 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2720 if (!zvni
->vxlan_if
) {
2721 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2726 zif
= zvni
->vxlan_if
->info
;
2729 vxl
= &zif
->l2info
.vxl
;
2731 ifp
= zvni
->vxlan_if
;
2732 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
2734 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
2738 * Install MAC hash entry - called upon access VLAN change.
2740 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
2743 struct mac_walk_ctx
*wctx
= ctxt
;
2745 mac
= (zebra_mac_t
*)backet
->data
;
2747 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
2748 zvni_mac_install(wctx
->zvni
, mac
);
2752 * Count of remote neighbors referencing this MAC.
2754 static int remote_neigh_count(zebra_mac_t
*zmac
)
2756 zebra_neigh_t
*n
= NULL
;
2757 struct listnode
*node
= NULL
;
2760 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2761 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2769 * Decrement neighbor refcount of MAC; uninstall and free it if
2772 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2774 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
2777 /* If all remote neighbors referencing a remote MAC go away,
2778 * we need to uninstall the MAC.
2780 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
2781 remote_neigh_count(mac
) == 0) {
2782 zvni_mac_uninstall(zvni
, mac
);
2783 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
2786 /* If no neighbors, delete the MAC. */
2787 if (list_isempty(mac
->neigh_list
))
2788 zvni_mac_del(zvni
, mac
);
2792 * Read and populate local MACs and neighbors corresponding to this VNI.
2794 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
2796 struct zebra_ns
*zns
;
2797 struct zebra_if
*zif
;
2798 struct interface
*vlan_if
;
2799 struct zebra_l2info_vxlan
*vxl
;
2800 struct interface
*vrr_if
;
2803 vxl
= &zif
->l2info
.vxl
;
2804 zns
= zebra_ns_lookup(NS_DEFAULT
);
2806 if (IS_ZEBRA_DEBUG_VXLAN
)
2808 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2809 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2810 zif
->brslave_info
.bridge_ifindex
);
2812 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
2813 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2816 /* Add SVI MAC-IP */
2817 zvni_add_macip_for_intf(vlan_if
, zvni
);
2819 /* Add VRR MAC-IP - if any*/
2820 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2822 zvni_add_macip_for_intf(vrr_if
, zvni
);
2824 neigh_read_for_vlan(zns
, vlan_if
);
2829 * Hash function for VNI.
2831 static unsigned int vni_hash_keymake(void *p
)
2833 const zebra_vni_t
*zvni
= p
;
2835 return (jhash_1word(zvni
->vni
, 0));
2839 * Compare 2 VNI hash entries.
2841 static bool vni_hash_cmp(const void *p1
, const void *p2
)
2843 const zebra_vni_t
*zvni1
= p1
;
2844 const zebra_vni_t
*zvni2
= p2
;
2846 return (zvni1
->vni
== zvni2
->vni
);
2849 static int vni_list_cmp(void *p1
, void *p2
)
2851 const zebra_vni_t
*zvni1
= p1
;
2852 const zebra_vni_t
*zvni2
= p2
;
2854 if (zvni1
->vni
== zvni2
->vni
)
2856 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
2860 * Callback to allocate VNI hash entry.
2862 static void *zvni_alloc(void *p
)
2864 const zebra_vni_t
*tmp_vni
= p
;
2867 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
2868 zvni
->vni
= tmp_vni
->vni
;
2869 return ((void *)zvni
);
2873 * Look up VNI hash entry.
2875 static zebra_vni_t
*zvni_lookup(vni_t vni
)
2877 struct zebra_vrf
*zvrf
;
2878 zebra_vni_t tmp_vni
;
2879 zebra_vni_t
*zvni
= NULL
;
2881 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2883 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
2885 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
2891 * Add VNI hash entry.
2893 static zebra_vni_t
*zvni_add(vni_t vni
)
2895 struct zebra_vrf
*zvrf
;
2896 zebra_vni_t tmp_zvni
;
2897 zebra_vni_t
*zvni
= NULL
;
2899 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2901 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
2903 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
2906 /* Create hash table for MAC */
2908 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
2910 /* Create hash table for neighbors */
2911 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
2912 "Zebra VNI Neighbor Table");
2918 * Delete VNI hash entry.
2920 static int zvni_del(zebra_vni_t
*zvni
)
2922 struct zebra_vrf
*zvrf
;
2923 zebra_vni_t
*tmp_zvni
;
2925 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2928 zvni
->vxlan_if
= NULL
;
2930 /* Free the neighbor hash table. */
2931 hash_free(zvni
->neigh_table
);
2932 zvni
->neigh_table
= NULL
;
2934 /* Free the MAC hash table. */
2935 hash_free(zvni
->mac_table
);
2936 zvni
->mac_table
= NULL
;
2938 /* Free the VNI hash entry and allocated memory. */
2939 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
2941 XFREE(MTYPE_ZVNI
, tmp_zvni
);
2947 * Inform BGP about local VNI addition.
2949 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
2951 struct zserv
*client
;
2954 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2955 /* BGP may not be running. */
2959 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2961 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
2962 stream_putl(s
, zvni
->vni
);
2963 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
2964 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
2966 /* Write packet size. */
2967 stream_putw_at(s
, 0, stream_get_endp(s
));
2969 if (IS_ZEBRA_DEBUG_VXLAN
)
2970 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
2971 inet_ntoa(zvni
->local_vtep_ip
),
2972 vrf_id_to_name(zvni
->vrf_id
),
2973 zebra_route_string(client
->proto
));
2975 client
->vniadd_cnt
++;
2976 return zserv_send_message(client
, s
);
2980 * Inform BGP about local VNI deletion.
2982 static int zvni_send_del_to_client(vni_t vni
)
2984 struct zserv
*client
;
2987 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2988 /* BGP may not be running. */
2992 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2995 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
2996 stream_putl(s
, vni
);
2998 /* Write packet size. */
2999 stream_putw_at(s
, 0, stream_get_endp(s
));
3001 if (IS_ZEBRA_DEBUG_VXLAN
)
3002 zlog_debug("Send VNI_DEL %u to %s", vni
,
3003 zebra_route_string(client
->proto
));
3005 client
->vnidel_cnt
++;
3006 return zserv_send_message(client
, s
);
3010 * Build the VNI hash table by going over the VxLAN interfaces. This
3011 * is called when EVPN (advertise-all-vni) is enabled.
3013 static void zvni_build_hash_table()
3015 struct zebra_ns
*zns
;
3016 struct route_node
*rn
;
3017 struct interface
*ifp
;
3019 /* Walk VxLAN interfaces and create VNI hash. */
3020 zns
= zebra_ns_lookup(NS_DEFAULT
);
3021 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3023 zebra_vni_t
*zvni
= NULL
;
3024 zebra_l3vni_t
*zl3vni
= NULL
;
3025 struct zebra_if
*zif
;
3026 struct zebra_l2info_vxlan
*vxl
;
3028 ifp
= (struct interface
*)rn
->info
;
3032 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3035 vxl
= &zif
->l2info
.vxl
;
3038 /* L3-VNI and L2-VNI are handled seperately */
3039 zl3vni
= zl3vni_lookup(vni
);
3042 if (IS_ZEBRA_DEBUG_VXLAN
)
3044 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
3045 ifp
->name
, ifp
->ifindex
, vni
);
3047 /* associate with vxlan_if */
3048 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3049 zl3vni
->vxlan_if
= ifp
;
3052 * we need to associate with SVI.
3053 * we can associate with svi-if only after association
3054 * with vxlan-intf is complete
3056 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
3058 if (is_l3vni_oper_up(zl3vni
))
3059 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
3062 struct interface
*vlan_if
= NULL
;
3064 if (IS_ZEBRA_DEBUG_VXLAN
)
3066 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
3067 ifp
->name
, ifp
->ifindex
, vni
,
3068 inet_ntoa(vxl
->vtep_ip
));
3070 /* VNI hash entry is not expected to exist. */
3071 zvni
= zvni_lookup(vni
);
3074 "VNI hash already present for IF %s(%u) L2-VNI %u",
3075 ifp
->name
, ifp
->ifindex
, vni
);
3079 zvni
= zvni_add(vni
);
3082 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
3083 ifp
->name
, ifp
->ifindex
, vni
);
3087 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
3088 zvni
->vxlan_if
= ifp
;
3089 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
3090 zif
->brslave_info
.br_if
);
3092 zvni
->vrf_id
= vlan_if
->vrf_id
;
3093 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
3095 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3099 /* Inform BGP if intf is up and mapped to bridge. */
3100 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
3101 zvni_send_add_to_client(zvni
);
3107 * See if remote VTEP matches with prefix.
3109 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
3111 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
3115 * Locate remote VTEP in VNI hash table.
3117 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3119 zebra_vtep_t
*zvtep
;
3124 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
3125 if (zvni_vtep_match(vtep_ip
, zvtep
))
3133 * Add remote VTEP to VNI hash table.
3135 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3137 zebra_vtep_t
*zvtep
;
3139 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
3141 zvtep
->vtep_ip
= *vtep_ip
;
3144 zvni
->vteps
->prev
= zvtep
;
3145 zvtep
->next
= zvni
->vteps
;
3146 zvni
->vteps
= zvtep
;
3152 * Remove remote VTEP from VNI hash table.
3154 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
3157 zvtep
->next
->prev
= zvtep
->prev
;
3159 zvtep
->prev
->next
= zvtep
->next
;
3161 zvni
->vteps
= zvtep
->next
;
3163 zvtep
->prev
= zvtep
->next
= NULL
;
3164 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
3170 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
3171 * uninstall from kernel if asked to.
3173 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
3175 zebra_vtep_t
*zvtep
, *zvtep_next
;
3180 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
3181 zvtep_next
= zvtep
->next
;
3183 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
3184 zvni_vtep_del(zvni
, zvtep
);
3191 * Install remote VTEP into the kernel.
3193 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3195 if (is_vxlan_flooding_head_end())
3196 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3201 * Uninstall remote VTEP from the kernel.
3203 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3205 if (!zvni
->vxlan_if
) {
3206 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3211 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3215 * Install or uninstall flood entries in the kernel corresponding to
3216 * remote VTEPs. This is invoked upon change to BUM handling.
3218 static void zvni_handle_flooding_remote_vteps(struct hash_backet
*backet
,
3222 zebra_vtep_t
*zvtep
;
3224 zvni
= (zebra_vni_t
*)backet
->data
;
3228 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
3229 if (is_vxlan_flooding_head_end())
3230 zvni_vtep_install(zvni
, &zvtep
->vtep_ip
);
3232 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
3237 * Cleanup VNI/VTEP and update kernel
3239 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
3241 zebra_vni_t
*zvni
= NULL
;
3242 zebra_l3vni_t
*zl3vni
= NULL
;
3243 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
3245 zvni
= (zebra_vni_t
*)backet
->data
;
3247 /* remove from l3-vni list */
3249 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
3251 listnode_delete(zl3vni
->l2vnis
, zvni
);
3253 /* Free up all neighbors and MACs, if any. */
3254 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
3255 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
3257 /* Free up all remote VTEPs, if any. */
3258 zvni_vtep_del_all(zvni
, 1);
3260 /* Delete the hash entry. */
3265 static void zl3vni_cleanup_all(struct hash_backet
*backet
, void *args
)
3267 zebra_l3vni_t
*zl3vni
= NULL
;
3269 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
3271 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
3274 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
3275 struct prefix
*host
)
3277 struct host_rb_entry lookup
;
3278 struct host_rb_entry
*hle
;
3280 memset(&lookup
, 0, sizeof(lookup
));
3281 memcpy(&lookup
.p
, host
, sizeof(*host
));
3283 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3287 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
3288 memcpy(hle
, &lookup
, sizeof(lookup
));
3290 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
3293 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
3295 struct host_rb_entry lookup
;
3296 struct host_rb_entry
*hle
;
3298 memset(&lookup
, 0, sizeof(lookup
));
3299 memcpy(&lookup
.p
, host
, sizeof(*host
));
3301 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3303 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
3304 XFREE(MTYPE_HOST_PREFIX
, hle
);
3311 * Look up MAC hash entry.
3313 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
3314 struct ethaddr
*rmac
)
3319 memset(&tmp
, 0, sizeof(tmp
));
3320 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
3321 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
3327 * Callback to allocate RMAC hash entry.
3329 static void *zl3vni_rmac_alloc(void *p
)
3331 const zebra_mac_t
*tmp_rmac
= p
;
3334 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3337 return ((void *)zrmac
);
3341 * Add RMAC entry to l3-vni
3343 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
3345 zebra_mac_t tmp_rmac
;
3346 zebra_mac_t
*zrmac
= NULL
;
3348 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
3349 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
3350 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
3353 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
3355 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
3356 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
3364 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3366 zebra_mac_t
*tmp_rmac
;
3367 struct host_rb_entry
*hle
;
3369 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3370 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
3372 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
3373 XFREE(MTYPE_HOST_PREFIX
, hle
);
3376 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
3378 XFREE(MTYPE_MAC
, tmp_rmac
);
3384 * Install remote RMAC into the kernel.
3386 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3388 struct zebra_if
*zif
= NULL
;
3389 struct zebra_l2info_vxlan
*vxl
= NULL
;
3391 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3392 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3395 zif
= zl3vni
->vxlan_if
->info
;
3399 vxl
= &zif
->l2info
.vxl
;
3401 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3402 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3406 * Uninstall remote RMAC from the kernel.
3408 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3410 char buf
[ETHER_ADDR_STRLEN
];
3411 struct zebra_if
*zif
= NULL
;
3412 struct zebra_l2info_vxlan
*vxl
= NULL
;
3414 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3415 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3418 if (!zl3vni
->vxlan_if
) {
3420 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
3421 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
3422 zl3vni
->vni
, zl3vni
);
3426 zif
= zl3vni
->vxlan_if
->info
;
3430 vxl
= &zif
->l2info
.vxl
;
3432 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3433 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
3436 /* handle rmac add */
3437 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
3438 struct ipaddr
*vtep_ip
,
3439 struct prefix
*host_prefix
)
3441 char buf
[ETHER_ADDR_STRLEN
];
3442 char buf1
[INET6_ADDRSTRLEN
];
3443 zebra_mac_t
*zrmac
= NULL
;
3445 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3448 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
3451 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
3452 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3454 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
3457 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
3458 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
3460 /* install rmac in kernel */
3461 zl3vni_rmac_install(zl3vni
, zrmac
);
3464 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
3470 /* handle rmac delete */
3471 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
3472 struct prefix
*host_prefix
)
3474 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
3476 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3477 /* uninstall from kernel */
3478 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3480 /* del the rmac entry */
3481 zl3vni_rmac_del(zl3vni
, zrmac
);
3486 * Look up nh hash entry on a l3-vni.
3488 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3493 memset(&tmp
, 0, sizeof(tmp
));
3494 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
3495 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
3502 * Callback to allocate NH hash entry on L3-VNI.
3504 static void *zl3vni_nh_alloc(void *p
)
3506 const zebra_neigh_t
*tmp_n
= p
;
3509 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
3516 * Add neighbor entry.
3518 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3519 struct ethaddr
*mac
)
3521 zebra_neigh_t tmp_n
;
3522 zebra_neigh_t
*n
= NULL
;
3524 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
3525 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
3526 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
3529 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
3531 memcpy(&n
->emac
, mac
, ETH_ALEN
);
3532 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3533 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
3539 * Delete neighbor entry.
3541 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3543 zebra_neigh_t
*tmp_n
;
3544 struct host_rb_entry
*hle
;
3546 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
3547 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
3549 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
3550 XFREE(MTYPE_HOST_PREFIX
, hle
);
3553 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
3555 XFREE(MTYPE_NEIGH
, tmp_n
);
3561 * Install remote nh as neigh into the kernel.
3563 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3570 if (!is_l3vni_oper_up(zl3vni
))
3573 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3574 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3577 flags
= NTF_EXT_LEARNED
;
3578 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
3579 flags
|= NTF_ROUTER
;
3580 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
3586 * Uninstall remote nh from the kernel.
3588 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3590 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3591 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3594 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
3597 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
3600 /* add remote vtep as a neigh entry */
3601 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
3602 struct ethaddr
*rmac
,
3603 struct prefix
*host_prefix
)
3605 char buf
[ETHER_ADDR_STRLEN
];
3606 char buf1
[INET6_ADDRSTRLEN
];
3607 zebra_neigh_t
*nh
= NULL
;
3609 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3611 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
3615 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
3616 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
3617 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3622 /* install the nh neigh in kernel */
3623 zl3vni_nh_install(zl3vni
, nh
);
3626 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
3631 /* handle nh neigh delete */
3632 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
3633 struct prefix
*host_prefix
)
3635 rb_delete_host(&nh
->host_rb
, host_prefix
);
3637 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
3638 /* uninstall from kernel */
3639 zl3vni_nh_uninstall(zl3vni
, nh
);
3641 /* delete the nh entry */
3642 zl3vni_nh_del(zl3vni
, nh
);
3646 /* handle neigh update from kernel - the only thing of interest is to
3647 * readd stale entries.
3649 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3653 zebra_neigh_t
*n
= NULL
;
3655 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3659 /* all next hop neigh are remote and installed by frr.
3660 * If the kernel has aged this entry, re-install.
3662 if (state
& NUD_STALE
)
3663 zl3vni_nh_install(zl3vni
, n
);
3668 /* handle neigh delete from kernel */
3669 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3671 zebra_neigh_t
*n
= NULL
;
3673 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3677 /* all next hop neigh are remote and installed by frr.
3678 * If we get an age out notification for these neigh entries, we have to
3681 zl3vni_nh_install(zl3vni
, n
);
3687 * Hash function for L3 VNI.
3689 static unsigned int l3vni_hash_keymake(void *p
)
3691 const zebra_l3vni_t
*zl3vni
= p
;
3693 return jhash_1word(zl3vni
->vni
, 0);
3697 * Compare 2 L3 VNI hash entries.
3699 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
3701 const zebra_l3vni_t
*zl3vni1
= p1
;
3702 const zebra_l3vni_t
*zl3vni2
= p2
;
3704 return (zl3vni1
->vni
== zl3vni2
->vni
);
3708 * Callback to allocate L3 VNI hash entry.
3710 static void *zl3vni_alloc(void *p
)
3712 zebra_l3vni_t
*zl3vni
= NULL
;
3713 const zebra_l3vni_t
*tmp_l3vni
= p
;
3715 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
3716 zl3vni
->vni
= tmp_l3vni
->vni
;
3717 return ((void *)zl3vni
);
3721 * Look up L3 VNI hash entry.
3723 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
3725 zebra_l3vni_t tmp_l3vni
;
3726 zebra_l3vni_t
*zl3vni
= NULL
;
3728 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
3729 tmp_l3vni
.vni
= vni
;
3730 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
3736 * Add L3 VNI hash entry.
3738 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
3740 zebra_l3vni_t tmp_zl3vni
;
3741 zebra_l3vni_t
*zl3vni
= NULL
;
3743 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
3744 tmp_zl3vni
.vni
= vni
;
3746 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
3749 zl3vni
->vrf_id
= vrf_id
;
3750 zl3vni
->svi_if
= NULL
;
3751 zl3vni
->vxlan_if
= NULL
;
3752 zl3vni
->l2vnis
= list_new();
3753 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
3755 /* Create hash table for remote RMAC */
3756 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
3757 "Zebra L3-VNI RMAC-Table");
3759 /* Create hash table for neighbors */
3760 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3761 "Zebra L3-VNI next-hop table");
3767 * Delete L3 VNI hash entry.
3769 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
3771 zebra_l3vni_t
*tmp_zl3vni
;
3773 /* free the list of l2vnis */
3774 list_delete(&zl3vni
->l2vnis
);
3775 zl3vni
->l2vnis
= NULL
;
3777 /* Free the rmac table */
3778 hash_free(zl3vni
->rmac_table
);
3779 zl3vni
->rmac_table
= NULL
;
3781 /* Free the nh table */
3782 hash_free(zl3vni
->nh_table
);
3783 zl3vni
->nh_table
= NULL
;
3785 /* Free the VNI hash entry and allocated memory. */
3786 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
3788 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
3793 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
3795 struct zebra_ns
*zns
= NULL
;
3796 struct route_node
*rn
= NULL
;
3797 struct interface
*ifp
= NULL
;
3799 /* loop through all vxlan-interface */
3800 zns
= zebra_ns_lookup(NS_DEFAULT
);
3801 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3803 struct zebra_if
*zif
= NULL
;
3804 struct zebra_l2info_vxlan
*vxl
= NULL
;
3806 ifp
= (struct interface
*)rn
->info
;
3811 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3814 vxl
= &zif
->l2info
.vxl
;
3815 if (vxl
->vni
== zl3vni
->vni
) {
3816 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3824 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
3826 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
3827 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
3832 if (!zl3vni
->vxlan_if
)
3835 zif
= zl3vni
->vxlan_if
->info
;
3839 vxl
= &zif
->l2info
.vxl
;
3841 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3844 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
3846 struct zebra_vrf
*zvrf
= NULL
;
3848 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
3852 return zl3vni_lookup(zvrf
->l3vni
);
3856 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3857 * neighbor notifications, to see if they are of interest.
3859 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
3860 struct interface
*br_if
)
3864 uint8_t bridge_vlan_aware
= 0;
3865 zebra_l3vni_t
*zl3vni
= NULL
;
3866 struct zebra_ns
*zns
= NULL
;
3867 struct route_node
*rn
= NULL
;
3868 struct zebra_if
*zif
= NULL
;
3869 struct interface
*tmp_if
= NULL
;
3870 struct zebra_l2info_bridge
*br
= NULL
;
3871 struct zebra_l2info_vxlan
*vxl
= NULL
;
3876 /* Make sure the linked interface is a bridge. */
3877 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3880 /* Determine if bridge is VLAN-aware or not */
3883 br
= &zif
->l2info
.br
;
3884 bridge_vlan_aware
= br
->vlan_aware
;
3885 if (bridge_vlan_aware
) {
3886 struct zebra_l2info_vlan
*vl
;
3888 if (!IS_ZEBRA_IF_VLAN(ifp
))
3893 vl
= &zif
->l2info
.vl
;
3897 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3898 /* TODO: Optimize with a hash. */
3899 zns
= zebra_ns_lookup(NS_DEFAULT
);
3900 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3901 tmp_if
= (struct interface
*)rn
->info
;
3905 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3907 if (!if_is_operative(tmp_if
))
3909 vxl
= &zif
->l2info
.vxl
;
3911 if (zif
->brslave_info
.br_if
!= br_if
)
3914 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3923 zl3vni
= zl3vni_lookup(vxl
->vni
);
3928 * Inform BGP about l3-vni.
3930 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
3932 struct stream
*s
= NULL
;
3933 struct zserv
*client
= NULL
;
3934 struct ethaddr rmac
;
3935 char buf
[ETHER_ADDR_STRLEN
];
3937 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3938 /* BGP may not be running. */
3943 memset(&rmac
, 0, sizeof(struct ethaddr
));
3944 zl3vni_get_rmac(zl3vni
, &rmac
);
3946 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3948 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
3949 stream_putl(s
, zl3vni
->vni
);
3950 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
3951 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
3952 stream_put(s
, &zl3vni
->filter
, sizeof(int));
3954 /* Write packet size. */
3955 stream_putw_at(s
, 0, stream_get_endp(s
));
3957 if (IS_ZEBRA_DEBUG_VXLAN
)
3959 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
3960 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3961 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
3962 inet_ntoa(zl3vni
->local_vtep_ip
),
3963 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
3964 ? "prefix-routes-only"
3966 zebra_route_string(client
->proto
));
3968 client
->l3vniadd_cnt
++;
3969 return zserv_send_message(client
, s
);
3973 * Inform BGP about local l3-VNI deletion.
3975 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
3977 struct stream
*s
= NULL
;
3978 struct zserv
*client
= NULL
;
3980 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3981 /* BGP may not be running. */
3985 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3987 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
3988 stream_putl(s
, zl3vni
->vni
);
3990 /* Write packet size. */
3991 stream_putw_at(s
, 0, stream_get_endp(s
));
3993 if (IS_ZEBRA_DEBUG_VXLAN
)
3994 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
3995 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3996 zebra_route_string(client
->proto
));
3998 client
->l3vnidel_cnt
++;
3999 return zserv_send_message(client
, s
);
4002 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
4007 /* send l3vni add to BGP */
4008 zl3vni_send_add_to_client(zl3vni
);
4011 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
4016 /* send l3-vni del to BGP*/
4017 zl3vni_send_del_to_client(zl3vni
);
4020 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
, void *ctxt
)
4022 zebra_vni_t
*zvni
= (zebra_vni_t
*)backet
->data
;
4023 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
4025 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
4026 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4030 * handle transition of vni from l2 to l3 and vice versa
4032 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
4035 zebra_vni_t
*zvni
= NULL
;
4037 /* There is a possibility that VNI notification was already received
4038 * from kernel and we programmed it as L2-VNI
4039 * In such a case we need to delete this L2-VNI first, so
4040 * that it can be reprogrammed as L3-VNI in the system. It is also
4041 * possible that the vrf-vni mapping is removed from FRR while the vxlan
4042 * interface is still present in kernel. In this case to keep it
4043 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
4046 /* Locate hash entry */
4047 zvni
= zvni_lookup(vni
);
4051 if (IS_ZEBRA_DEBUG_VXLAN
)
4052 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
4054 /* Delete VNI from BGP. */
4055 zvni_send_del_to_client(zvni
->vni
);
4057 /* Free up all neighbors and MAC, if any. */
4058 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
4059 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
4061 /* Free up all remote VTEPs, if any. */
4062 zvni_vtep_del_all(zvni
, 0);
4064 /* Delete the hash entry. */
4065 if (zvni_del(zvni
)) {
4066 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
4067 "Failed to del VNI hash %p, VNI %u", zvni
,
4072 /* TODO_MITESH: This needs to be thought through. We don't have
4073 * enough information at this point to reprogram the vni as
4074 * l2-vni. One way is to store the required info in l3-vni and
4075 * used it solely for this purpose
4082 /* delete and uninstall rmac hash entry */
4083 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
, void *ctx
)
4085 zebra_mac_t
*zrmac
= NULL
;
4086 zebra_l3vni_t
*zl3vni
= NULL
;
4088 zrmac
= (zebra_mac_t
*)backet
->data
;
4089 zl3vni
= (zebra_l3vni_t
*)ctx
;
4090 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4091 zl3vni_rmac_del(zl3vni
, zrmac
);
4094 /* delete and uninstall nh hash entry */
4095 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
, void *ctx
)
4097 zebra_neigh_t
*n
= NULL
;
4098 zebra_l3vni_t
*zl3vni
= NULL
;
4100 n
= (zebra_neigh_t
*)backet
->data
;
4101 zl3vni
= (zebra_l3vni_t
*)ctx
;
4102 zl3vni_nh_uninstall(zl3vni
, n
);
4103 zl3vni_nh_del(zl3vni
, n
);
4106 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
4109 struct zserv
*client
= NULL
;
4110 struct stream
*s
= NULL
;
4111 char buf
[PREFIX_STRLEN
];
4113 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4114 /* BGP may not be running. */
4118 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4120 zclient_create_header(s
, cmd
, vrf_id
);
4121 stream_put(s
, p
, sizeof(struct prefix
));
4123 /* Write packet size. */
4124 stream_putw_at(s
, 0, stream_get_endp(s
));
4126 if (IS_ZEBRA_DEBUG_VXLAN
)
4127 zlog_debug("Send ip prefix %s %s on vrf %s",
4128 prefix2str(p
, buf
, sizeof(buf
)),
4129 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
4130 vrf_id_to_name(vrf_id
));
4132 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
4133 client
->prefixadd_cnt
++;
4135 client
->prefixdel_cnt
++;
4137 return zserv_send_message(client
, s
);
4140 /* re-add remote rmac if needed */
4141 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
4142 struct ethaddr
*rmac
)
4144 char buf
[ETHER_ADDR_STRLEN
];
4145 zebra_mac_t
*zrmac
= NULL
;
4147 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4151 if (IS_ZEBRA_DEBUG_VXLAN
)
4152 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
4153 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
4155 zl3vni_rmac_install(zl3vni
, zrmac
);
4159 /* Process a remote MACIP add from BGP. */
4160 static void process_remote_macip_add(vni_t vni
,
4161 struct ethaddr
*macaddr
,
4163 struct ipaddr
*ipaddr
,
4166 struct in_addr vtep_ip
)
4169 zebra_vtep_t
*zvtep
;
4170 zebra_mac_t
*mac
, *old_mac
;
4171 zebra_neigh_t
*n
= NULL
;
4172 int update_mac
= 0, update_neigh
= 0;
4173 char buf
[ETHER_ADDR_STRLEN
];
4174 char buf1
[INET6_ADDRSTRLEN
];
4175 struct interface
*ifp
= NULL
;
4176 struct zebra_if
*zif
= NULL
;
4182 /* Locate VNI hash entry - expected to exist. */
4183 zvni
= zvni_lookup(vni
);
4185 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
4189 ifp
= zvni
->vxlan_if
;
4193 !if_is_operative(ifp
) ||
4195 !zif
->brslave_info
.br_if
) {
4196 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
4201 /* The remote VTEP specified should normally exist, but it is
4202 * possible that when peering comes up, peer may advertise MACIP
4203 * routes before advertising type-3 routes.
4205 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
4207 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
4209 EC_ZEBRA_VTEP_ADD_FAILED
,
4210 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
4215 zvni_vtep_install(zvni
, &vtep_ip
);
4218 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
4219 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
4220 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
4222 mac
= zvni_mac_lookup(zvni
, macaddr
);
4224 /* Ignore if the mac is already present as a gateway mac */
4226 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
4227 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
4228 if (IS_ZEBRA_DEBUG_VXLAN
)
4229 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
4231 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4232 ipa_len
? " IP " : "",
4234 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
4238 /* check if the remote MAC is unknown or has a change.
4239 * If so, that needs to be updated first. Note that client could
4240 * install MAC and MACIP separately or just install the latter.
4243 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
4244 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
4245 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
4246 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
4247 || seq
!= mac
->rem_seq
)
4252 mac
= zvni_mac_add(zvni
, macaddr
);
4255 "Failed to add MAC %s VNI %u Remote VTEP %s",
4256 prefix_mac2str(macaddr
, buf
,
4258 vni
, inet_ntoa(vtep_ip
));
4262 /* Is this MAC created for a MACIP? */
4264 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
4266 const char *mac_type
;
4268 /* When host moves but changes its (MAC,IP)
4269 * binding, BGP may install a MACIP entry that
4270 * corresponds to "older" location of the host
4271 * in transient situations (because {IP1,M1}
4272 * is a different route from {IP1,M2}). Check
4273 * the sequence number and ignore this update
4276 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
4277 tmp_seq
= mac
->loc_seq
;
4280 tmp_seq
= mac
->rem_seq
;
4281 mac_type
= "remote";
4283 if (seq
< tmp_seq
) {
4284 if (IS_ZEBRA_DEBUG_VXLAN
)
4285 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
4287 prefix_mac2str(macaddr
,
4289 ipa_len
? " IP " : "",
4292 buf1
, sizeof(buf1
)) : "",
4299 /* Remove local MAC from BGP. */
4300 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
4301 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
4303 /* Set "auto" and "remote" forwarding info. */
4304 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
4305 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
4306 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
4307 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
4310 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
4312 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
4315 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
4317 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
4319 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
4321 /* Install the entry. */
4322 zvni_mac_install(zvni
, mac
);
4326 /* Update seq number. */
4329 /* If there is no IP, return after clearing AUTO flag of MAC. */
4331 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
4335 /* Check if the remote neighbor itself is unknown or has a
4336 * change. If so, create or update and then install the entry.
4338 n
= zvni_neigh_lookup(zvni
, ipaddr
);
4340 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
4341 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
4342 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
4343 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
4344 || seq
!= n
->rem_seq
)
4349 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
4352 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
4353 ipaddr2str(ipaddr
, buf1
,
4355 prefix_mac2str(macaddr
, buf
,
4357 vni
, inet_ntoa(vtep_ip
));
4364 /* When host moves but changes its (MAC,IP)
4365 * binding, BGP may install a MACIP entry that
4366 * corresponds to "older" location of the host
4367 * in transient situations (because {IP1,M1}
4368 * is a different route from {IP1,M2}). Check
4369 * the sequence number and ignore this update
4372 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
4373 tmp_seq
= n
->loc_seq
;
4376 tmp_seq
= n
->rem_seq
;
4379 if (seq
< tmp_seq
) {
4380 if (IS_ZEBRA_DEBUG_VXLAN
)
4381 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
4383 prefix_mac2str(macaddr
,
4386 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
4391 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
4392 /* MAC change, send a delete for old
4393 * neigh if learnt locally.
4395 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
4396 IS_ZEBRA_NEIGH_ACTIVE(n
))
4397 zvni_neigh_send_del_to_client(
4401 /* update neigh list for macs */
4402 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
4404 listnode_delete(old_mac
->neigh_list
, n
);
4405 zvni_deref_ip2mac(zvni
, old_mac
);
4407 listnode_add_sort(mac
->neigh_list
, n
);
4408 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
4412 /* Set "remote" forwarding info. */
4413 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
4414 n
->r_vtep_ip
= vtep_ip
;
4415 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4417 /* Set router flag (R-bit) to this Neighbor entry */
4418 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
4419 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
4421 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
4423 /* Install the entry. */
4424 zvni_neigh_install(zvni
, n
);
4427 /* Update seq number. */
4431 /* Process a remote MACIP delete from BGP. */
4432 static void process_remote_macip_del(vni_t vni
,
4433 struct ethaddr
*macaddr
,
4435 struct ipaddr
*ipaddr
,
4436 struct in_addr vtep_ip
)
4439 zebra_mac_t
*mac
= NULL
;
4440 zebra_neigh_t
*n
= NULL
;
4441 struct interface
*ifp
= NULL
;
4442 struct zebra_if
*zif
= NULL
;
4443 char buf
[ETHER_ADDR_STRLEN
];
4444 char buf1
[INET6_ADDRSTRLEN
];
4446 /* Locate VNI hash entry - expected to exist. */
4447 zvni
= zvni_lookup(vni
);
4449 if (IS_ZEBRA_DEBUG_VXLAN
)
4450 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
4454 ifp
= zvni
->vxlan_if
;
4458 !if_is_operative(ifp
) ||
4460 !zif
->brslave_info
.br_if
) {
4461 if (IS_ZEBRA_DEBUG_VXLAN
)
4462 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
4467 /* The remote VTEP specified is normally expected to exist, but
4468 * it is possible that the peer may delete the VTEP before deleting
4469 * any MACs referring to the VTEP, in which case the handler (see
4470 * remote_vtep_del) would have already deleted the MACs.
4472 if (!zvni_vtep_find(zvni
, &vtep_ip
))
4475 mac
= zvni_mac_lookup(zvni
, macaddr
);
4477 n
= zvni_neigh_lookup(zvni
, ipaddr
);
4480 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
4481 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4482 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
4486 /* If the remote mac or neighbor doesn't exist there is nothing
4487 * more to do. Otherwise, uninstall the entry and then remove it.
4492 /* Ignore the delete if this mac is a gateway mac-ip */
4494 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
4495 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
4497 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
4499 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4500 ipa_len
? " IP " : "",
4502 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
4506 /* Uninstall remote neighbor or MAC. */
4508 /* When the MAC changes for an IP, it is possible the
4509 * client may update the new MAC before trying to delete the
4510 * "old" neighbor (as these are two different MACIP routes).
4511 * Do the delete only if the MAC matches.
4513 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
4514 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
4515 zvni_neigh_uninstall(zvni
, n
);
4516 zvni_neigh_del(zvni
, n
);
4517 zvni_deref_ip2mac(zvni
, mac
);
4520 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
4521 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
4523 * the remote sequence number in the auto mac entry
4524 * needs to be reset to 0 as the mac entry may have
4525 * been removed on all VTEPs (including
4526 * the originating one)
4530 /* If all remote neighbors referencing a remote MAC
4531 * go away, we need to uninstall the MAC.
4533 if (remote_neigh_count(mac
) == 0) {
4534 zvni_mac_uninstall(zvni
, mac
);
4535 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
4537 if (list_isempty(mac
->neigh_list
))
4538 zvni_mac_del(zvni
, mac
);
4540 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
4546 /* Public functions */
4548 int is_l3vni_for_prefix_routes_only(vni_t vni
)
4550 zebra_l3vni_t
*zl3vni
= NULL
;
4552 zl3vni
= zl3vni_lookup(vni
);
4556 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
4559 /* handle evpn route in vrf table */
4560 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
4561 struct ipaddr
*vtep_ip
,
4562 struct prefix
*host_prefix
)
4564 zebra_l3vni_t
*zl3vni
= NULL
;
4565 struct ipaddr ipv4_vtep
;
4567 zl3vni
= zl3vni_from_vrf(vrf_id
);
4568 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
4572 * add the next hop neighbor -
4573 * neigh to be installed is the ipv6 nexthop neigh
4575 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
4578 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
4579 * address. Rmac is programmed against the ipv4 vtep because we only
4580 * support ipv4 tunnels in the h/w right now
4582 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
4583 ipv4_vtep
.ipa_type
= IPADDR_V4
;
4584 if (vtep_ip
->ipa_type
== IPADDR_V6
)
4585 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
4586 &(ipv4_vtep
.ipaddr_v4
));
4588 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
4589 sizeof(struct in_addr
));
4592 * add the rmac - remote rmac to be installed is against the ipv4
4595 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
4598 /* handle evpn vrf route delete */
4599 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
4600 struct ipaddr
*vtep_ip
,
4601 struct prefix
*host_prefix
)
4603 zebra_l3vni_t
*zl3vni
= NULL
;
4604 zebra_neigh_t
*nh
= NULL
;
4605 zebra_mac_t
*zrmac
= NULL
;
4607 zl3vni
= zl3vni_from_vrf(vrf_id
);
4611 /* find the next hop entry and rmac entry */
4612 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4615 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
4617 /* delete the next hop entry */
4618 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
4620 /* delete the rmac entry */
4622 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
4626 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
4627 struct ethaddr
*rmac
, bool use_json
)
4629 zebra_l3vni_t
*zl3vni
= NULL
;
4630 zebra_mac_t
*zrmac
= NULL
;
4631 json_object
*json
= NULL
;
4633 if (!is_evpn_enabled()) {
4635 vty_out(vty
, "{}\n");
4640 json
= json_object_new_object();
4642 zl3vni
= zl3vni_lookup(l3vni
);
4645 vty_out(vty
, "{}\n");
4647 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
4651 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4654 vty_out(vty
, "{}\n");
4657 "%% Requested RMAC doesn't exist in L3-VNI %u",
4662 zl3vni_print_rmac(zrmac
, vty
, json
);
4665 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4666 json
, JSON_C_TO_STRING_PRETTY
));
4667 json_object_free(json
);
4671 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
4673 zebra_l3vni_t
*zl3vni
;
4675 struct rmac_walk_ctx wctx
;
4676 json_object
*json
= NULL
;
4678 if (!is_evpn_enabled())
4681 zl3vni
= zl3vni_lookup(l3vni
);
4684 vty_out(vty
, "{}\n");
4686 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4689 num_rmacs
= hashcount(zl3vni
->rmac_table
);
4694 json
= json_object_new_object();
4696 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
4700 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
4702 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
4704 json_object_int_add(json
, "numRmacs", num_rmacs
);
4706 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
4709 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4710 json
, JSON_C_TO_STRING_PRETTY
));
4711 json_object_free(json
);
4715 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
4717 json_object
*json
= NULL
;
4720 if (!is_evpn_enabled()) {
4722 vty_out(vty
, "{}\n");
4727 json
= json_object_new_object();
4731 hash_iterate(zrouter
.l3vni_table
,
4732 (void (*)(struct hash_backet
*,
4733 void *))zl3vni_print_rmac_hash_all_vni
,
4737 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4738 json
, JSON_C_TO_STRING_PRETTY
));
4739 json_object_free(json
);
4743 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
4744 struct ipaddr
*ip
, bool use_json
)
4746 zebra_l3vni_t
*zl3vni
= NULL
;
4747 zebra_neigh_t
*n
= NULL
;
4748 json_object
*json
= NULL
;
4750 if (!is_evpn_enabled()) {
4752 vty_out(vty
, "{}\n");
4757 json
= json_object_new_object();
4759 zl3vni
= zl3vni_lookup(l3vni
);
4762 vty_out(vty
, "{}\n");
4764 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4768 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4771 vty_out(vty
, "{}\n");
4774 "%% Requested next-hop not present for L3-VNI %u",
4779 zl3vni_print_nh(n
, vty
, json
);
4782 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4783 json
, JSON_C_TO_STRING_PRETTY
));
4784 json_object_free(json
);
4788 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
4791 struct nh_walk_ctx wctx
;
4792 json_object
*json
= NULL
;
4793 zebra_l3vni_t
*zl3vni
= NULL
;
4795 if (!is_evpn_enabled())
4798 zl3vni
= zl3vni_lookup(l3vni
);
4801 vty_out(vty
, "{}\n");
4803 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4807 num_nh
= hashcount(zl3vni
->nh_table
);
4812 json
= json_object_new_object();
4817 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
4819 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
4821 json_object_int_add(json
, "numNextHops", num_nh
);
4823 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
4826 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4827 json
, JSON_C_TO_STRING_PRETTY
));
4828 json_object_free(json
);
4832 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
4834 json_object
*json
= NULL
;
4837 if (!is_evpn_enabled()) {
4839 vty_out(vty
, "{}\n");
4844 json
= json_object_new_object();
4848 hash_iterate(zrouter
.l3vni_table
,
4849 (void (*)(struct hash_backet
*,
4850 void *))zl3vni_print_nh_hash_all_vni
,
4854 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4855 json
, JSON_C_TO_STRING_PRETTY
));
4856 json_object_free(json
);
4861 * Display L3 VNI information (VTY command handler).
4863 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
4866 json_object
*json
= NULL
;
4867 zebra_l3vni_t
*zl3vni
= NULL
;
4869 if (!is_evpn_enabled()) {
4871 vty_out(vty
, "{}\n");
4875 zl3vni
= zl3vni_lookup(vni
);
4878 vty_out(vty
, "{}\n");
4880 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4885 json
= json_object_new_object();
4889 zl3vni_print(zl3vni
, (void *)args
);
4892 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4893 json
, JSON_C_TO_STRING_PRETTY
));
4894 json_object_free(json
);
4898 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4899 json_object
*json_vrfs
)
4901 char buf
[ETHER_ADDR_STRLEN
];
4902 zebra_l3vni_t
*zl3vni
= NULL
;
4904 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4909 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
4910 zvrf_name(zvrf
), zl3vni
->vni
,
4911 zl3vni_vxlan_if_name(zl3vni
),
4912 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
4913 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4915 json_object
*json_vrf
= NULL
;
4917 json_vrf
= json_object_new_object();
4918 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
4919 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
4920 json_object_string_add(json_vrf
, "vxlanIntf",
4921 zl3vni_vxlan_if_name(zl3vni
));
4922 json_object_string_add(json_vrf
, "sviIntf",
4923 zl3vni_svi_if_name(zl3vni
));
4924 json_object_string_add(json_vrf
, "state",
4925 zl3vni_state2str(zl3vni
));
4926 json_object_string_add(
4927 json_vrf
, "routerMac",
4928 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4929 json_object_array_add(json_vrfs
, json_vrf
);
4934 * Display Neighbors for a VNI (VTY command handler).
4936 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4937 vni_t vni
, bool use_json
)
4941 struct neigh_walk_ctx wctx
;
4942 json_object
*json
= NULL
;
4944 if (!is_evpn_enabled())
4946 zvni
= zvni_lookup(vni
);
4949 vty_out(vty
, "{}\n");
4951 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4954 num_neigh
= hashcount(zvni
->neigh_table
);
4959 json
= json_object_new_object();
4961 /* Since we have IPv6 addresses to deal with which can vary widely in
4962 * size, we try to be a bit more elegant in display by first computing
4963 * the maximum width.
4965 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4968 wctx
.addr_width
= 15;
4970 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4974 "Number of ARPs (local and remote) known for this VNI: %u\n",
4976 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
4977 -wctx
.addr_width
, "IP", "Type",
4978 "State", "MAC", "Remote VTEP");
4980 json_object_int_add(json
, "numArpNd", num_neigh
);
4982 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4984 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4985 json
, JSON_C_TO_STRING_PRETTY
));
4986 json_object_free(json
);
4991 * Display neighbors across all VNIs (VTY command handler).
4993 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4996 json_object
*json
= NULL
;
4999 if (!is_evpn_enabled())
5003 json
= json_object_new_object();
5007 hash_iterate(zvrf
->vni_table
,
5008 (void (*)(struct hash_backet
*,
5009 void *))zvni_print_neigh_hash_all_vni
,
5012 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5013 json
, JSON_C_TO_STRING_PRETTY
));
5014 json_object_free(json
);
5019 * Display specific neighbor for a VNI, if present (VTY command handler).
5021 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
5022 struct zebra_vrf
*zvrf
, vni_t vni
,
5023 struct ipaddr
*ip
, bool use_json
)
5027 json_object
*json
= NULL
;
5029 if (!is_evpn_enabled())
5031 zvni
= zvni_lookup(vni
);
5034 vty_out(vty
, "{}\n");
5036 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5039 n
= zvni_neigh_lookup(zvni
, ip
);
5043 "%% Requested neighbor does not exist in VNI %u\n",
5048 json
= json_object_new_object();
5050 zvni_print_neigh(n
, vty
, json
);
5053 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5054 json
, JSON_C_TO_STRING_PRETTY
));
5055 json_object_free(json
);
5060 * Display neighbors for a VNI from specific VTEP (VTY command handler).
5061 * By definition, these are remote neighbors.
5063 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5064 vni_t vni
, struct in_addr vtep_ip
,
5069 struct neigh_walk_ctx wctx
;
5070 json_object
*json
= NULL
;
5072 if (!is_evpn_enabled())
5074 zvni
= zvni_lookup(vni
);
5077 vty_out(vty
, "{}\n");
5079 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5082 num_neigh
= hashcount(zvni
->neigh_table
);
5086 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
5089 wctx
.addr_width
= 15;
5090 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
5091 wctx
.r_vtep_ip
= vtep_ip
;
5093 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
5094 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
5097 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5098 json
, JSON_C_TO_STRING_PRETTY
));
5099 json_object_free(json
);
5104 * Display MACs for a VNI (VTY command handler).
5106 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5107 vni_t vni
, bool use_json
)
5111 struct mac_walk_ctx wctx
;
5112 json_object
*json
= NULL
;
5113 json_object
*json_mac
= NULL
;
5115 if (!is_evpn_enabled())
5117 zvni
= zvni_lookup(vni
);
5120 vty_out(vty
, "{}\n");
5122 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5125 num_macs
= num_valid_macs(zvni
);
5130 json
= json_object_new_object();
5131 json_mac
= json_object_new_object();
5134 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5137 wctx
.json
= json_mac
;
5141 "Number of MACs (local and remote) known for this VNI: %u\n",
5143 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
5144 "Intf/Remote VTEP", "VLAN");
5146 json_object_int_add(json
, "numMacs", num_macs
);
5148 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
5151 json_object_object_add(json
, "macs", json_mac
);
5152 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5153 json
, JSON_C_TO_STRING_PRETTY
));
5154 json_object_free(json
);
5159 * Display MACs for all VNIs (VTY command handler).
5161 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5164 struct mac_walk_ctx wctx
;
5165 json_object
*json
= NULL
;
5167 if (!is_evpn_enabled()) {
5169 vty_out(vty
, "{}\n");
5173 json
= json_object_new_object();
5175 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5178 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
5181 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5182 json
, JSON_C_TO_STRING_PRETTY
));
5183 json_object_free(json
);
5188 * Display MACs for all VNIs (VTY command handler).
5190 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
5191 struct zebra_vrf
*zvrf
,
5192 struct in_addr vtep_ip
, bool use_json
)
5194 struct mac_walk_ctx wctx
;
5195 json_object
*json
= NULL
;
5197 if (!is_evpn_enabled())
5201 json
= json_object_new_object();
5203 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5205 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
5206 wctx
.r_vtep_ip
= vtep_ip
;
5208 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
5211 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5212 json
, JSON_C_TO_STRING_PRETTY
));
5213 json_object_free(json
);
5218 * Display specific MAC for a VNI, if present (VTY command handler).
5220 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5221 vni_t vni
, struct ethaddr
*macaddr
,
5226 json_object
*json
= NULL
;
5228 if (!is_evpn_enabled())
5231 zvni
= zvni_lookup(vni
);
5234 vty_out(vty
, "{}\n");
5236 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5239 mac
= zvni_mac_lookup(zvni
, macaddr
);
5242 vty_out(vty
, "{}\n");
5245 "%% Requested MAC does not exist in VNI %u\n",
5251 json
= json_object_new_object();
5253 zvni_print_mac(mac
, vty
, json
);
5257 * Display MACs for a VNI from specific VTEP (VTY command handler).
5259 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5260 vni_t vni
, struct in_addr vtep_ip
,
5265 struct mac_walk_ctx wctx
;
5266 json_object
*json
= NULL
;
5267 json_object
*json_mac
= NULL
;
5269 if (!is_evpn_enabled())
5271 zvni
= zvni_lookup(vni
);
5274 vty_out(vty
, "{}\n");
5276 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5279 num_macs
= num_valid_macs(zvni
);
5284 json
= json_object_new_object();
5285 json_mac
= json_object_new_object();
5288 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5291 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
5292 wctx
.r_vtep_ip
= vtep_ip
;
5293 wctx
.json
= json_mac
;
5294 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
5297 json_object_int_add(json
, "numMacs", wctx
.count
);
5299 json_object_object_add(json
, "macs", json_mac
);
5300 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5301 json
, JSON_C_TO_STRING_PRETTY
));
5302 json_object_free(json
);
5308 * Display VNI information (VTY command handler).
5310 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
5313 json_object
*json
= NULL
;
5315 zebra_l3vni_t
*zl3vni
= NULL
;
5316 zebra_vni_t
*zvni
= NULL
;
5318 if (!is_evpn_enabled())
5322 json
= json_object_new_object();
5326 zl3vni
= zl3vni_lookup(vni
);
5328 zl3vni_print(zl3vni
, (void *)args
);
5330 zvni
= zvni_lookup(vni
);
5333 vty_out(vty
, "{}\n");
5335 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5339 zvni_print(zvni
, (void *)args
);
5343 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5344 json
, JSON_C_TO_STRING_PRETTY
));
5345 json_object_free(json
);
5349 /* Display all global details for EVPN */
5350 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
5355 json_object
*json
= NULL
;
5356 struct zebra_vrf
*zvrf
= NULL
;
5358 if (!is_evpn_enabled())
5361 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
5365 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
5366 num_l2vnis
= hashcount(zvrf
->vni_table
);
5367 num_vnis
= num_l2vnis
+ num_l3vnis
;
5370 json
= json_object_new_object();
5371 json_object_string_add(json
, "advertiseGatewayMacip",
5372 zvrf
->advertise_gw_macip
? "Yes" : "No");
5373 json_object_int_add(json
, "numVnis", num_vnis
);
5374 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
5375 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
5377 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
5378 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
5379 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
5380 zvrf
->advertise_gw_macip
? "Yes" : "No");
5384 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5385 json
, JSON_C_TO_STRING_PRETTY
));
5386 json_object_free(json
);
5391 * Display VNI hash table (VTY command handler).
5393 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5396 json_object
*json
= NULL
;
5399 if (!is_evpn_enabled())
5403 json
= json_object_new_object();
5405 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
5406 "Type", "VxLAN IF", "# MACs", "# ARPs",
5407 "# Remote VTEPs", "Tenant VRF");
5412 /* Display all L2-VNIs */
5413 hash_iterate(zvrf
->vni_table
,
5414 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
5417 /* Display all L3-VNIs */
5418 hash_iterate(zrouter
.l3vni_table
,
5419 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
5423 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5424 json
, JSON_C_TO_STRING_PRETTY
));
5425 json_object_free(json
);
5430 * Handle neighbor delete notification from the kernel (on a VLAN device
5431 * / L3 interface). This may result in either the neighbor getting deleted
5432 * from our database or being re-added to the kernel (if it is a valid
5435 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
5436 struct interface
*link_if
,
5439 char buf
[INET6_ADDRSTRLEN
];
5440 char buf2
[ETHER_ADDR_STRLEN
];
5441 zebra_neigh_t
*n
= NULL
;
5442 zebra_vni_t
*zvni
= NULL
;
5443 zebra_mac_t
*zmac
= NULL
;
5444 zebra_l3vni_t
*zl3vni
= NULL
;
5446 /* check if this is a remote neigh entry corresponding to remote
5449 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5451 return zl3vni_local_nh_del(zl3vni
, ip
);
5453 /* We are only interested in neighbors on an SVI that resides on top
5454 * of a VxLAN bridge.
5456 zvni
= zvni_from_svi(ifp
, link_if
);
5460 if (!zvni
->vxlan_if
) {
5462 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
5467 if (IS_ZEBRA_DEBUG_VXLAN
)
5468 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
5469 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
5470 ifp
->ifindex
, zvni
->vni
);
5472 /* If entry doesn't exist, nothing to do. */
5473 n
= zvni_neigh_lookup(zvni
, ip
);
5477 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
5479 if (IS_ZEBRA_DEBUG_VXLAN
)
5481 "Trying to del a neigh %s without a mac %s on VNI %u",
5482 ipaddr2str(ip
, buf
, sizeof(buf
)),
5483 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
5489 /* If it is a remote entry, the kernel has aged this out or someone has
5490 * deleted it, it needs to be re-installed as Quagga is the owner.
5492 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
5493 zvni_neigh_install(zvni
, n
);
5497 /* Remove neighbor from BGP. */
5498 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
5499 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0);
5501 /* Delete this neighbor entry. */
5502 zvni_neigh_del(zvni
, n
);
5504 /* see if the AUTO mac needs to be deleted */
5505 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
5506 && !listcount(zmac
->neigh_list
))
5507 zvni_mac_del(zvni
, zmac
);
5513 * Handle neighbor add or update notification from the kernel (on a VLAN
5514 * device / L3 interface). This is typically for a local neighbor but can
5515 * also be for a remote neighbor (e.g., ageout notification). It could
5516 * also be a "move" scenario.
5518 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
5519 struct interface
*link_if
,
5521 struct ethaddr
*macaddr
,
5526 char buf
[ETHER_ADDR_STRLEN
];
5527 char buf2
[INET6_ADDRSTRLEN
];
5528 zebra_vni_t
*zvni
= NULL
;
5529 zebra_l3vni_t
*zl3vni
= NULL
;
5531 /* check if this is a remote neigh entry corresponding to remote
5534 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5536 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
5538 /* We are only interested in neighbors on an SVI that resides on top
5539 * of a VxLAN bridge.
5541 zvni
= zvni_from_svi(ifp
, link_if
);
5545 if (IS_ZEBRA_DEBUG_VXLAN
)
5547 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
5548 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
5549 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5550 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
5551 is_router
? "router " : "",
5554 /* Is this about a local neighbor or a remote one? */
5556 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
5559 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
5564 * Handle message from client to delete a remote MACIP for a VNI.
5566 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
5570 struct ethaddr macaddr
;
5572 struct in_addr vtep_ip
;
5573 uint16_t l
= 0, ipa_len
;
5574 char buf
[ETHER_ADDR_STRLEN
];
5575 char buf1
[INET6_ADDRSTRLEN
];
5577 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5578 memset(&ip
, 0, sizeof(struct ipaddr
));
5579 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5583 while (l
< hdr
->length
) {
5584 /* Obtain each remote MACIP and process. */
5585 /* Message contains VNI, followed by MAC followed by IP (if any)
5586 * followed by remote VTEP IP.
5588 memset(&ip
, 0, sizeof(ip
));
5589 STREAM_GETL(s
, vni
);
5590 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5591 STREAM_GETL(s
, ipa_len
);
5593 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5595 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5597 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5598 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5599 l
+= IPV4_MAX_BYTELEN
;
5601 if (IS_ZEBRA_DEBUG_VXLAN
)
5603 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
5605 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5606 ipa_len
? " IP " : "",
5608 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
5610 zebra_route_string(client
->proto
));
5612 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
5620 * Handle message from client to add a remote MACIP for a VNI. This
5621 * could be just the add of a MAC address or the add of a neighbor
5624 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
5628 struct ethaddr macaddr
;
5630 struct in_addr vtep_ip
;
5631 uint16_t l
= 0, ipa_len
;
5634 char buf
[ETHER_ADDR_STRLEN
];
5635 char buf1
[INET6_ADDRSTRLEN
];
5637 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5638 memset(&ip
, 0, sizeof(struct ipaddr
));
5639 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5641 if (!EVPN_ENABLED(zvrf
)) {
5642 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
5648 while (l
< hdr
->length
) {
5649 /* Obtain each remote MACIP and process. */
5650 /* Message contains VNI, followed by MAC followed by IP (if any)
5651 * followed by remote VTEP IP.
5653 memset(&ip
, 0, sizeof(ip
));
5654 STREAM_GETL(s
, vni
);
5655 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5656 STREAM_GETL(s
, ipa_len
);
5658 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5660 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5662 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5663 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5664 l
+= IPV4_MAX_BYTELEN
;
5666 /* Get flags - sticky mac and/or gateway mac */
5667 STREAM_GETC(s
, flags
);
5669 STREAM_GETL(s
, seq
);
5672 if (IS_ZEBRA_DEBUG_VXLAN
)
5674 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
5676 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5677 ipa_len
? " IP " : "",
5679 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
5680 flags
, seq
, inet_ntoa(vtep_ip
),
5681 zebra_route_string(client
->proto
));
5683 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
5684 flags
, seq
, vtep_ip
);
5692 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5693 * us, this must involve a multihoming scenario. Treat this as implicit delete
5694 * of any prior local MAC.
5696 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
5697 struct interface
*br_if
,
5698 struct ethaddr
*macaddr
, vlanid_t vid
)
5700 struct zebra_if
*zif
;
5701 struct zebra_l2info_vxlan
*vxl
;
5705 char buf
[ETHER_ADDR_STRLEN
];
5709 vxl
= &zif
->l2info
.vxl
;
5712 /* Check if EVPN is enabled. */
5713 if (!is_evpn_enabled())
5716 /* Locate hash entry; it is expected to exist. */
5717 zvni
= zvni_lookup(vni
);
5721 /* If entry doesn't exist, nothing to do. */
5722 mac
= zvni_mac_lookup(zvni
, macaddr
);
5726 /* Is it a local entry? */
5727 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5730 if (IS_ZEBRA_DEBUG_VXLAN
)
5732 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5733 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5736 /* Remove MAC from BGP. */
5737 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5740 * If there are no neigh associated with the mac delete the mac
5741 * else mark it as AUTO for forward reference
5743 if (!listcount(mac
->neigh_list
)) {
5744 zvni_mac_del(zvni
, mac
);
5746 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5747 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5754 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5755 * This can happen because the remote MAC entries are also added as "dynamic",
5756 * so the kernel can ageout the entry.
5758 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
5759 struct interface
*br_if
,
5760 struct ethaddr
*macaddr
, vlanid_t vid
)
5762 struct zebra_if
*zif
= NULL
;
5763 struct zebra_l2info_vxlan
*vxl
= NULL
;
5765 zebra_vni_t
*zvni
= NULL
;
5766 zebra_l3vni_t
*zl3vni
= NULL
;
5767 zebra_mac_t
*mac
= NULL
;
5768 char buf
[ETHER_ADDR_STRLEN
];
5772 vxl
= &zif
->l2info
.vxl
;
5775 /* Check if EVPN is enabled. */
5776 if (!is_evpn_enabled())
5779 /* check if this is a remote RMAC and readd simillar to remote macs */
5780 zl3vni
= zl3vni_lookup(vni
);
5782 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
5784 /* Locate hash entry; it is expected to exist. */
5785 zvni
= zvni_lookup(vni
);
5789 /* If entry doesn't exist, nothing to do. */
5790 mac
= zvni_mac_lookup(zvni
, macaddr
);
5794 /* Is it a remote entry? */
5795 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
5798 if (IS_ZEBRA_DEBUG_VXLAN
)
5799 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
5800 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5803 zvni_mac_install(zvni
, mac
);
5808 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
5810 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
5811 struct ethaddr
*macaddr
, vlanid_t vid
)
5815 char buf
[ETHER_ADDR_STRLEN
];
5817 /* We are interested in MACs only on ports or (port, VLAN) that
5820 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5823 if (!zvni
->vxlan_if
) {
5825 "VNI %u hash %p doesn't have intf upon local MAC DEL",
5830 if (IS_ZEBRA_DEBUG_VXLAN
)
5831 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
5832 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5833 ifp
->ifindex
, vid
, zvni
->vni
);
5835 /* If entry doesn't exist, nothing to do. */
5836 mac
= zvni_mac_lookup(zvni
, macaddr
);
5840 /* Is it a local entry? */
5841 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5844 /* Update all the neigh entries associated with this mac */
5845 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
5847 /* Remove MAC from BGP. */
5848 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5851 * If there are no neigh associated with the mac delete the mac
5852 * else mark it as AUTO for forward reference
5854 if (!listcount(mac
->neigh_list
)) {
5855 zvni_mac_del(zvni
, mac
);
5857 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5858 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5865 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
5867 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
5868 struct interface
*br_if
,
5869 struct ethaddr
*macaddr
, vlanid_t vid
,
5874 char buf
[ETHER_ADDR_STRLEN
];
5875 bool mac_sticky
= false;
5876 bool inform_client
= false;
5877 bool upd_neigh
= false;
5879 /* We are interested in MACs only on ports or (port, VLAN) that
5882 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5884 if (IS_ZEBRA_DEBUG_VXLAN
)
5886 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5887 sticky
? "sticky " : "",
5888 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5889 ifp
->name
, ifp
->ifindex
, vid
);
5893 if (!zvni
->vxlan_if
) {
5895 "VNI %u hash %p doesn't have intf upon local MAC ADD",
5900 /* Check if we need to create or update or it is a NO-OP. */
5901 mac
= zvni_mac_lookup(zvni
, macaddr
);
5903 if (IS_ZEBRA_DEBUG_VXLAN
)
5905 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
5906 sticky
? "sticky " : "",
5907 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5908 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
5910 mac
= zvni_mac_add(zvni
, macaddr
);
5913 EC_ZEBRA_MAC_ADD_FAILED
,
5914 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
5915 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5916 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
5919 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5920 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
5921 mac
->fwd_info
.local
.vid
= vid
;
5923 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5924 inform_client
= true;
5927 if (IS_ZEBRA_DEBUG_VXLAN
)
5929 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
5930 sticky
? "sticky " : "",
5931 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5932 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
5935 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5936 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
5940 * Update any changes and if changes are relevant to
5943 if (mac_sticky
== sticky
5944 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
5945 && mac
->fwd_info
.local
.vid
== vid
) {
5946 if (IS_ZEBRA_DEBUG_VXLAN
)
5948 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
5949 "entry exists and has not changed ",
5950 sticky
? "sticky " : "",
5951 prefix_mac2str(macaddr
, buf
,
5953 ifp
->name
, ifp
->ifindex
, vid
,
5957 if (mac_sticky
!= sticky
) {
5959 SET_FLAG(mac
->flags
,
5962 UNSET_FLAG(mac
->flags
,
5964 inform_client
= true;
5967 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5968 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
5969 mac
->fwd_info
.local
.vid
= vid
;
5971 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
5972 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
5975 * MAC has either moved or was "internally" created due
5976 * to a neighbor learn and is now actually learnt. If
5977 * it was learnt as a remote sticky MAC, this is an
5980 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
5982 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
5983 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
5984 prefix_mac2str(macaddr
, buf
,
5986 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
5991 /* If an actual move, compute MAC's seq number */
5992 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
5993 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
5995 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5996 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5997 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5998 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5999 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
6000 mac
->fwd_info
.local
.vid
= vid
;
6002 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
6004 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
6006 * We have to inform BGP of this MAC as well as process
6009 inform_client
= true;
6014 /* Inform BGP if required. */
6015 if (inform_client
) {
6016 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
6017 mac
->flags
, mac
->loc_seq
))
6021 /* Process all neighbors associated with this MAC, if required. */
6023 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6029 * Handle message from client to delete a remote VTEP for a VNI.
6031 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
6034 unsigned short l
= 0;
6036 struct in_addr vtep_ip
;
6038 zebra_vtep_t
*zvtep
;
6039 struct interface
*ifp
;
6040 struct zebra_if
*zif
;
6042 if (!is_evpn_enabled()) {
6044 "%s: EVPN is not enabled yet we have received a vtep del command",
6045 __PRETTY_FUNCTION__
);
6049 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6050 zlog_debug("Recv MACIP DEL for non-default VRF %u",
6057 while (l
< hdr
->length
) {
6058 /* Obtain each remote VTEP and process. */
6059 STREAM_GETL(s
, vni
);
6061 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
6062 l
+= IPV4_MAX_BYTELEN
;
6064 if (IS_ZEBRA_DEBUG_VXLAN
)
6065 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
6066 inet_ntoa(vtep_ip
), vni
,
6067 zebra_route_string(client
->proto
));
6069 /* Locate VNI hash entry - expected to exist. */
6070 zvni
= zvni_lookup(vni
);
6072 if (IS_ZEBRA_DEBUG_VXLAN
)
6074 "Failed to locate VNI hash upon remote VTEP DEL, "
6080 ifp
= zvni
->vxlan_if
;
6083 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
6089 /* If down or not mapped to a bridge, we're done. */
6090 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6093 /* If the remote VTEP does not exist, there's nothing more to
6095 * Otherwise, uninstall any remote MACs pointing to this VTEP
6097 * then, the VTEP entry itself and remove it.
6099 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
6103 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
6104 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
6105 zvni_vtep_uninstall(zvni
, &vtep_ip
);
6106 zvni_vtep_del(zvni
, zvtep
);
6114 * Handle message from client to add a remote VTEP for a VNI.
6116 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
6119 unsigned short l
= 0;
6121 struct in_addr vtep_ip
;
6123 struct interface
*ifp
;
6124 struct zebra_if
*zif
;
6126 if (!is_evpn_enabled()) {
6128 "%s: EVPN not enabled yet we received a vtep_add zapi call",
6129 __PRETTY_FUNCTION__
);
6133 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6134 zlog_debug("Recv MACIP ADD for non-default VRF %u",
6141 while (l
< hdr
->length
) {
6142 /* Obtain each remote VTEP and process. */
6143 STREAM_GETL(s
, vni
);
6145 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
6146 l
+= IPV4_MAX_BYTELEN
;
6148 if (IS_ZEBRA_DEBUG_VXLAN
)
6149 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
6150 inet_ntoa(vtep_ip
), vni
,
6151 zebra_route_string(client
->proto
));
6153 /* Locate VNI hash entry - expected to exist. */
6154 zvni
= zvni_lookup(vni
);
6157 EC_ZEBRA_VTEP_ADD_FAILED
,
6158 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
6163 ifp
= zvni
->vxlan_if
;
6166 EC_ZEBRA_VTEP_ADD_FAILED
,
6167 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
6174 /* If down or not mapped to a bridge, we're done. */
6175 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6178 /* If the remote VTEP already exists,
6179 there's nothing more to do. */
6180 if (zvni_vtep_find(zvni
, &vtep_ip
))
6183 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
6184 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
6185 "Failed to add remote VTEP, VNI %u zvni %p",
6190 zvni_vtep_install(zvni
, &vtep_ip
);
6198 * Add/Del gateway macip to evpn
6200 * 1. SVI interface on a vlan aware bridge
6201 * 2. SVI interface on a vlan unaware bridge
6202 * 3. vrr interface (MACVLAN) associated to a SVI
6203 * We advertise macip routes for an interface if it is associated to VxLan vlan
6205 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
6209 struct ethaddr macaddr
;
6210 zebra_vni_t
*zvni
= NULL
;
6212 memset(&ip
, 0, sizeof(struct ipaddr
));
6213 memset(&macaddr
, 0, sizeof(struct ethaddr
));
6215 /* Check if EVPN is enabled. */
6216 if (!is_evpn_enabled())
6219 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
6220 struct interface
*svi_if
=
6221 NULL
; /* SVI corresponding to the MACVLAN */
6222 struct zebra_if
*ifp_zif
=
6223 NULL
; /* Zebra daemon specific info for MACVLAN */
6224 struct zebra_if
*svi_if_zif
=
6225 NULL
; /* Zebra daemon specific info for SVI*/
6227 ifp_zif
= ifp
->info
;
6232 * for a MACVLAN interface the link represents the svi_if
6234 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
6235 ifp_zif
->link_ifindex
);
6237 zlog_debug("MACVLAN %s(%u) without link information",
6238 ifp
->name
, ifp
->ifindex
);
6242 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
6244 * If it is a vlan aware bridge then the link gives the
6245 * bridge information
6247 struct interface
*svi_if_link
= NULL
;
6249 svi_if_zif
= svi_if
->info
;
6251 svi_if_link
= if_lookup_by_index_per_ns(
6252 zebra_ns_lookup(NS_DEFAULT
),
6253 svi_if_zif
->link_ifindex
);
6254 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
6256 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
6258 * If it is a vlan unaware bridge then svi is the bridge
6261 zvni
= zvni_from_svi(svi_if
, svi_if
);
6263 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
6264 struct zebra_if
*svi_if_zif
=
6265 NULL
; /* Zebra daemon specific info for SVI */
6266 struct interface
*svi_if_link
=
6267 NULL
; /* link info for the SVI = bridge info */
6269 svi_if_zif
= ifp
->info
;
6271 svi_if_link
= if_lookup_by_index_per_ns(
6272 zebra_ns_lookup(NS_DEFAULT
),
6273 svi_if_zif
->link_ifindex
);
6275 zvni
= zvni_from_svi(ifp
, svi_if_link
);
6277 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
6278 zvni
= zvni_from_svi(ifp
, ifp
);
6284 if (!zvni
->vxlan_if
) {
6285 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
6291 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
6293 if (p
->family
== AF_INET
) {
6294 ip
.ipa_type
= IPADDR_V4
;
6295 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
6296 sizeof(struct in_addr
));
6297 } else if (p
->family
== AF_INET6
) {
6298 ip
.ipa_type
= IPADDR_V6
;
6299 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
6300 sizeof(struct in6_addr
));
6305 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
6307 zvni_gw_macip_del(ifp
, zvni
, &ip
);
6313 * Handle SVI interface going down.
6314 * SVI can be associated to either L3-VNI or L2-VNI.
6315 * For L2-VNI: At this point, this is a NOP since
6316 * the kernel deletes the neighbor entries on this SVI (if any).
6317 * We only need to update the vrf corresponding to zvni.
6318 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
6321 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
6323 zebra_l3vni_t
*zl3vni
= NULL
;
6325 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6328 /* process l3-vni down */
6329 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6331 /* remove association with svi-if */
6332 zl3vni
->svi_if
= NULL
;
6334 zebra_vni_t
*zvni
= NULL
;
6336 /* since we dont have svi corresponding to zvni, we associate it
6337 * to default vrf. Note: the corresponding neigh entries on the
6338 * SVI would have already been deleted */
6339 zvni
= zvni_from_svi(ifp
, link_if
);
6341 zvni
->vrf_id
= VRF_DEFAULT
;
6343 /* update the tenant vrf in BGP */
6344 zvni_send_add_to_client(zvni
);
6351 * Handle SVI interface coming up.
6352 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
6354 * For L2-VNI: we need to install any remote neighbors entried (used for
6356 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
6358 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
6360 zebra_vni_t
*zvni
= NULL
;
6361 zebra_l3vni_t
*zl3vni
= NULL
;
6363 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6366 /* associate with svi */
6367 zl3vni
->svi_if
= ifp
;
6369 /* process oper-up */
6370 if (is_l3vni_oper_up(zl3vni
))
6371 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6374 /* process SVI up for l2-vni */
6375 struct neigh_walk_ctx n_wctx
;
6377 zvni
= zvni_from_svi(ifp
, link_if
);
6381 if (!zvni
->vxlan_if
) {
6383 "VNI %u hash %p doesn't have intf upon SVI up",
6388 if (IS_ZEBRA_DEBUG_VXLAN
)
6390 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
6391 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
6392 vrf_id_to_name(ifp
->vrf_id
));
6394 /* update the vrf information for l2-vni and inform bgp */
6395 zvni
->vrf_id
= ifp
->vrf_id
;
6396 zvni_send_add_to_client(zvni
);
6398 /* Install any remote neighbors for this VNI. */
6399 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6401 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6409 * Handle VxLAN interface down
6411 int zebra_vxlan_if_down(struct interface
*ifp
)
6414 struct zebra_if
*zif
= NULL
;
6415 struct zebra_l2info_vxlan
*vxl
= NULL
;
6416 zebra_l3vni_t
*zl3vni
= NULL
;
6419 /* Check if EVPN is enabled. */
6420 if (!is_evpn_enabled())
6425 vxl
= &zif
->l2info
.vxl
;
6428 zl3vni
= zl3vni_lookup(vni
);
6430 /* process-if-down for l3-vni */
6431 if (IS_ZEBRA_DEBUG_VXLAN
)
6432 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
6435 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6437 /* process if-down for l2-vni */
6438 if (IS_ZEBRA_DEBUG_VXLAN
)
6439 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
6442 /* Locate hash entry; it is expected to exist. */
6443 zvni
= zvni_lookup(vni
);
6446 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
6447 ifp
->name
, ifp
->ifindex
, vni
);
6451 assert(zvni
->vxlan_if
== ifp
);
6453 /* Delete this VNI from BGP. */
6454 zvni_send_del_to_client(zvni
->vni
);
6456 /* Free up all neighbors and MACs, if any. */
6457 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6458 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6460 /* Free up all remote VTEPs, if any. */
6461 zvni_vtep_del_all(zvni
, 1);
6467 * Handle VxLAN interface up - update BGP if required.
6469 int zebra_vxlan_if_up(struct interface
*ifp
)
6472 struct zebra_if
*zif
= NULL
;
6473 struct zebra_l2info_vxlan
*vxl
= NULL
;
6474 zebra_vni_t
*zvni
= NULL
;
6475 zebra_l3vni_t
*zl3vni
= NULL
;
6477 /* Check if EVPN is enabled. */
6478 if (!is_evpn_enabled())
6483 vxl
= &zif
->l2info
.vxl
;
6486 zl3vni
= zl3vni_lookup(vni
);
6489 if (IS_ZEBRA_DEBUG_VXLAN
)
6490 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
6493 /* we need to associate with SVI, if any, we can associate with
6494 * svi-if only after association with vxlan-intf is complete
6496 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6498 if (is_l3vni_oper_up(zl3vni
))
6499 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6501 /* Handle L2-VNI add */
6502 struct interface
*vlan_if
= NULL
;
6504 if (IS_ZEBRA_DEBUG_VXLAN
)
6505 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
6508 /* Locate hash entry; it is expected to exist. */
6509 zvni
= zvni_lookup(vni
);
6512 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
6513 ifp
->name
, ifp
->ifindex
, vni
);
6517 assert(zvni
->vxlan_if
== ifp
);
6518 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6519 zif
->brslave_info
.br_if
);
6521 zvni
->vrf_id
= vlan_if
->vrf_id
;
6522 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6524 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6527 /* If part of a bridge, inform BGP about this VNI. */
6528 /* Also, read and populate local MACs and neighbors. */
6529 if (zif
->brslave_info
.br_if
) {
6530 zvni_send_add_to_client(zvni
);
6531 zvni_read_mac_neigh(zvni
, ifp
);
6539 * Handle VxLAN interface delete. Locate and remove entry in hash table
6540 * and update BGP, if required.
6542 int zebra_vxlan_if_del(struct interface
*ifp
)
6545 struct zebra_if
*zif
= NULL
;
6546 struct zebra_l2info_vxlan
*vxl
= NULL
;
6547 zebra_vni_t
*zvni
= NULL
;
6548 zebra_l3vni_t
*zl3vni
= NULL
;
6550 /* Check if EVPN is enabled. */
6551 if (!is_evpn_enabled())
6556 vxl
= &zif
->l2info
.vxl
;
6559 zl3vni
= zl3vni_lookup(vni
);
6562 if (IS_ZEBRA_DEBUG_VXLAN
)
6563 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
6566 /* process oper-down for l3-vni */
6567 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6569 /* remove the association with vxlan_if */
6570 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
6571 zl3vni
->vxlan_if
= NULL
;
6574 /* process if-del for l2-vni*/
6575 if (IS_ZEBRA_DEBUG_VXLAN
)
6576 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
6579 /* Locate hash entry; it is expected to exist. */
6580 zvni
= zvni_lookup(vni
);
6583 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6584 ifp
->name
, ifp
->ifindex
, vni
);
6588 /* remove from l3-vni list */
6589 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
6591 listnode_delete(zl3vni
->l2vnis
, zvni
);
6593 /* Delete VNI from BGP. */
6594 zvni_send_del_to_client(zvni
->vni
);
6596 /* Free up all neighbors and MAC, if any. */
6597 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
6598 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
6600 /* Free up all remote VTEPs, if any. */
6601 zvni_vtep_del_all(zvni
, 0);
6603 /* Delete the hash entry. */
6604 if (zvni_del(zvni
)) {
6605 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
6606 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
6607 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
6615 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6617 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
6620 struct zebra_if
*zif
= NULL
;
6621 struct zebra_l2info_vxlan
*vxl
= NULL
;
6622 zebra_vni_t
*zvni
= NULL
;
6623 zebra_l3vni_t
*zl3vni
= NULL
;
6625 /* Check if EVPN is enabled. */
6626 if (!is_evpn_enabled())
6631 vxl
= &zif
->l2info
.vxl
;
6634 zl3vni
= zl3vni_lookup(vni
);
6637 if (IS_ZEBRA_DEBUG_VXLAN
)
6639 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6640 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6641 inet_ntoa(vxl
->vtep_ip
),
6642 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6644 /* Removed from bridge? Cleanup and return */
6645 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6646 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6647 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6651 /* access-vlan change - process oper down, associate with new
6652 * svi_if and then process oper up again
6654 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6655 if (if_is_operative(ifp
)) {
6656 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6657 zl3vni
->svi_if
= NULL
;
6658 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6659 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6660 if (is_l3vni_oper_up(zl3vni
))
6661 zebra_vxlan_process_l3vni_oper_up(
6667 * local-ip change - process oper down, associate with new
6668 * local-ip and then process oper up again
6670 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
6671 if (if_is_operative(ifp
)) {
6672 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6673 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6674 if (is_l3vni_oper_up(zl3vni
))
6675 zebra_vxlan_process_l3vni_oper_up(
6680 /* Update local tunnel IP. */
6681 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6683 /* if we have a valid new master, process l3-vni oper up */
6684 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
6685 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
6686 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6690 /* Update VNI hash. */
6691 zvni
= zvni_lookup(vni
);
6694 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6695 ifp
->name
, ifp
->ifindex
, vni
);
6699 if (IS_ZEBRA_DEBUG_VXLAN
)
6701 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6702 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6703 inet_ntoa(vxl
->vtep_ip
),
6704 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6706 /* Removed from bridge? Cleanup and return */
6707 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6708 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6709 /* Delete from client, remove all remote VTEPs */
6710 /* Also, free up all MACs and neighbors. */
6711 zvni_send_del_to_client(zvni
->vni
);
6712 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6713 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6714 zvni_vtep_del_all(zvni
, 1);
6718 /* Handle other changes. */
6719 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6720 /* Remove all existing local neigh and MACs for this VNI
6721 * (including from BGP)
6723 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6724 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6727 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6728 zvni
->vxlan_if
= ifp
;
6730 /* Take further actions needed.
6731 * Note that if we are here, there is a change of interest.
6733 /* If down or not mapped to a bridge, we're done. */
6734 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6737 /* Inform BGP, if there is a change of interest. */
6739 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
6740 zvni_send_add_to_client(zvni
);
6742 /* If there is a valid new master or a VLAN mapping change,
6743 * read and populate local MACs and neighbors.
6744 * Also, reinstall any remote MACs and neighbors
6745 * for this VNI (based on new VLAN).
6747 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6748 zvni_read_mac_neigh(zvni
, ifp
);
6749 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6750 struct mac_walk_ctx m_wctx
;
6751 struct neigh_walk_ctx n_wctx
;
6753 zvni_read_mac_neigh(zvni
, ifp
);
6755 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6757 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
6760 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6762 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6771 * Handle VxLAN interface add.
6773 int zebra_vxlan_if_add(struct interface
*ifp
)
6776 struct zebra_if
*zif
= NULL
;
6777 struct zebra_l2info_vxlan
*vxl
= NULL
;
6778 zebra_vni_t
*zvni
= NULL
;
6779 zebra_l3vni_t
*zl3vni
= NULL
;
6781 /* Check if EVPN is enabled. */
6782 if (!is_evpn_enabled())
6787 vxl
= &zif
->l2info
.vxl
;
6790 zl3vni
= zl3vni_lookup(vni
);
6793 /* process if-add for l3-vni*/
6794 if (IS_ZEBRA_DEBUG_VXLAN
)
6796 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6797 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6798 inet_ntoa(vxl
->vtep_ip
),
6799 zif
->brslave_info
.bridge_ifindex
);
6801 /* associate with vxlan_if */
6802 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6803 zl3vni
->vxlan_if
= ifp
;
6805 /* Associate with SVI, if any. We can associate with svi-if only
6806 * after association with vxlan_if is complete */
6807 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6809 if (is_l3vni_oper_up(zl3vni
))
6810 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6813 /* process if-add for l2-vni */
6814 struct interface
*vlan_if
= NULL
;
6816 /* Create or update VNI hash. */
6817 zvni
= zvni_lookup(vni
);
6819 zvni
= zvni_add(vni
);
6822 EC_ZEBRA_VNI_ADD_FAILED
,
6823 "Failed to add VNI hash, IF %s(%u) VNI %u",
6824 ifp
->name
, ifp
->ifindex
, vni
);
6829 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6830 zvni
->vxlan_if
= ifp
;
6831 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6832 zif
->brslave_info
.br_if
);
6834 zvni
->vrf_id
= vlan_if
->vrf_id
;
6835 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6837 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6840 if (IS_ZEBRA_DEBUG_VXLAN
)
6842 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6844 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
6846 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6847 inet_ntoa(vxl
->vtep_ip
),
6848 zif
->brslave_info
.bridge_ifindex
);
6850 /* If down or not mapped to a bridge, we're done. */
6851 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6855 zvni_send_add_to_client(zvni
);
6857 /* Read and populate local MACs and neighbors */
6858 zvni_read_mac_neigh(zvni
, ifp
);
6864 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
6865 char *err
, int err_str_sz
, int filter
,
6868 zebra_l3vni_t
*zl3vni
= NULL
;
6869 struct zebra_vrf
*zvrf_default
= NULL
;
6871 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
6875 if (IS_ZEBRA_DEBUG_VXLAN
)
6876 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
6877 add
? "ADD" : "DEL");
6881 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6883 /* check if the vni is already present under zvrf */
6885 snprintf(err
, err_str_sz
,
6886 "VNI is already configured under the vrf");
6890 /* check if this VNI is already present in the system */
6891 zl3vni
= zl3vni_lookup(vni
);
6893 snprintf(err
, err_str_sz
,
6894 "VNI is already configured as L3-VNI");
6898 /* add the L3-VNI to the global table */
6899 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
6901 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
6905 /* associate the vrf with vni */
6908 /* set the filter in l3vni to denote if we are using l3vni only
6912 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
6914 /* associate with vxlan-intf;
6915 * we need to associate with the vxlan-intf first
6917 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
6919 /* associate with corresponding SVI interface, we can associate
6920 * with svi-if only after vxlan interface association is
6923 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6925 /* formulate l2vni list */
6926 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
6929 if (is_l3vni_oper_up(zl3vni
))
6930 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6933 zl3vni
= zl3vni_lookup(vni
);
6935 snprintf(err
, err_str_sz
, "VNI doesn't exist");
6939 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
6940 snprintf(err
, ERR_STR_SZ
,
6941 "prefix-routes-only is not set for the vni");
6945 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6947 /* delete and uninstall all rmacs */
6948 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
6951 /* delete and uninstall all next-hops */
6952 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
6958 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6963 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
6965 zebra_l3vni_t
*zl3vni
= NULL
;
6968 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6972 zl3vni
->vrf_id
= zvrf_id(zvrf
);
6973 if (is_l3vni_oper_up(zl3vni
))
6974 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6978 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
6980 zebra_l3vni_t
*zl3vni
= NULL
;
6983 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6987 zl3vni
->vrf_id
= VRF_UNKNOWN
;
6988 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6992 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
6994 zebra_l3vni_t
*zl3vni
= NULL
;
6998 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
7004 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
7010 * Handle message from client to specify the flooding mechanism for
7011 * BUM packets. The default is to do head-end (ingress) replication
7012 * and the other supported option is to disable it. This applies to
7013 * all BUM traffic and disabling it applies to both the transmit and
7014 * receive direction.
7016 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
7019 enum vxlan_flood_control flood_ctrl
;
7021 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7022 zlog_err("EVPN flood control for non-default VRF %u",
7028 STREAM_GETC(s
, flood_ctrl
);
7030 if (IS_ZEBRA_DEBUG_VXLAN
)
7031 zlog_debug("EVPN flood control %u, currently %u",
7032 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
7034 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
7037 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
7039 /* Install or uninstall flood entries corresponding to
7042 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
7050 * Handle message from client to enable/disable advertisement of g/w macip
7053 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
7058 zebra_vni_t
*zvni
= NULL
;
7059 struct interface
*ifp
= NULL
;
7060 struct zebra_if
*zif
= NULL
;
7061 struct zebra_l2info_vxlan zl2_info
;
7062 struct interface
*vlan_if
= NULL
;
7064 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7065 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
7071 STREAM_GETC(s
, advertise
);
7072 vni
= stream_get3(s
);
7074 zvni
= zvni_lookup(vni
);
7078 if (zvni
->advertise_subnet
== advertise
)
7081 if (IS_ZEBRA_DEBUG_VXLAN
)
7082 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
7083 advertise
? "enabled" : "disabled", vni
,
7084 zvni
->advertise_subnet
? "enabled" : "disabled");
7087 zvni
->advertise_subnet
= advertise
;
7089 ifp
= zvni
->vxlan_if
;
7095 /* If down or not mapped to a bridge, we're done. */
7096 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7099 zl2_info
= zif
->l2info
.vxl
;
7102 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
7106 if (zvni
->advertise_subnet
)
7107 zvni_advertise_subnet(zvni
, vlan_if
, 1);
7109 zvni_advertise_subnet(zvni
, vlan_if
, 0);
7116 * Handle message from client to enable/disable advertisement of g/w macip
7119 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
7124 zebra_vni_t
*zvni
= NULL
;
7125 struct interface
*ifp
= NULL
;
7127 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7128 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
7134 STREAM_GETC(s
, advertise
);
7135 STREAM_GETL(s
, vni
);
7138 if (IS_ZEBRA_DEBUG_VXLAN
)
7139 zlog_debug("EVPN gateway macip Adv %s, currently %s",
7140 advertise
? "enabled" : "disabled",
7141 advertise_gw_macip_enabled(NULL
)
7145 if (zvrf
->advertise_gw_macip
== advertise
)
7148 zvrf
->advertise_gw_macip
= advertise
;
7150 if (advertise_gw_macip_enabled(zvni
))
7151 hash_iterate(zvrf
->vni_table
,
7152 zvni_gw_macip_add_for_vni_hash
, NULL
);
7154 hash_iterate(zvrf
->vni_table
,
7155 zvni_gw_macip_del_for_vni_hash
, NULL
);
7158 struct zebra_if
*zif
= NULL
;
7159 struct zebra_l2info_vxlan zl2_info
;
7160 struct interface
*vlan_if
= NULL
;
7161 struct interface
*vrr_if
= NULL
;
7163 zvni
= zvni_lookup(vni
);
7167 if (IS_ZEBRA_DEBUG_VXLAN
)
7169 "EVPN gateway macip Adv %s on VNI %d , currently %s",
7170 advertise
? "enabled" : "disabled", vni
,
7171 advertise_gw_macip_enabled(zvni
) ? "enabled"
7174 if (zvni
->advertise_gw_macip
== advertise
)
7177 zvni
->advertise_gw_macip
= advertise
;
7179 ifp
= zvni
->vxlan_if
;
7185 /* If down or not mapped to a bridge, we're done. */
7186 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7189 zl2_info
= zif
->l2info
.vxl
;
7191 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
7192 zif
->brslave_info
.br_if
);
7196 if (advertise_gw_macip_enabled(zvni
)) {
7197 /* Add primary SVI MAC-IP */
7198 zvni_add_macip_for_intf(vlan_if
, zvni
);
7200 /* Add VRR MAC-IP - if any*/
7201 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
7203 zvni_add_macip_for_intf(vrr_if
, zvni
);
7205 /* Del primary MAC-IP */
7206 zvni_del_macip_for_intf(vlan_if
, zvni
);
7208 /* Del VRR MAC-IP - if any*/
7209 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
7211 zvni_del_macip_for_intf(vrr_if
, zvni
);
7221 * Handle message from client to learn (or stop learning) about VNIs and MACs.
7222 * When enabled, the VNI hash table will be built and MAC FDB table read;
7223 * when disabled, the entries should be deleted and remote VTEPs and MACs
7224 * uninstalled from the kernel.
7225 * This also informs the setting for BUM handling at the time this change
7226 * occurs; it is relevant only when specifying "learn".
7228 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
7230 struct stream
*s
= NULL
;
7232 enum vxlan_flood_control flood_ctrl
;
7234 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7235 zlog_debug("EVPN VNI Adv for non-default VRF %u",
7241 STREAM_GETC(s
, advertise
);
7242 STREAM_GETC(s
, flood_ctrl
);
7244 if (IS_ZEBRA_DEBUG_VXLAN
)
7245 zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u",
7246 advertise
? "enabled" : "disabled",
7247 is_evpn_enabled() ? "enabled" : "disabled",
7250 if (zvrf
->advertise_all_vni
== advertise
)
7253 zvrf
->advertise_all_vni
= advertise
;
7254 if (is_evpn_enabled()) {
7255 /* Note BUM handling */
7256 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
7258 /* Build VNI hash table and inform BGP. */
7259 zvni_build_hash_table();
7261 /* Add all SVI (L3 GW) MACs to BGP*/
7262 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
7265 /* Read the MAC FDB */
7266 macfdb_read(zvrf
->zns
);
7268 /* Read neighbors */
7269 neigh_read(zvrf
->zns
);
7271 /* Cleanup VTEPs for all VNIs - uninstall from
7272 * kernel and free entries.
7274 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
7276 /* cleanup all l3vnis */
7277 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
7285 * Allocate VNI hash table for this VRF and do other initialization.
7286 * NOTE: Currently supported only for default VRF.
7288 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
7292 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
7293 "Zebra VRF VNI Table");
7296 /* Cleanup VNI info, but don't free the table. */
7297 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
7301 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
7304 /* Close all VNI handling */
7305 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
7309 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
7310 hash_free(zvrf
->vni_table
);
7313 /* init the l3vni table */
7314 void zebra_vxlan_ns_init(struct zebra_ns
*zns
)
7316 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
7317 "Zebra VRF L3 VNI table");
7320 /* free l3vni table */
7321 void zebra_vxlan_ns_disable(struct zebra_ns
*zns
)
7323 hash_free(zrouter
.l3vni_table
);
7326 /* get the l3vni svi ifindex */
7327 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
7329 zebra_l3vni_t
*zl3vni
= NULL
;
7331 zl3vni
= zl3vni_from_vrf(vrf_id
);
7332 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
7335 return zl3vni
->svi_if
->ifindex
;