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
);
1198 /* Private Structure to pass callback data for hash iterator */
1199 struct zvni_evpn_show
{
1202 struct zebra_vrf
*zvrf
;
1205 /* print a L3 VNI hash entry in detail*/
1206 static void zl3vni_print_hash_detail(struct hash_backet
*backet
, void *data
)
1208 struct vty
*vty
= NULL
;
1209 zebra_l3vni_t
*zl3vni
= NULL
;
1210 json_object
*json
= NULL
;
1211 bool use_json
= false;
1212 struct zvni_evpn_show
*zes
= data
;
1220 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1222 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
1228 * Print a VNI hash entry - called for display of all VNIs.
1230 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1234 zebra_vtep_t
*zvtep
;
1235 uint32_t num_vteps
= 0;
1236 uint32_t num_macs
= 0;
1237 uint32_t num_neigh
= 0;
1238 json_object
*json
= NULL
;
1239 json_object
*json_vni
= NULL
;
1240 json_object
*json_ip_str
= NULL
;
1241 json_object
*json_vtep_list
= NULL
;
1246 zvni
= (zebra_vni_t
*)backet
->data
;
1248 zvtep
= zvni
->vteps
;
1251 zvtep
= zvtep
->next
;
1254 num_macs
= num_valid_macs(zvni
);
1255 num_neigh
= hashcount(zvni
->neigh_table
);
1257 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1259 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1260 num_macs
, num_neigh
, num_vteps
,
1261 vrf_id_to_name(zvni
->vrf_id
));
1263 char vni_str
[VNI_STR_LEN
];
1264 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1265 json_vni
= json_object_new_object();
1266 json_object_int_add(json_vni
, "vni", zvni
->vni
);
1267 json_object_string_add(json_vni
, "type", "L2");
1268 json_object_string_add(json_vni
, "vxlanIf",
1269 zvni
->vxlan_if
? zvni
->vxlan_if
->name
1271 json_object_int_add(json_vni
, "numMacs", num_macs
);
1272 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1273 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
1274 json_object_string_add(json_vni
, "tenantVrf",
1275 vrf_id_to_name(zvni
->vrf_id
));
1277 json_vtep_list
= json_object_new_array();
1278 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1279 json_ip_str
= json_object_new_string(
1280 inet_ntoa(zvtep
->vtep_ip
));
1281 json_object_array_add(json_vtep_list
,
1284 json_object_object_add(json_vni
, "remoteVteps",
1287 json_object_object_add(json
, vni_str
, json_vni
);
1292 * Print a VNI hash entry in detail - called for display of all VNIs.
1294 static void zvni_print_hash_detail(struct hash_backet
*backet
, void *data
)
1298 json_object
*json
= NULL
;
1299 bool use_json
= false;
1300 struct zvni_evpn_show
*zes
= data
;
1308 zvni
= (zebra_vni_t
*)backet
->data
;
1310 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
1315 * Inform BGP about local MACIP.
1317 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
1318 struct ipaddr
*ip
, uint8_t flags
,
1319 uint32_t seq
, uint16_t cmd
)
1321 char buf
[ETHER_ADDR_STRLEN
];
1322 char buf2
[INET6_ADDRSTRLEN
];
1324 struct zserv
*client
= NULL
;
1325 struct stream
*s
= NULL
;
1327 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
1328 /* BGP may not be running. */
1332 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
1334 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
1335 stream_putl(s
, vni
);
1336 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
1339 if (IS_IPADDR_V4(ip
))
1340 ipa_len
= IPV4_MAX_BYTELEN
;
1341 else if (IS_IPADDR_V6(ip
))
1342 ipa_len
= IPV6_MAX_BYTELEN
;
1344 stream_putl(s
, ipa_len
); /* IP address length */
1346 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
1348 stream_putl(s
, 0); /* Just MAC. */
1350 if (cmd
== ZEBRA_MACIP_ADD
) {
1351 stream_putc(s
, flags
); /* sticky mac/gateway mac */
1352 stream_putl(s
, seq
); /* sequence number */
1356 /* Write packet size. */
1357 stream_putw_at(s
, 0, stream_get_endp(s
));
1359 if (IS_ZEBRA_DEBUG_VXLAN
)
1361 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
1362 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
1363 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1364 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
1365 zebra_route_string(client
->proto
));
1367 if (cmd
== ZEBRA_MACIP_ADD
)
1368 client
->macipadd_cnt
++;
1370 client
->macipdel_cnt
++;
1372 return zserv_send_message(client
, s
);
1376 * Make hash key for neighbors.
1378 static unsigned int neigh_hash_keymake(void *p
)
1380 zebra_neigh_t
*n
= p
;
1381 struct ipaddr
*ip
= &n
->ip
;
1383 if (IS_IPADDR_V4(ip
))
1384 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
1386 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
1387 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
1391 * Compare two neighbor hash structures.
1393 static bool neigh_cmp(const void *p1
, const void *p2
)
1395 const zebra_neigh_t
*n1
= p1
;
1396 const zebra_neigh_t
*n2
= p2
;
1398 if (n1
== NULL
&& n2
== NULL
)
1401 if (n1
== NULL
|| n2
== NULL
)
1404 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
1407 static int neigh_list_cmp(void *p1
, void *p2
)
1409 const zebra_neigh_t
*n1
= p1
;
1410 const zebra_neigh_t
*n2
= p2
;
1412 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
1416 * Callback to allocate neighbor hash entry.
1418 static void *zvni_neigh_alloc(void *p
)
1420 const zebra_neigh_t
*tmp_n
= p
;
1423 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
1430 * Add neighbor entry.
1432 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
1433 struct ethaddr
*mac
)
1435 zebra_neigh_t tmp_n
;
1436 zebra_neigh_t
*n
= NULL
;
1437 zebra_mac_t
*zmac
= NULL
;
1439 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
1440 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1441 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
1444 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1445 n
->state
= ZEBRA_NEIGH_INACTIVE
;
1447 /* Associate the neigh to mac */
1448 zmac
= zvni_mac_lookup(zvni
, mac
);
1450 listnode_add_sort(zmac
->neigh_list
, n
);
1456 * Delete neighbor entry.
1458 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1460 zebra_neigh_t
*tmp_n
;
1461 zebra_mac_t
*zmac
= NULL
;
1463 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
1465 listnode_delete(zmac
->neigh_list
, n
);
1467 /* Free the VNI hash entry and allocated memory. */
1468 tmp_n
= hash_release(zvni
->neigh_table
, n
);
1470 XFREE(MTYPE_NEIGH
, tmp_n
);
1476 * Free neighbor hash entry (callback)
1478 static void zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
1480 struct neigh_walk_ctx
*wctx
= arg
;
1481 zebra_neigh_t
*n
= backet
->data
;
1483 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1484 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
1485 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
1486 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
1487 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
1488 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
1489 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1490 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
1493 if (wctx
->uninstall
)
1494 zvni_neigh_uninstall(wctx
->zvni
, n
);
1496 zvni_neigh_del(wctx
->zvni
, n
);
1503 * Delete all neighbor entries from specific VTEP for a particular VNI.
1505 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
1506 struct in_addr
*r_vtep_ip
)
1508 struct neigh_walk_ctx wctx
;
1510 if (!zvni
->neigh_table
)
1513 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1515 wctx
.uninstall
= uninstall
;
1516 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
1517 wctx
.r_vtep_ip
= *r_vtep_ip
;
1519 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1523 * Delete all neighbor entries for this VNI.
1525 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
1528 struct neigh_walk_ctx wctx
;
1530 if (!zvni
->neigh_table
)
1533 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1535 wctx
.uninstall
= uninstall
;
1536 wctx
.upd_client
= upd_client
;
1539 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1543 * Look up neighbor hash entry.
1545 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
1550 memset(&tmp
, 0, sizeof(tmp
));
1551 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
1552 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
1558 * Process all neighbors associated with a MAC upon the MAC being learnt
1559 * locally or undergoing any other change (such as sequence number).
1561 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
1565 zebra_neigh_t
*n
= NULL
;
1566 struct listnode
*node
= NULL
;
1567 char buf
[ETHER_ADDR_STRLEN
];
1569 if (IS_ZEBRA_DEBUG_VXLAN
)
1570 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
1571 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
1572 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
1574 /* Walk all neighbors and mark any inactive local neighbors as
1575 * active and/or update sequence number upon a move, and inform BGP.
1576 * The action for remote neighbors is TBD.
1577 * NOTE: We can't simply uninstall remote neighbors as the kernel may
1578 * accidentally end up deleting a just-learnt local neighbor.
1580 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1581 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1582 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
1583 ZEBRA_NEIGH_SET_ACTIVE(n
);
1584 n
->loc_seq
= zmac
->loc_seq
;
1585 zvni_neigh_send_add_to_client(
1586 zvni
->vni
, &n
->ip
, &n
->emac
,
1587 n
->flags
, n
->loc_seq
);
1594 * Process all neighbors associated with a local MAC upon the MAC being
1597 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
1600 zebra_neigh_t
*n
= NULL
;
1601 struct listnode
*node
= NULL
;
1602 char buf
[ETHER_ADDR_STRLEN
];
1604 if (IS_ZEBRA_DEBUG_VXLAN
)
1605 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
1606 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
1609 /* Walk all local neighbors and mark as inactive and inform
1611 * TBD: There is currently no handling for remote neighbors. We
1612 * don't expect them to exist, if they do, do we install the MAC
1613 * as a remote MAC and the neighbor as remote?
1615 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1616 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1617 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1618 ZEBRA_NEIGH_SET_INACTIVE(n
);
1620 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1628 * Process all neighbors associated with a MAC upon the MAC being remotely
1631 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
1634 zebra_neigh_t
*n
= NULL
;
1635 struct listnode
*node
= NULL
;
1636 char buf
[ETHER_ADDR_STRLEN
];
1638 if (IS_ZEBRA_DEBUG_VXLAN
)
1639 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
1640 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
1643 /* Walk all local neighbors and mark as inactive and inform
1646 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1647 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1648 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1649 ZEBRA_NEIGH_SET_INACTIVE(n
);
1651 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1659 * Process all neighbors associated with a remote MAC upon the MAC being
1662 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
1665 /* NOTE: Currently a NO-OP. */
1669 * Inform BGP about local neighbor addition.
1671 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
1672 struct ethaddr
*macaddr
,
1673 uint8_t neigh_flags
,
1678 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
1679 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
1680 /* Set router flag (R-bit) based on local neigh entry add */
1681 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
1682 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
1684 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1685 seq
, ZEBRA_MACIP_ADD
);
1689 * Inform BGP about local neighbor deletion.
1691 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
1692 struct ethaddr
*macaddr
, uint8_t flags
)
1694 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1695 0, ZEBRA_MACIP_DEL
);
1699 * Install remote neighbor into the kernel.
1701 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1703 struct zebra_if
*zif
;
1704 struct zebra_l2info_vxlan
*vxl
;
1705 struct interface
*vlan_if
;
1711 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1714 zif
= zvni
->vxlan_if
->info
;
1717 vxl
= &zif
->l2info
.vxl
;
1719 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1723 flags
= NTF_EXT_LEARNED
;
1724 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
1725 flags
|= NTF_ROUTER
;
1726 ZEBRA_NEIGH_SET_ACTIVE(n
);
1727 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
1733 * Uninstall remote neighbor from the kernel.
1735 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1737 struct zebra_if
*zif
;
1738 struct zebra_l2info_vxlan
*vxl
;
1739 struct interface
*vlan_if
;
1741 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1744 if (!zvni
->vxlan_if
) {
1745 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
1750 zif
= zvni
->vxlan_if
->info
;
1753 vxl
= &zif
->l2info
.vxl
;
1754 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1758 ZEBRA_NEIGH_SET_INACTIVE(n
);
1760 return kernel_del_neigh(vlan_if
, &n
->ip
);
1764 * Install neighbor hash entry - called upon access VLAN change.
1766 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
1769 struct neigh_walk_ctx
*wctx
= ctxt
;
1771 n
= (zebra_neigh_t
*)backet
->data
;
1773 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
1774 zvni_neigh_install(wctx
->zvni
, n
);
1777 /* Get the VRR interface for SVI if any */
1778 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
1780 struct zebra_vrf
*zvrf
= NULL
;
1781 struct interface
*tmp_if
= NULL
;
1782 struct zebra_if
*zif
= NULL
;
1784 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1787 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
1792 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
1795 if (zif
->link
== ifp
)
1802 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1804 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1805 struct connected
*c
= NULL
;
1806 struct ethaddr macaddr
;
1808 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1810 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1813 memset(&ip
, 0, sizeof(struct ipaddr
));
1814 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1817 if (c
->address
->family
== AF_INET
) {
1818 ip
.ipa_type
= IPADDR_V4
;
1819 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1820 sizeof(struct in_addr
));
1821 } else if (c
->address
->family
== AF_INET6
) {
1822 ip
.ipa_type
= IPADDR_V6
;
1823 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1824 sizeof(struct in6_addr
));
1829 zvni_gw_macip_del(ifp
, zvni
, &ip
);
1835 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1837 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1838 struct connected
*c
= NULL
;
1839 struct ethaddr macaddr
;
1841 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1843 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1846 memset(&ip
, 0, sizeof(struct ipaddr
));
1847 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1850 if (c
->address
->family
== AF_INET
) {
1851 ip
.ipa_type
= IPADDR_V4
;
1852 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1853 sizeof(struct in_addr
));
1854 } else if (c
->address
->family
== AF_INET6
) {
1855 ip
.ipa_type
= IPADDR_V6
;
1856 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1857 sizeof(struct in6_addr
));
1862 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
1868 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
1871 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1872 struct connected
*c
= NULL
;
1873 struct ethaddr macaddr
;
1875 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1877 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1880 memcpy(&p
, c
->address
, sizeof(struct prefix
));
1882 /* skip link local address */
1883 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
1888 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1889 ZEBRA_IP_PREFIX_ROUTE_ADD
);
1891 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1892 ZEBRA_IP_PREFIX_ROUTE_DEL
);
1898 * zvni_gw_macip_add_to_client
1900 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
1901 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
1903 char buf
[ETHER_ADDR_STRLEN
];
1904 char buf2
[INET6_ADDRSTRLEN
];
1905 zebra_neigh_t
*n
= NULL
;
1906 zebra_mac_t
*mac
= NULL
;
1907 struct zebra_if
*zif
= NULL
;
1908 struct zebra_l2info_vxlan
*vxl
= NULL
;
1910 zif
= zvni
->vxlan_if
->info
;
1914 vxl
= &zif
->l2info
.vxl
;
1916 mac
= zvni_mac_lookup(zvni
, macaddr
);
1918 mac
= zvni_mac_add(zvni
, macaddr
);
1920 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
1921 "Failed to add MAC %s intf %s(%u) VID %u",
1922 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1923 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
1928 /* Set "local" forwarding info. */
1929 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
1930 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
1931 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
1932 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
1933 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
1934 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
1936 n
= zvni_neigh_lookup(zvni
, ip
);
1938 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
1941 EC_ZEBRA_MAC_ADD_FAILED
,
1942 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1943 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
1944 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1945 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
1950 /* Set "local" forwarding info. */
1951 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
1952 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
1953 ZEBRA_NEIGH_SET_ACTIVE(n
);
1954 /* Set Router flag (R-bit) */
1955 if (ip
->ipa_type
== IPADDR_V6
)
1956 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
1957 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
1958 n
->ifindex
= ifp
->ifindex
;
1960 /* Only advertise in BGP if the knob is enabled */
1961 if (!advertise_gw_macip_enabled(zvni
))
1964 if (IS_ZEBRA_DEBUG_VXLAN
)
1966 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
1967 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1968 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1969 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
1971 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
1972 n
->flags
, n
->loc_seq
);
1978 * zvni_gw_macip_del_from_client
1980 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
1983 char buf1
[ETHER_ADDR_STRLEN
];
1984 char buf2
[INET6_ADDRSTRLEN
];
1985 zebra_neigh_t
*n
= NULL
;
1986 zebra_mac_t
*mac
= NULL
;
1988 /* If the neigh entry is not present nothing to do*/
1989 n
= zvni_neigh_lookup(zvni
, ip
);
1993 /* mac entry should be present */
1994 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
1996 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
1997 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
1998 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2002 /* If the entry is not local nothing to do*/
2003 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2006 /* only need to delete the entry from bgp if we sent it before */
2007 if (IS_ZEBRA_DEBUG_VXLAN
)
2009 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2010 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2011 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2012 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2014 /* Remove neighbor from BGP. */
2015 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2016 ZEBRA_MACIP_TYPE_GW
);
2018 /* Delete this neighbor entry. */
2019 zvni_neigh_del(zvni
, n
);
2021 /* see if the mac needs to be deleted as well*/
2023 zvni_deref_ip2mac(zvni
, mac
);
2028 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
2031 zebra_vni_t
*zvni
= NULL
;
2032 struct zebra_if
*zif
= NULL
;
2033 struct zebra_l2info_vxlan zl2_info
;
2034 struct interface
*vlan_if
= NULL
;
2035 struct interface
*vrr_if
= NULL
;
2036 struct interface
*ifp
;
2038 /* Add primary SVI MAC*/
2039 zvni
= (zebra_vni_t
*)backet
->data
;
2041 ifp
= zvni
->vxlan_if
;
2046 /* If down or not mapped to a bridge, we're done. */
2047 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2050 zl2_info
= zif
->l2info
.vxl
;
2053 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2057 /* Del primary MAC-IP */
2058 zvni_del_macip_for_intf(vlan_if
, zvni
);
2060 /* Del VRR MAC-IP - if any*/
2061 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2063 zvni_del_macip_for_intf(vrr_if
, zvni
);
2068 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
2071 zebra_vni_t
*zvni
= NULL
;
2072 struct zebra_if
*zif
= NULL
;
2073 struct zebra_l2info_vxlan zl2_info
;
2074 struct interface
*vlan_if
= NULL
;
2075 struct interface
*vrr_if
= NULL
;
2076 struct interface
*ifp
= NULL
;
2078 zvni
= (zebra_vni_t
*)backet
->data
;
2080 ifp
= zvni
->vxlan_if
;
2085 /* If down or not mapped to a bridge, we're done. */
2086 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2088 zl2_info
= zif
->l2info
.vxl
;
2091 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2095 /* Add primary SVI MAC-IP */
2096 zvni_add_macip_for_intf(vlan_if
, zvni
);
2098 /* Add VRR MAC-IP - if any*/
2099 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2101 zvni_add_macip_for_intf(vrr_if
, zvni
);
2106 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2107 struct interface
*ifp
,
2109 struct ethaddr
*macaddr
,
2112 char buf
[ETHER_ADDR_STRLEN
];
2113 char buf2
[INET6_ADDRSTRLEN
];
2114 zebra_neigh_t
*n
= NULL
;
2115 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2116 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2117 bool upd_mac_seq
= false;
2118 bool neigh_mac_change
= false;
2119 bool check_rbit
= false;
2121 /* Check if the MAC exists. */
2122 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2124 /* create a dummy MAC if the MAC is not already present */
2125 if (IS_ZEBRA_DEBUG_VXLAN
)
2127 "AUTO MAC %s created for neigh %s on VNI %u",
2128 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2129 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2131 zmac
= zvni_mac_add(zvni
, macaddr
);
2133 zlog_debug("Failed to add MAC %s VNI %u",
2134 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2139 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
2140 memset(&zmac
->flags
, 0, sizeof(uint32_t));
2141 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2143 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2145 * We don't change the MAC to local upon a neighbor
2146 * learn event, we wait for the explicit local MAC
2147 * learn. However, we have to compute its sequence
2148 * number in preparation for when it actually turns
2155 /* Check if the neighbor exists. */
2156 n
= zvni_neigh_lookup(zvni
, ip
);
2158 /* New neighbor - create */
2159 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2162 EC_ZEBRA_MAC_ADD_FAILED
,
2163 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2164 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2165 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2166 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2169 /* Set "local" forwarding info. */
2170 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2171 n
->ifindex
= ifp
->ifindex
;
2174 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2178 /* Note any changes and see if of interest to BGP. */
2179 mac_different
= (memcmp(n
->emac
.octet
,
2180 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
2181 cur_is_router
= !!CHECK_FLAG(n
->flags
,
2182 ZEBRA_NEIGH_ROUTER_FLAG
);
2183 if (!mac_different
&& is_router
== cur_is_router
) {
2184 n
->ifindex
= ifp
->ifindex
;
2188 if (!mac_different
) {
2189 /* Only the router flag has changed. */
2192 ZEBRA_NEIGH_ROUTER_FLAG
);
2194 UNSET_FLAG(n
->flags
,
2195 ZEBRA_NEIGH_ROUTER_FLAG
);
2197 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
2198 return zvni_neigh_send_add_to_client(
2199 zvni
->vni
, ip
, macaddr
,
2200 n
->flags
, n
->loc_seq
);
2204 /* The MAC has changed, need to issue a delete
2205 * first as this means a different MACIP route.
2206 * Also, need to do some unlinking/relinking.
2207 * We also need to update the MAC's sequence number
2208 * in different situations.
2210 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
2211 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2213 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2215 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
2217 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
2218 neigh_mac_change
= upd_mac_seq
= true;
2219 listnode_delete(old_zmac
->neigh_list
, n
);
2220 zvni_deref_ip2mac(zvni
, old_zmac
);
2223 /* Update the forwarding info. */
2224 n
->ifindex
= ifp
->ifindex
;
2225 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2227 /* Link to new MAC */
2228 listnode_add_sort(zmac
->neigh_list
, n
);
2229 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2231 * Neighbor has moved from remote to local. Its
2232 * MAC could have also changed as part of the move.
2234 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2236 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2238 old_mac_seq
= CHECK_FLAG(
2243 neigh_mac_change
= upd_mac_seq
= true;
2244 listnode_delete(old_zmac
->neigh_list
,
2246 zvni_deref_ip2mac(zvni
, old_zmac
);
2249 /* Link to new MAC */
2250 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2251 listnode_add_sort(zmac
->neigh_list
, n
);
2254 /* Mark appropriately */
2255 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2256 n
->r_vtep_ip
.s_addr
= 0;
2257 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2258 n
->ifindex
= ifp
->ifindex
;
2263 /* If MAC was previously remote, or the neighbor had a different
2264 * MAC earlier, recompute the sequence number.
2267 uint32_t seq1
, seq2
;
2269 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
2270 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
2271 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
2272 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
2273 MAX(seq1
, seq2
) : zmac
->loc_seq
;
2276 /*Mark Router flag (R-bit) */
2278 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2280 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2282 /* Before we program this in BGP, we need to check if MAC is locally
2283 * learnt. If not, force neighbor to be inactive and reset its seq.
2285 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
2286 ZEBRA_NEIGH_SET_INACTIVE(n
);
2288 zmac
->loc_seq
= mac_new_seq
;
2295 /* If the MAC's sequence number has changed, inform the MAC and all
2296 * neighbors associated with the MAC to BGP, else just inform this
2299 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
2300 if (IS_ZEBRA_DEBUG_VXLAN
)
2301 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
2302 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2303 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
2304 zmac
->loc_seq
= mac_new_seq
;
2305 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
2306 zmac
->flags
, zmac
->loc_seq
))
2308 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
2312 ZEBRA_NEIGH_SET_ACTIVE(n
);
2313 n
->loc_seq
= zmac
->loc_seq
;
2315 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2316 n
->flags
, n
->loc_seq
);
2319 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
2320 struct interface
*ifp
,
2322 struct ethaddr
*macaddr
,
2325 char buf
[ETHER_ADDR_STRLEN
];
2326 char buf2
[INET6_ADDRSTRLEN
];
2327 zebra_neigh_t
*n
= NULL
;
2328 zebra_mac_t
*zmac
= NULL
;
2330 /* If the neighbor is unknown, there is no further action. */
2331 n
= zvni_neigh_lookup(zvni
, ip
);
2335 /* If a remote entry, see if it needs to be refreshed */
2336 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2338 if (state
& NUD_STALE
)
2339 zvni_neigh_install(zvni
, n
);
2342 /* We got a "remote" neighbor notification for an entry
2343 * we think is local. This can happen in a multihoming
2344 * scenario - but only if the MAC is already "remote".
2345 * Just mark our entry as "remote".
2347 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2348 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2350 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
2351 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
2352 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2357 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2358 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2359 ZEBRA_NEIGH_SET_ACTIVE(n
);
2360 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
2367 * Make hash key for MAC.
2369 static unsigned int mac_hash_keymake(void *p
)
2371 zebra_mac_t
*pmac
= p
;
2372 const void *pnt
= (void *)pmac
->macaddr
.octet
;
2374 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
2378 * Compare two MAC addresses.
2380 static bool mac_cmp(const void *p1
, const void *p2
)
2382 const zebra_mac_t
*pmac1
= p1
;
2383 const zebra_mac_t
*pmac2
= p2
;
2385 if (pmac1
== NULL
&& pmac2
== NULL
)
2388 if (pmac1
== NULL
|| pmac2
== NULL
)
2391 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
2396 * Callback to allocate MAC hash entry.
2398 static void *zvni_mac_alloc(void *p
)
2400 const zebra_mac_t
*tmp_mac
= p
;
2403 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2406 return ((void *)mac
);
2412 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
2414 zebra_mac_t tmp_mac
;
2415 zebra_mac_t
*mac
= NULL
;
2417 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
2418 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
2419 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
2422 mac
->neigh_list
= list_new();
2423 mac
->neigh_list
->cmp
= neigh_list_cmp
;
2431 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2433 zebra_mac_t
*tmp_mac
;
2435 list_delete(&mac
->neigh_list
);
2437 /* Free the VNI hash entry and allocated memory. */
2438 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
2440 XFREE(MTYPE_MAC
, tmp_mac
);
2446 * Free MAC hash entry (callback)
2448 static void zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2450 struct mac_walk_ctx
*wctx
= arg
;
2451 zebra_mac_t
*mac
= backet
->data
;
2453 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
2454 || ((wctx
->flags
& DEL_REMOTE_MAC
)
2455 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
2456 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
2457 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
2458 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
2459 &wctx
->r_vtep_ip
))) {
2460 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
2461 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
2465 if (wctx
->uninstall
)
2466 zvni_mac_uninstall(wctx
->zvni
, mac
);
2468 zvni_mac_del(wctx
->zvni
, mac
);
2475 * Delete all MAC entries from specific VTEP for a particular VNI.
2477 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2478 struct in_addr
*r_vtep_ip
)
2480 struct mac_walk_ctx wctx
;
2482 if (!zvni
->mac_table
)
2485 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2487 wctx
.uninstall
= uninstall
;
2488 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
2489 wctx
.r_vtep_ip
= *r_vtep_ip
;
2491 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2495 * Delete all MAC entries for this VNI.
2497 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2500 struct mac_walk_ctx wctx
;
2502 if (!zvni
->mac_table
)
2505 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2507 wctx
.uninstall
= uninstall
;
2508 wctx
.upd_client
= upd_client
;
2511 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2515 * Look up MAC hash entry.
2517 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
2522 memset(&tmp
, 0, sizeof(tmp
));
2523 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
2524 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
2530 * Inform BGP about local MAC addition.
2532 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2533 uint8_t mac_flags
, uint32_t seq
)
2537 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2538 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2539 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2540 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2542 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2543 seq
, ZEBRA_MACIP_ADD
);
2547 * Inform BGP about local MAC deletion.
2549 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
2551 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
2552 0 /* seq */, ZEBRA_MACIP_DEL
);
2556 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2557 * notifications, to see if they are of interest.
2559 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
2560 struct interface
*br_if
, vlanid_t vid
)
2562 struct zebra_ns
*zns
;
2563 struct route_node
*rn
;
2564 struct interface
*tmp_if
= NULL
;
2565 struct zebra_if
*zif
;
2566 struct zebra_l2info_bridge
*br
;
2567 struct zebra_l2info_vxlan
*vxl
= NULL
;
2568 uint8_t bridge_vlan_aware
;
2572 /* Determine if bridge is VLAN-aware or not */
2575 br
= &zif
->l2info
.br
;
2576 bridge_vlan_aware
= br
->vlan_aware
;
2578 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2579 /* TODO: Optimize with a hash. */
2580 zns
= zebra_ns_lookup(NS_DEFAULT
);
2581 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2582 tmp_if
= (struct interface
*)rn
->info
;
2586 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2588 if (!if_is_operative(tmp_if
))
2590 vxl
= &zif
->l2info
.vxl
;
2592 if (zif
->brslave_info
.br_if
!= br_if
)
2595 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2604 zvni
= zvni_lookup(vxl
->vni
);
2609 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2610 * neighbor notifications, to see if they are of interest.
2612 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
2613 struct interface
*br_if
)
2615 struct zebra_ns
*zns
;
2616 struct route_node
*rn
;
2617 struct interface
*tmp_if
= NULL
;
2618 struct zebra_if
*zif
;
2619 struct zebra_l2info_bridge
*br
;
2620 struct zebra_l2info_vxlan
*vxl
= NULL
;
2621 uint8_t bridge_vlan_aware
;
2629 /* Make sure the linked interface is a bridge. */
2630 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
2633 /* Determine if bridge is VLAN-aware or not */
2636 br
= &zif
->l2info
.br
;
2637 bridge_vlan_aware
= br
->vlan_aware
;
2638 if (bridge_vlan_aware
) {
2639 struct zebra_l2info_vlan
*vl
;
2641 if (!IS_ZEBRA_IF_VLAN(ifp
))
2646 vl
= &zif
->l2info
.vl
;
2650 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2651 /* TODO: Optimize with a hash. */
2652 zns
= zebra_ns_lookup(NS_DEFAULT
);
2653 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2654 tmp_if
= (struct interface
*)rn
->info
;
2658 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2660 if (!if_is_operative(tmp_if
))
2662 vxl
= &zif
->l2info
.vxl
;
2664 if (zif
->brslave_info
.br_if
!= br_if
)
2667 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2676 zvni
= zvni_lookup(vxl
->vni
);
2680 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
2682 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
2683 * linked to the bridge
2684 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
2687 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
2689 struct zebra_ns
*zns
;
2690 struct route_node
*rn
;
2691 struct interface
*tmp_if
= NULL
;
2692 struct zebra_if
*zif
;
2693 struct zebra_l2info_bridge
*br
;
2694 struct zebra_l2info_vlan
*vl
;
2695 uint8_t bridge_vlan_aware
;
2698 /* Defensive check, caller expected to invoke only with valid bridge. */
2702 /* Determine if bridge is VLAN-aware or not */
2705 br
= &zif
->l2info
.br
;
2706 bridge_vlan_aware
= br
->vlan_aware
;
2708 /* Check oper status of the SVI. */
2709 if (!bridge_vlan_aware
)
2710 return if_is_operative(br_if
) ? br_if
: NULL
;
2712 /* Identify corresponding VLAN interface. */
2713 /* TODO: Optimize with a hash. */
2714 zns
= zebra_ns_lookup(NS_DEFAULT
);
2715 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2716 tmp_if
= (struct interface
*)rn
->info
;
2717 /* Check oper status of the SVI. */
2718 if (!tmp_if
|| !if_is_operative(tmp_if
))
2721 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
2722 || zif
->link
!= br_if
)
2724 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
2726 if (vl
->vid
== vid
) {
2732 return found
? tmp_if
: NULL
;
2736 * Install remote MAC into the kernel.
2738 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2740 struct zebra_if
*zif
;
2741 struct zebra_l2info_vxlan
*vxl
;
2744 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2747 zif
= zvni
->vxlan_if
->info
;
2750 vxl
= &zif
->l2info
.vxl
;
2752 sticky
= !!CHECK_FLAG(mac
->flags
,
2753 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
2755 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
2756 mac
->fwd_info
.r_vtep_ip
, sticky
);
2760 * Uninstall remote MAC from the kernel.
2762 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2764 struct zebra_if
*zif
;
2765 struct zebra_l2info_vxlan
*vxl
;
2766 struct in_addr vtep_ip
;
2767 struct interface
*ifp
;
2769 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2772 if (!zvni
->vxlan_if
) {
2773 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2778 zif
= zvni
->vxlan_if
->info
;
2781 vxl
= &zif
->l2info
.vxl
;
2783 ifp
= zvni
->vxlan_if
;
2784 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
2786 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
2790 * Install MAC hash entry - called upon access VLAN change.
2792 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
2795 struct mac_walk_ctx
*wctx
= ctxt
;
2797 mac
= (zebra_mac_t
*)backet
->data
;
2799 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
2800 zvni_mac_install(wctx
->zvni
, mac
);
2804 * Count of remote neighbors referencing this MAC.
2806 static int remote_neigh_count(zebra_mac_t
*zmac
)
2808 zebra_neigh_t
*n
= NULL
;
2809 struct listnode
*node
= NULL
;
2812 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2813 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2821 * Decrement neighbor refcount of MAC; uninstall and free it if
2824 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2826 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
2829 /* If all remote neighbors referencing a remote MAC go away,
2830 * we need to uninstall the MAC.
2832 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
2833 remote_neigh_count(mac
) == 0) {
2834 zvni_mac_uninstall(zvni
, mac
);
2835 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
2838 /* If no neighbors, delete the MAC. */
2839 if (list_isempty(mac
->neigh_list
))
2840 zvni_mac_del(zvni
, mac
);
2844 * Read and populate local MACs and neighbors corresponding to this VNI.
2846 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
2848 struct zebra_ns
*zns
;
2849 struct zebra_if
*zif
;
2850 struct interface
*vlan_if
;
2851 struct zebra_l2info_vxlan
*vxl
;
2852 struct interface
*vrr_if
;
2855 vxl
= &zif
->l2info
.vxl
;
2856 zns
= zebra_ns_lookup(NS_DEFAULT
);
2858 if (IS_ZEBRA_DEBUG_VXLAN
)
2860 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2861 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2862 zif
->brslave_info
.bridge_ifindex
);
2864 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
2865 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2868 /* Add SVI MAC-IP */
2869 zvni_add_macip_for_intf(vlan_if
, zvni
);
2871 /* Add VRR MAC-IP - if any*/
2872 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2874 zvni_add_macip_for_intf(vrr_if
, zvni
);
2876 neigh_read_for_vlan(zns
, vlan_if
);
2881 * Hash function for VNI.
2883 static unsigned int vni_hash_keymake(void *p
)
2885 const zebra_vni_t
*zvni
= p
;
2887 return (jhash_1word(zvni
->vni
, 0));
2891 * Compare 2 VNI hash entries.
2893 static bool vni_hash_cmp(const void *p1
, const void *p2
)
2895 const zebra_vni_t
*zvni1
= p1
;
2896 const zebra_vni_t
*zvni2
= p2
;
2898 return (zvni1
->vni
== zvni2
->vni
);
2901 static int vni_list_cmp(void *p1
, void *p2
)
2903 const zebra_vni_t
*zvni1
= p1
;
2904 const zebra_vni_t
*zvni2
= p2
;
2906 if (zvni1
->vni
== zvni2
->vni
)
2908 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
2912 * Callback to allocate VNI hash entry.
2914 static void *zvni_alloc(void *p
)
2916 const zebra_vni_t
*tmp_vni
= p
;
2919 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
2920 zvni
->vni
= tmp_vni
->vni
;
2921 return ((void *)zvni
);
2925 * Look up VNI hash entry.
2927 static zebra_vni_t
*zvni_lookup(vni_t vni
)
2929 struct zebra_vrf
*zvrf
;
2930 zebra_vni_t tmp_vni
;
2931 zebra_vni_t
*zvni
= NULL
;
2933 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2935 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
2937 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
2943 * Add VNI hash entry.
2945 static zebra_vni_t
*zvni_add(vni_t vni
)
2947 struct zebra_vrf
*zvrf
;
2948 zebra_vni_t tmp_zvni
;
2949 zebra_vni_t
*zvni
= NULL
;
2951 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2953 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
2955 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
2958 /* Create hash table for MAC */
2960 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
2962 /* Create hash table for neighbors */
2963 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
2964 "Zebra VNI Neighbor Table");
2970 * Delete VNI hash entry.
2972 static int zvni_del(zebra_vni_t
*zvni
)
2974 struct zebra_vrf
*zvrf
;
2975 zebra_vni_t
*tmp_zvni
;
2977 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2980 zvni
->vxlan_if
= NULL
;
2982 /* Free the neighbor hash table. */
2983 hash_free(zvni
->neigh_table
);
2984 zvni
->neigh_table
= NULL
;
2986 /* Free the MAC hash table. */
2987 hash_free(zvni
->mac_table
);
2988 zvni
->mac_table
= NULL
;
2990 /* Free the VNI hash entry and allocated memory. */
2991 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
2993 XFREE(MTYPE_ZVNI
, tmp_zvni
);
2999 * Inform BGP about local VNI addition.
3001 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3003 struct zserv
*client
;
3006 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3007 /* BGP may not be running. */
3011 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3013 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
3014 stream_putl(s
, zvni
->vni
);
3015 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3016 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3018 /* Write packet size. */
3019 stream_putw_at(s
, 0, stream_get_endp(s
));
3021 if (IS_ZEBRA_DEBUG_VXLAN
)
3022 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3023 inet_ntoa(zvni
->local_vtep_ip
),
3024 vrf_id_to_name(zvni
->vrf_id
),
3025 zebra_route_string(client
->proto
));
3027 client
->vniadd_cnt
++;
3028 return zserv_send_message(client
, s
);
3032 * Inform BGP about local VNI deletion.
3034 static int zvni_send_del_to_client(vni_t vni
)
3036 struct zserv
*client
;
3039 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3040 /* BGP may not be running. */
3044 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3047 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
3048 stream_putl(s
, vni
);
3050 /* Write packet size. */
3051 stream_putw_at(s
, 0, stream_get_endp(s
));
3053 if (IS_ZEBRA_DEBUG_VXLAN
)
3054 zlog_debug("Send VNI_DEL %u to %s", vni
,
3055 zebra_route_string(client
->proto
));
3057 client
->vnidel_cnt
++;
3058 return zserv_send_message(client
, s
);
3062 * Build the VNI hash table by going over the VxLAN interfaces. This
3063 * is called when EVPN (advertise-all-vni) is enabled.
3065 static void zvni_build_hash_table()
3067 struct zebra_ns
*zns
;
3068 struct route_node
*rn
;
3069 struct interface
*ifp
;
3071 /* Walk VxLAN interfaces and create VNI hash. */
3072 zns
= zebra_ns_lookup(NS_DEFAULT
);
3073 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3075 zebra_vni_t
*zvni
= NULL
;
3076 zebra_l3vni_t
*zl3vni
= NULL
;
3077 struct zebra_if
*zif
;
3078 struct zebra_l2info_vxlan
*vxl
;
3080 ifp
= (struct interface
*)rn
->info
;
3084 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3087 vxl
= &zif
->l2info
.vxl
;
3090 /* L3-VNI and L2-VNI are handled seperately */
3091 zl3vni
= zl3vni_lookup(vni
);
3094 if (IS_ZEBRA_DEBUG_VXLAN
)
3096 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
3097 ifp
->name
, ifp
->ifindex
, vni
);
3099 /* associate with vxlan_if */
3100 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3101 zl3vni
->vxlan_if
= ifp
;
3104 * we need to associate with SVI.
3105 * we can associate with svi-if only after association
3106 * with vxlan-intf is complete
3108 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
3110 if (is_l3vni_oper_up(zl3vni
))
3111 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
3114 struct interface
*vlan_if
= NULL
;
3116 if (IS_ZEBRA_DEBUG_VXLAN
)
3118 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
3119 ifp
->name
, ifp
->ifindex
, vni
,
3120 inet_ntoa(vxl
->vtep_ip
));
3122 /* VNI hash entry is not expected to exist. */
3123 zvni
= zvni_lookup(vni
);
3126 "VNI hash already present for IF %s(%u) L2-VNI %u",
3127 ifp
->name
, ifp
->ifindex
, vni
);
3131 zvni
= zvni_add(vni
);
3134 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
3135 ifp
->name
, ifp
->ifindex
, vni
);
3139 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
3140 zvni
->vxlan_if
= ifp
;
3141 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
3142 zif
->brslave_info
.br_if
);
3144 zvni
->vrf_id
= vlan_if
->vrf_id
;
3145 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
3147 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3151 /* Inform BGP if intf is up and mapped to bridge. */
3152 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
3153 zvni_send_add_to_client(zvni
);
3159 * See if remote VTEP matches with prefix.
3161 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
3163 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
3167 * Locate remote VTEP in VNI hash table.
3169 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3171 zebra_vtep_t
*zvtep
;
3176 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
3177 if (zvni_vtep_match(vtep_ip
, zvtep
))
3185 * Add remote VTEP to VNI hash table.
3187 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3189 zebra_vtep_t
*zvtep
;
3191 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
3193 zvtep
->vtep_ip
= *vtep_ip
;
3196 zvni
->vteps
->prev
= zvtep
;
3197 zvtep
->next
= zvni
->vteps
;
3198 zvni
->vteps
= zvtep
;
3204 * Remove remote VTEP from VNI hash table.
3206 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
3209 zvtep
->next
->prev
= zvtep
->prev
;
3211 zvtep
->prev
->next
= zvtep
->next
;
3213 zvni
->vteps
= zvtep
->next
;
3215 zvtep
->prev
= zvtep
->next
= NULL
;
3216 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
3222 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
3223 * uninstall from kernel if asked to.
3225 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
3227 zebra_vtep_t
*zvtep
, *zvtep_next
;
3232 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
3233 zvtep_next
= zvtep
->next
;
3235 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
3236 zvni_vtep_del(zvni
, zvtep
);
3243 * Install remote VTEP into the kernel.
3245 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3247 if (is_vxlan_flooding_head_end())
3248 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3253 * Uninstall remote VTEP from the kernel.
3255 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3257 if (!zvni
->vxlan_if
) {
3258 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3263 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3267 * Install or uninstall flood entries in the kernel corresponding to
3268 * remote VTEPs. This is invoked upon change to BUM handling.
3270 static void zvni_handle_flooding_remote_vteps(struct hash_backet
*backet
,
3274 zebra_vtep_t
*zvtep
;
3276 zvni
= (zebra_vni_t
*)backet
->data
;
3280 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
3281 if (is_vxlan_flooding_head_end())
3282 zvni_vtep_install(zvni
, &zvtep
->vtep_ip
);
3284 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
3289 * Cleanup VNI/VTEP and update kernel
3291 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
3293 zebra_vni_t
*zvni
= NULL
;
3294 zebra_l3vni_t
*zl3vni
= NULL
;
3295 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
3297 zvni
= (zebra_vni_t
*)backet
->data
;
3299 /* remove from l3-vni list */
3301 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
3303 listnode_delete(zl3vni
->l2vnis
, zvni
);
3305 /* Free up all neighbors and MACs, if any. */
3306 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
3307 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
3309 /* Free up all remote VTEPs, if any. */
3310 zvni_vtep_del_all(zvni
, 1);
3312 /* Delete the hash entry. */
3317 static void zl3vni_cleanup_all(struct hash_backet
*backet
, void *args
)
3319 zebra_l3vni_t
*zl3vni
= NULL
;
3321 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
3323 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
3326 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
3327 struct prefix
*host
)
3329 struct host_rb_entry lookup
;
3330 struct host_rb_entry
*hle
;
3332 memset(&lookup
, 0, sizeof(lookup
));
3333 memcpy(&lookup
.p
, host
, sizeof(*host
));
3335 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3339 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
3340 memcpy(hle
, &lookup
, sizeof(lookup
));
3342 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
3345 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
3347 struct host_rb_entry lookup
;
3348 struct host_rb_entry
*hle
;
3350 memset(&lookup
, 0, sizeof(lookup
));
3351 memcpy(&lookup
.p
, host
, sizeof(*host
));
3353 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3355 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
3356 XFREE(MTYPE_HOST_PREFIX
, hle
);
3363 * Look up MAC hash entry.
3365 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
3366 struct ethaddr
*rmac
)
3371 memset(&tmp
, 0, sizeof(tmp
));
3372 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
3373 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
3379 * Callback to allocate RMAC hash entry.
3381 static void *zl3vni_rmac_alloc(void *p
)
3383 const zebra_mac_t
*tmp_rmac
= p
;
3386 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3389 return ((void *)zrmac
);
3393 * Add RMAC entry to l3-vni
3395 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
3397 zebra_mac_t tmp_rmac
;
3398 zebra_mac_t
*zrmac
= NULL
;
3400 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
3401 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
3402 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
3405 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
3407 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
3408 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
3416 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3418 zebra_mac_t
*tmp_rmac
;
3419 struct host_rb_entry
*hle
;
3421 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3422 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
3424 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
3425 XFREE(MTYPE_HOST_PREFIX
, hle
);
3428 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
3430 XFREE(MTYPE_MAC
, tmp_rmac
);
3436 * Install remote RMAC into the kernel.
3438 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3440 struct zebra_if
*zif
= NULL
;
3441 struct zebra_l2info_vxlan
*vxl
= NULL
;
3443 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3444 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3447 zif
= zl3vni
->vxlan_if
->info
;
3451 vxl
= &zif
->l2info
.vxl
;
3453 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3454 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3458 * Uninstall remote RMAC from the kernel.
3460 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3462 char buf
[ETHER_ADDR_STRLEN
];
3463 struct zebra_if
*zif
= NULL
;
3464 struct zebra_l2info_vxlan
*vxl
= NULL
;
3466 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3467 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3470 if (!zl3vni
->vxlan_if
) {
3472 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
3473 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
3474 zl3vni
->vni
, zl3vni
);
3478 zif
= zl3vni
->vxlan_if
->info
;
3482 vxl
= &zif
->l2info
.vxl
;
3484 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3485 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
3488 /* handle rmac add */
3489 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
3490 struct ipaddr
*vtep_ip
,
3491 struct prefix
*host_prefix
)
3493 char buf
[ETHER_ADDR_STRLEN
];
3494 char buf1
[INET6_ADDRSTRLEN
];
3495 zebra_mac_t
*zrmac
= NULL
;
3497 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3500 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
3503 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
3504 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3506 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
3509 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
3510 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
3512 /* install rmac in kernel */
3513 zl3vni_rmac_install(zl3vni
, zrmac
);
3516 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
3522 /* handle rmac delete */
3523 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
3524 struct prefix
*host_prefix
)
3526 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
3528 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3529 /* uninstall from kernel */
3530 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3532 /* del the rmac entry */
3533 zl3vni_rmac_del(zl3vni
, zrmac
);
3538 * Look up nh hash entry on a l3-vni.
3540 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3545 memset(&tmp
, 0, sizeof(tmp
));
3546 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
3547 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
3554 * Callback to allocate NH hash entry on L3-VNI.
3556 static void *zl3vni_nh_alloc(void *p
)
3558 const zebra_neigh_t
*tmp_n
= p
;
3561 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
3568 * Add neighbor entry.
3570 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3571 struct ethaddr
*mac
)
3573 zebra_neigh_t tmp_n
;
3574 zebra_neigh_t
*n
= NULL
;
3576 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
3577 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
3578 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
3581 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
3583 memcpy(&n
->emac
, mac
, ETH_ALEN
);
3584 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3585 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
3591 * Delete neighbor entry.
3593 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3595 zebra_neigh_t
*tmp_n
;
3596 struct host_rb_entry
*hle
;
3598 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
3599 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
3601 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
3602 XFREE(MTYPE_HOST_PREFIX
, hle
);
3605 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
3607 XFREE(MTYPE_NEIGH
, tmp_n
);
3613 * Install remote nh as neigh into the kernel.
3615 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3622 if (!is_l3vni_oper_up(zl3vni
))
3625 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3626 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3629 flags
= NTF_EXT_LEARNED
;
3630 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
3631 flags
|= NTF_ROUTER
;
3632 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
3638 * Uninstall remote nh from the kernel.
3640 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3642 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3643 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3646 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
3649 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
3652 /* add remote vtep as a neigh entry */
3653 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
3654 struct ethaddr
*rmac
,
3655 struct prefix
*host_prefix
)
3657 char buf
[ETHER_ADDR_STRLEN
];
3658 char buf1
[INET6_ADDRSTRLEN
];
3659 zebra_neigh_t
*nh
= NULL
;
3661 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3663 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
3667 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
3668 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
3669 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3674 /* install the nh neigh in kernel */
3675 zl3vni_nh_install(zl3vni
, nh
);
3678 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
3683 /* handle nh neigh delete */
3684 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
3685 struct prefix
*host_prefix
)
3687 rb_delete_host(&nh
->host_rb
, host_prefix
);
3689 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
3690 /* uninstall from kernel */
3691 zl3vni_nh_uninstall(zl3vni
, nh
);
3693 /* delete the nh entry */
3694 zl3vni_nh_del(zl3vni
, nh
);
3698 /* handle neigh update from kernel - the only thing of interest is to
3699 * readd stale entries.
3701 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3705 zebra_neigh_t
*n
= NULL
;
3707 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3711 /* all next hop neigh are remote and installed by frr.
3712 * If the kernel has aged this entry, re-install.
3714 if (state
& NUD_STALE
)
3715 zl3vni_nh_install(zl3vni
, n
);
3720 /* handle neigh delete from kernel */
3721 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3723 zebra_neigh_t
*n
= NULL
;
3725 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3729 /* all next hop neigh are remote and installed by frr.
3730 * If we get an age out notification for these neigh entries, we have to
3733 zl3vni_nh_install(zl3vni
, n
);
3739 * Hash function for L3 VNI.
3741 static unsigned int l3vni_hash_keymake(void *p
)
3743 const zebra_l3vni_t
*zl3vni
= p
;
3745 return jhash_1word(zl3vni
->vni
, 0);
3749 * Compare 2 L3 VNI hash entries.
3751 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
3753 const zebra_l3vni_t
*zl3vni1
= p1
;
3754 const zebra_l3vni_t
*zl3vni2
= p2
;
3756 return (zl3vni1
->vni
== zl3vni2
->vni
);
3760 * Callback to allocate L3 VNI hash entry.
3762 static void *zl3vni_alloc(void *p
)
3764 zebra_l3vni_t
*zl3vni
= NULL
;
3765 const zebra_l3vni_t
*tmp_l3vni
= p
;
3767 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
3768 zl3vni
->vni
= tmp_l3vni
->vni
;
3769 return ((void *)zl3vni
);
3773 * Look up L3 VNI hash entry.
3775 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
3777 zebra_l3vni_t tmp_l3vni
;
3778 zebra_l3vni_t
*zl3vni
= NULL
;
3780 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
3781 tmp_l3vni
.vni
= vni
;
3782 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
3788 * Add L3 VNI hash entry.
3790 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
3792 zebra_l3vni_t tmp_zl3vni
;
3793 zebra_l3vni_t
*zl3vni
= NULL
;
3795 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
3796 tmp_zl3vni
.vni
= vni
;
3798 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
3801 zl3vni
->vrf_id
= vrf_id
;
3802 zl3vni
->svi_if
= NULL
;
3803 zl3vni
->vxlan_if
= NULL
;
3804 zl3vni
->l2vnis
= list_new();
3805 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
3807 /* Create hash table for remote RMAC */
3808 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
3809 "Zebra L3-VNI RMAC-Table");
3811 /* Create hash table for neighbors */
3812 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3813 "Zebra L3-VNI next-hop table");
3819 * Delete L3 VNI hash entry.
3821 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
3823 zebra_l3vni_t
*tmp_zl3vni
;
3825 /* free the list of l2vnis */
3826 list_delete(&zl3vni
->l2vnis
);
3827 zl3vni
->l2vnis
= NULL
;
3829 /* Free the rmac table */
3830 hash_free(zl3vni
->rmac_table
);
3831 zl3vni
->rmac_table
= NULL
;
3833 /* Free the nh table */
3834 hash_free(zl3vni
->nh_table
);
3835 zl3vni
->nh_table
= NULL
;
3837 /* Free the VNI hash entry and allocated memory. */
3838 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
3840 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
3845 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
3847 struct zebra_ns
*zns
= NULL
;
3848 struct route_node
*rn
= NULL
;
3849 struct interface
*ifp
= NULL
;
3851 /* loop through all vxlan-interface */
3852 zns
= zebra_ns_lookup(NS_DEFAULT
);
3853 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3855 struct zebra_if
*zif
= NULL
;
3856 struct zebra_l2info_vxlan
*vxl
= NULL
;
3858 ifp
= (struct interface
*)rn
->info
;
3863 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3866 vxl
= &zif
->l2info
.vxl
;
3867 if (vxl
->vni
== zl3vni
->vni
) {
3868 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3876 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
3878 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
3879 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
3884 if (!zl3vni
->vxlan_if
)
3887 zif
= zl3vni
->vxlan_if
->info
;
3891 vxl
= &zif
->l2info
.vxl
;
3893 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3896 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
3898 struct zebra_vrf
*zvrf
= NULL
;
3900 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
3904 return zl3vni_lookup(zvrf
->l3vni
);
3908 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3909 * neighbor notifications, to see if they are of interest.
3911 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
3912 struct interface
*br_if
)
3916 uint8_t bridge_vlan_aware
= 0;
3917 zebra_l3vni_t
*zl3vni
= NULL
;
3918 struct zebra_ns
*zns
= NULL
;
3919 struct route_node
*rn
= NULL
;
3920 struct zebra_if
*zif
= NULL
;
3921 struct interface
*tmp_if
= NULL
;
3922 struct zebra_l2info_bridge
*br
= NULL
;
3923 struct zebra_l2info_vxlan
*vxl
= NULL
;
3928 /* Make sure the linked interface is a bridge. */
3929 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3932 /* Determine if bridge is VLAN-aware or not */
3935 br
= &zif
->l2info
.br
;
3936 bridge_vlan_aware
= br
->vlan_aware
;
3937 if (bridge_vlan_aware
) {
3938 struct zebra_l2info_vlan
*vl
;
3940 if (!IS_ZEBRA_IF_VLAN(ifp
))
3945 vl
= &zif
->l2info
.vl
;
3949 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3950 /* TODO: Optimize with a hash. */
3951 zns
= zebra_ns_lookup(NS_DEFAULT
);
3952 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3953 tmp_if
= (struct interface
*)rn
->info
;
3957 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3959 if (!if_is_operative(tmp_if
))
3961 vxl
= &zif
->l2info
.vxl
;
3963 if (zif
->brslave_info
.br_if
!= br_if
)
3966 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3975 zl3vni
= zl3vni_lookup(vxl
->vni
);
3980 * Inform BGP about l3-vni.
3982 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
3984 struct stream
*s
= NULL
;
3985 struct zserv
*client
= NULL
;
3986 struct ethaddr rmac
;
3987 char buf
[ETHER_ADDR_STRLEN
];
3989 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3990 /* BGP may not be running. */
3995 memset(&rmac
, 0, sizeof(struct ethaddr
));
3996 zl3vni_get_rmac(zl3vni
, &rmac
);
3998 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4000 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4001 stream_putl(s
, zl3vni
->vni
);
4002 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4003 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4004 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4006 /* Write packet size. */
4007 stream_putw_at(s
, 0, stream_get_endp(s
));
4009 if (IS_ZEBRA_DEBUG_VXLAN
)
4011 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4012 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4013 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
4014 inet_ntoa(zl3vni
->local_vtep_ip
),
4015 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
4016 ? "prefix-routes-only"
4018 zebra_route_string(client
->proto
));
4020 client
->l3vniadd_cnt
++;
4021 return zserv_send_message(client
, s
);
4025 * Inform BGP about local l3-VNI deletion.
4027 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
4029 struct stream
*s
= NULL
;
4030 struct zserv
*client
= NULL
;
4032 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4033 /* BGP may not be running. */
4037 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4039 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
4040 stream_putl(s
, zl3vni
->vni
);
4042 /* Write packet size. */
4043 stream_putw_at(s
, 0, stream_get_endp(s
));
4045 if (IS_ZEBRA_DEBUG_VXLAN
)
4046 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
4047 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4048 zebra_route_string(client
->proto
));
4050 client
->l3vnidel_cnt
++;
4051 return zserv_send_message(client
, s
);
4054 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
4059 /* send l3vni add to BGP */
4060 zl3vni_send_add_to_client(zl3vni
);
4063 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
4068 /* send l3-vni del to BGP*/
4069 zl3vni_send_del_to_client(zl3vni
);
4072 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
, void *ctxt
)
4074 zebra_vni_t
*zvni
= (zebra_vni_t
*)backet
->data
;
4075 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
4077 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
4078 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4082 * handle transition of vni from l2 to l3 and vice versa
4084 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
4087 zebra_vni_t
*zvni
= NULL
;
4089 /* There is a possibility that VNI notification was already received
4090 * from kernel and we programmed it as L2-VNI
4091 * In such a case we need to delete this L2-VNI first, so
4092 * that it can be reprogrammed as L3-VNI in the system. It is also
4093 * possible that the vrf-vni mapping is removed from FRR while the vxlan
4094 * interface is still present in kernel. In this case to keep it
4095 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
4098 /* Locate hash entry */
4099 zvni
= zvni_lookup(vni
);
4103 if (IS_ZEBRA_DEBUG_VXLAN
)
4104 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
4106 /* Delete VNI from BGP. */
4107 zvni_send_del_to_client(zvni
->vni
);
4109 /* Free up all neighbors and MAC, if any. */
4110 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
4111 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
4113 /* Free up all remote VTEPs, if any. */
4114 zvni_vtep_del_all(zvni
, 0);
4116 /* Delete the hash entry. */
4117 if (zvni_del(zvni
)) {
4118 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
4119 "Failed to del VNI hash %p, VNI %u", zvni
,
4124 /* TODO_MITESH: This needs to be thought through. We don't have
4125 * enough information at this point to reprogram the vni as
4126 * l2-vni. One way is to store the required info in l3-vni and
4127 * used it solely for this purpose
4134 /* delete and uninstall rmac hash entry */
4135 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
, void *ctx
)
4137 zebra_mac_t
*zrmac
= NULL
;
4138 zebra_l3vni_t
*zl3vni
= NULL
;
4140 zrmac
= (zebra_mac_t
*)backet
->data
;
4141 zl3vni
= (zebra_l3vni_t
*)ctx
;
4142 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4143 zl3vni_rmac_del(zl3vni
, zrmac
);
4146 /* delete and uninstall nh hash entry */
4147 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
, void *ctx
)
4149 zebra_neigh_t
*n
= NULL
;
4150 zebra_l3vni_t
*zl3vni
= NULL
;
4152 n
= (zebra_neigh_t
*)backet
->data
;
4153 zl3vni
= (zebra_l3vni_t
*)ctx
;
4154 zl3vni_nh_uninstall(zl3vni
, n
);
4155 zl3vni_nh_del(zl3vni
, n
);
4158 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
4161 struct zserv
*client
= NULL
;
4162 struct stream
*s
= NULL
;
4163 char buf
[PREFIX_STRLEN
];
4165 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4166 /* BGP may not be running. */
4170 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4172 zclient_create_header(s
, cmd
, vrf_id
);
4173 stream_put(s
, p
, sizeof(struct prefix
));
4175 /* Write packet size. */
4176 stream_putw_at(s
, 0, stream_get_endp(s
));
4178 if (IS_ZEBRA_DEBUG_VXLAN
)
4179 zlog_debug("Send ip prefix %s %s on vrf %s",
4180 prefix2str(p
, buf
, sizeof(buf
)),
4181 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
4182 vrf_id_to_name(vrf_id
));
4184 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
4185 client
->prefixadd_cnt
++;
4187 client
->prefixdel_cnt
++;
4189 return zserv_send_message(client
, s
);
4192 /* re-add remote rmac if needed */
4193 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
4194 struct ethaddr
*rmac
)
4196 char buf
[ETHER_ADDR_STRLEN
];
4197 zebra_mac_t
*zrmac
= NULL
;
4199 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4203 if (IS_ZEBRA_DEBUG_VXLAN
)
4204 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
4205 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
4207 zl3vni_rmac_install(zl3vni
, zrmac
);
4211 /* Process a remote MACIP add from BGP. */
4212 static void process_remote_macip_add(vni_t vni
,
4213 struct ethaddr
*macaddr
,
4215 struct ipaddr
*ipaddr
,
4218 struct in_addr vtep_ip
)
4221 zebra_vtep_t
*zvtep
;
4222 zebra_mac_t
*mac
, *old_mac
;
4223 zebra_neigh_t
*n
= NULL
;
4224 int update_mac
= 0, update_neigh
= 0;
4225 char buf
[ETHER_ADDR_STRLEN
];
4226 char buf1
[INET6_ADDRSTRLEN
];
4227 struct interface
*ifp
= NULL
;
4228 struct zebra_if
*zif
= NULL
;
4234 /* Locate VNI hash entry - expected to exist. */
4235 zvni
= zvni_lookup(vni
);
4237 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
4241 ifp
= zvni
->vxlan_if
;
4245 !if_is_operative(ifp
) ||
4247 !zif
->brslave_info
.br_if
) {
4248 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
4253 /* The remote VTEP specified should normally exist, but it is
4254 * possible that when peering comes up, peer may advertise MACIP
4255 * routes before advertising type-3 routes.
4257 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
4259 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
4261 EC_ZEBRA_VTEP_ADD_FAILED
,
4262 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
4267 zvni_vtep_install(zvni
, &vtep_ip
);
4270 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
4271 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
4272 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
4274 mac
= zvni_mac_lookup(zvni
, macaddr
);
4276 /* Ignore if the mac is already present as a gateway mac */
4278 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
4279 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
4280 if (IS_ZEBRA_DEBUG_VXLAN
)
4281 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
4283 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4284 ipa_len
? " IP " : "",
4286 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
4290 /* check if the remote MAC is unknown or has a change.
4291 * If so, that needs to be updated first. Note that client could
4292 * install MAC and MACIP separately or just install the latter.
4295 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
4296 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
4297 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
4298 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
4299 || seq
!= mac
->rem_seq
)
4304 mac
= zvni_mac_add(zvni
, macaddr
);
4307 "Failed to add MAC %s VNI %u Remote VTEP %s",
4308 prefix_mac2str(macaddr
, buf
,
4310 vni
, inet_ntoa(vtep_ip
));
4314 /* Is this MAC created for a MACIP? */
4316 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
4318 const char *mac_type
;
4320 /* When host moves but changes its (MAC,IP)
4321 * binding, BGP may install a MACIP entry that
4322 * corresponds to "older" location of the host
4323 * in transient situations (because {IP1,M1}
4324 * is a different route from {IP1,M2}). Check
4325 * the sequence number and ignore this update
4328 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
4329 tmp_seq
= mac
->loc_seq
;
4332 tmp_seq
= mac
->rem_seq
;
4333 mac_type
= "remote";
4335 if (seq
< tmp_seq
) {
4336 if (IS_ZEBRA_DEBUG_VXLAN
)
4337 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
4339 prefix_mac2str(macaddr
,
4341 ipa_len
? " IP " : "",
4344 buf1
, sizeof(buf1
)) : "",
4351 /* Remove local MAC from BGP. */
4352 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
4353 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
4355 /* Set "auto" and "remote" forwarding info. */
4356 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
4357 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
4358 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
4359 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
4362 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
4364 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
4367 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
4369 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
4371 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
4373 /* Install the entry. */
4374 zvni_mac_install(zvni
, mac
);
4378 /* Update seq number. */
4381 /* If there is no IP, return after clearing AUTO flag of MAC. */
4383 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
4387 /* Check if the remote neighbor itself is unknown or has a
4388 * change. If so, create or update and then install the entry.
4390 n
= zvni_neigh_lookup(zvni
, ipaddr
);
4392 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
4393 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
4394 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
4395 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
4396 || seq
!= n
->rem_seq
)
4401 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
4404 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
4405 ipaddr2str(ipaddr
, buf1
,
4407 prefix_mac2str(macaddr
, buf
,
4409 vni
, inet_ntoa(vtep_ip
));
4416 /* When host moves but changes its (MAC,IP)
4417 * binding, BGP may install a MACIP entry that
4418 * corresponds to "older" location of the host
4419 * in transient situations (because {IP1,M1}
4420 * is a different route from {IP1,M2}). Check
4421 * the sequence number and ignore this update
4424 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
4425 tmp_seq
= n
->loc_seq
;
4428 tmp_seq
= n
->rem_seq
;
4431 if (seq
< tmp_seq
) {
4432 if (IS_ZEBRA_DEBUG_VXLAN
)
4433 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
4435 prefix_mac2str(macaddr
,
4438 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
4443 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
4444 /* MAC change, send a delete for old
4445 * neigh if learnt locally.
4447 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
4448 IS_ZEBRA_NEIGH_ACTIVE(n
))
4449 zvni_neigh_send_del_to_client(
4453 /* update neigh list for macs */
4454 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
4456 listnode_delete(old_mac
->neigh_list
, n
);
4457 zvni_deref_ip2mac(zvni
, old_mac
);
4459 listnode_add_sort(mac
->neigh_list
, n
);
4460 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
4464 /* Set "remote" forwarding info. */
4465 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
4466 n
->r_vtep_ip
= vtep_ip
;
4467 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4469 /* Set router flag (R-bit) to this Neighbor entry */
4470 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
4471 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
4473 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
4475 /* Install the entry. */
4476 zvni_neigh_install(zvni
, n
);
4479 /* Update seq number. */
4483 /* Process a remote MACIP delete from BGP. */
4484 static void process_remote_macip_del(vni_t vni
,
4485 struct ethaddr
*macaddr
,
4487 struct ipaddr
*ipaddr
,
4488 struct in_addr vtep_ip
)
4491 zebra_mac_t
*mac
= NULL
;
4492 zebra_neigh_t
*n
= NULL
;
4493 struct interface
*ifp
= NULL
;
4494 struct zebra_if
*zif
= NULL
;
4495 char buf
[ETHER_ADDR_STRLEN
];
4496 char buf1
[INET6_ADDRSTRLEN
];
4498 /* Locate VNI hash entry - expected to exist. */
4499 zvni
= zvni_lookup(vni
);
4501 if (IS_ZEBRA_DEBUG_VXLAN
)
4502 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
4506 ifp
= zvni
->vxlan_if
;
4510 !if_is_operative(ifp
) ||
4512 !zif
->brslave_info
.br_if
) {
4513 if (IS_ZEBRA_DEBUG_VXLAN
)
4514 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
4519 /* The remote VTEP specified is normally expected to exist, but
4520 * it is possible that the peer may delete the VTEP before deleting
4521 * any MACs referring to the VTEP, in which case the handler (see
4522 * remote_vtep_del) would have already deleted the MACs.
4524 if (!zvni_vtep_find(zvni
, &vtep_ip
))
4527 mac
= zvni_mac_lookup(zvni
, macaddr
);
4529 n
= zvni_neigh_lookup(zvni
, ipaddr
);
4532 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
4533 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4534 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
4538 /* If the remote mac or neighbor doesn't exist there is nothing
4539 * more to do. Otherwise, uninstall the entry and then remove it.
4544 /* Ignore the delete if this mac is a gateway mac-ip */
4546 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
4547 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
4549 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
4551 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4552 ipa_len
? " IP " : "",
4554 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
4558 /* Uninstall remote neighbor or MAC. */
4560 /* When the MAC changes for an IP, it is possible the
4561 * client may update the new MAC before trying to delete the
4562 * "old" neighbor (as these are two different MACIP routes).
4563 * Do the delete only if the MAC matches.
4565 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
4566 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
4567 zvni_neigh_uninstall(zvni
, n
);
4568 zvni_neigh_del(zvni
, n
);
4569 zvni_deref_ip2mac(zvni
, mac
);
4572 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
4573 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
4575 * the remote sequence number in the auto mac entry
4576 * needs to be reset to 0 as the mac entry may have
4577 * been removed on all VTEPs (including
4578 * the originating one)
4582 /* If all remote neighbors referencing a remote MAC
4583 * go away, we need to uninstall the MAC.
4585 if (remote_neigh_count(mac
) == 0) {
4586 zvni_mac_uninstall(zvni
, mac
);
4587 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
4589 if (list_isempty(mac
->neigh_list
))
4590 zvni_mac_del(zvni
, mac
);
4592 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
4598 /* Public functions */
4600 int is_l3vni_for_prefix_routes_only(vni_t vni
)
4602 zebra_l3vni_t
*zl3vni
= NULL
;
4604 zl3vni
= zl3vni_lookup(vni
);
4608 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
4611 /* handle evpn route in vrf table */
4612 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
4613 struct ipaddr
*vtep_ip
,
4614 struct prefix
*host_prefix
)
4616 zebra_l3vni_t
*zl3vni
= NULL
;
4617 struct ipaddr ipv4_vtep
;
4619 zl3vni
= zl3vni_from_vrf(vrf_id
);
4620 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
4624 * add the next hop neighbor -
4625 * neigh to be installed is the ipv6 nexthop neigh
4627 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
4630 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
4631 * address. Rmac is programmed against the ipv4 vtep because we only
4632 * support ipv4 tunnels in the h/w right now
4634 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
4635 ipv4_vtep
.ipa_type
= IPADDR_V4
;
4636 if (vtep_ip
->ipa_type
== IPADDR_V6
)
4637 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
4638 &(ipv4_vtep
.ipaddr_v4
));
4640 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
4641 sizeof(struct in_addr
));
4644 * add the rmac - remote rmac to be installed is against the ipv4
4647 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
4650 /* handle evpn vrf route delete */
4651 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
4652 struct ipaddr
*vtep_ip
,
4653 struct prefix
*host_prefix
)
4655 zebra_l3vni_t
*zl3vni
= NULL
;
4656 zebra_neigh_t
*nh
= NULL
;
4657 zebra_mac_t
*zrmac
= NULL
;
4659 zl3vni
= zl3vni_from_vrf(vrf_id
);
4663 /* find the next hop entry and rmac entry */
4664 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4667 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
4669 /* delete the next hop entry */
4670 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
4672 /* delete the rmac entry */
4674 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
4678 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
4679 struct ethaddr
*rmac
, bool use_json
)
4681 zebra_l3vni_t
*zl3vni
= NULL
;
4682 zebra_mac_t
*zrmac
= NULL
;
4683 json_object
*json
= NULL
;
4685 if (!is_evpn_enabled()) {
4687 vty_out(vty
, "{}\n");
4692 json
= json_object_new_object();
4694 zl3vni
= zl3vni_lookup(l3vni
);
4697 vty_out(vty
, "{}\n");
4699 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
4703 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4706 vty_out(vty
, "{}\n");
4709 "%% Requested RMAC doesn't exist in L3-VNI %u",
4714 zl3vni_print_rmac(zrmac
, vty
, json
);
4717 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4718 json
, JSON_C_TO_STRING_PRETTY
));
4719 json_object_free(json
);
4723 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
4725 zebra_l3vni_t
*zl3vni
;
4727 struct rmac_walk_ctx wctx
;
4728 json_object
*json
= NULL
;
4730 if (!is_evpn_enabled())
4733 zl3vni
= zl3vni_lookup(l3vni
);
4736 vty_out(vty
, "{}\n");
4738 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4741 num_rmacs
= hashcount(zl3vni
->rmac_table
);
4746 json
= json_object_new_object();
4748 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
4752 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
4754 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
4756 json_object_int_add(json
, "numRmacs", num_rmacs
);
4758 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
4761 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4762 json
, JSON_C_TO_STRING_PRETTY
));
4763 json_object_free(json
);
4767 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
4769 json_object
*json
= NULL
;
4772 if (!is_evpn_enabled()) {
4774 vty_out(vty
, "{}\n");
4779 json
= json_object_new_object();
4783 hash_iterate(zrouter
.l3vni_table
,
4784 (void (*)(struct hash_backet
*,
4785 void *))zl3vni_print_rmac_hash_all_vni
,
4789 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4790 json
, JSON_C_TO_STRING_PRETTY
));
4791 json_object_free(json
);
4795 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
4796 struct ipaddr
*ip
, bool use_json
)
4798 zebra_l3vni_t
*zl3vni
= NULL
;
4799 zebra_neigh_t
*n
= NULL
;
4800 json_object
*json
= NULL
;
4802 if (!is_evpn_enabled()) {
4804 vty_out(vty
, "{}\n");
4809 json
= json_object_new_object();
4811 zl3vni
= zl3vni_lookup(l3vni
);
4814 vty_out(vty
, "{}\n");
4816 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4820 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4823 vty_out(vty
, "{}\n");
4826 "%% Requested next-hop not present for L3-VNI %u",
4831 zl3vni_print_nh(n
, vty
, json
);
4834 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4835 json
, JSON_C_TO_STRING_PRETTY
));
4836 json_object_free(json
);
4840 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
4843 struct nh_walk_ctx wctx
;
4844 json_object
*json
= NULL
;
4845 zebra_l3vni_t
*zl3vni
= NULL
;
4847 if (!is_evpn_enabled())
4850 zl3vni
= zl3vni_lookup(l3vni
);
4853 vty_out(vty
, "{}\n");
4855 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4859 num_nh
= hashcount(zl3vni
->nh_table
);
4864 json
= json_object_new_object();
4869 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
4871 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
4873 json_object_int_add(json
, "numNextHops", num_nh
);
4875 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
4878 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4879 json
, JSON_C_TO_STRING_PRETTY
));
4880 json_object_free(json
);
4884 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
4886 json_object
*json
= NULL
;
4889 if (!is_evpn_enabled()) {
4891 vty_out(vty
, "{}\n");
4896 json
= json_object_new_object();
4900 hash_iterate(zrouter
.l3vni_table
,
4901 (void (*)(struct hash_backet
*,
4902 void *))zl3vni_print_nh_hash_all_vni
,
4906 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4907 json
, JSON_C_TO_STRING_PRETTY
));
4908 json_object_free(json
);
4913 * Display L3 VNI information (VTY command handler).
4915 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
4918 json_object
*json
= NULL
;
4919 zebra_l3vni_t
*zl3vni
= NULL
;
4921 if (!is_evpn_enabled()) {
4923 vty_out(vty
, "{}\n");
4927 zl3vni
= zl3vni_lookup(vni
);
4930 vty_out(vty
, "{}\n");
4932 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4937 json
= json_object_new_object();
4941 zl3vni_print(zl3vni
, (void *)args
);
4944 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4945 json
, JSON_C_TO_STRING_PRETTY
));
4946 json_object_free(json
);
4950 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4951 json_object
*json_vrfs
)
4953 char buf
[ETHER_ADDR_STRLEN
];
4954 zebra_l3vni_t
*zl3vni
= NULL
;
4956 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4961 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
4962 zvrf_name(zvrf
), zl3vni
->vni
,
4963 zl3vni_vxlan_if_name(zl3vni
),
4964 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
4965 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4967 json_object
*json_vrf
= NULL
;
4969 json_vrf
= json_object_new_object();
4970 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
4971 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
4972 json_object_string_add(json_vrf
, "vxlanIntf",
4973 zl3vni_vxlan_if_name(zl3vni
));
4974 json_object_string_add(json_vrf
, "sviIntf",
4975 zl3vni_svi_if_name(zl3vni
));
4976 json_object_string_add(json_vrf
, "state",
4977 zl3vni_state2str(zl3vni
));
4978 json_object_string_add(
4979 json_vrf
, "routerMac",
4980 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4981 json_object_array_add(json_vrfs
, json_vrf
);
4986 * Display Neighbors for a VNI (VTY command handler).
4988 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4989 vni_t vni
, bool use_json
)
4993 struct neigh_walk_ctx wctx
;
4994 json_object
*json
= NULL
;
4996 if (!is_evpn_enabled())
4998 zvni
= zvni_lookup(vni
);
5001 vty_out(vty
, "{}\n");
5003 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5006 num_neigh
= hashcount(zvni
->neigh_table
);
5011 json
= json_object_new_object();
5013 /* Since we have IPv6 addresses to deal with which can vary widely in
5014 * size, we try to be a bit more elegant in display by first computing
5015 * the maximum width.
5017 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
5020 wctx
.addr_width
= 15;
5022 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
5026 "Number of ARPs (local and remote) known for this VNI: %u\n",
5028 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
5029 -wctx
.addr_width
, "IP", "Type",
5030 "State", "MAC", "Remote VTEP");
5032 json_object_int_add(json
, "numArpNd", num_neigh
);
5034 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
5036 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5037 json
, JSON_C_TO_STRING_PRETTY
));
5038 json_object_free(json
);
5043 * Display neighbors across all VNIs (VTY command handler).
5045 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5048 json_object
*json
= NULL
;
5051 if (!is_evpn_enabled())
5055 json
= json_object_new_object();
5059 hash_iterate(zvrf
->vni_table
,
5060 (void (*)(struct hash_backet
*,
5061 void *))zvni_print_neigh_hash_all_vni
,
5064 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5065 json
, JSON_C_TO_STRING_PRETTY
));
5066 json_object_free(json
);
5071 * Display specific neighbor for a VNI, if present (VTY command handler).
5073 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
5074 struct zebra_vrf
*zvrf
, vni_t vni
,
5075 struct ipaddr
*ip
, bool use_json
)
5079 json_object
*json
= NULL
;
5081 if (!is_evpn_enabled())
5083 zvni
= zvni_lookup(vni
);
5086 vty_out(vty
, "{}\n");
5088 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5091 n
= zvni_neigh_lookup(zvni
, ip
);
5095 "%% Requested neighbor does not exist in VNI %u\n",
5100 json
= json_object_new_object();
5102 zvni_print_neigh(n
, vty
, json
);
5105 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5106 json
, JSON_C_TO_STRING_PRETTY
));
5107 json_object_free(json
);
5112 * Display neighbors for a VNI from specific VTEP (VTY command handler).
5113 * By definition, these are remote neighbors.
5115 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5116 vni_t vni
, struct in_addr vtep_ip
,
5121 struct neigh_walk_ctx wctx
;
5122 json_object
*json
= NULL
;
5124 if (!is_evpn_enabled())
5126 zvni
= zvni_lookup(vni
);
5129 vty_out(vty
, "{}\n");
5131 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5134 num_neigh
= hashcount(zvni
->neigh_table
);
5138 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
5141 wctx
.addr_width
= 15;
5142 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
5143 wctx
.r_vtep_ip
= vtep_ip
;
5145 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
5146 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
5149 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5150 json
, JSON_C_TO_STRING_PRETTY
));
5151 json_object_free(json
);
5156 * Display MACs for a VNI (VTY command handler).
5158 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5159 vni_t vni
, bool use_json
)
5163 struct mac_walk_ctx wctx
;
5164 json_object
*json
= NULL
;
5165 json_object
*json_mac
= NULL
;
5167 if (!is_evpn_enabled())
5169 zvni
= zvni_lookup(vni
);
5172 vty_out(vty
, "{}\n");
5174 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5177 num_macs
= num_valid_macs(zvni
);
5182 json
= json_object_new_object();
5183 json_mac
= json_object_new_object();
5186 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5189 wctx
.json
= json_mac
;
5193 "Number of MACs (local and remote) known for this VNI: %u\n",
5195 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
5196 "Intf/Remote VTEP", "VLAN");
5198 json_object_int_add(json
, "numMacs", num_macs
);
5200 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
5203 json_object_object_add(json
, "macs", json_mac
);
5204 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5205 json
, JSON_C_TO_STRING_PRETTY
));
5206 json_object_free(json
);
5211 * Display MACs for all VNIs (VTY command handler).
5213 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5216 struct mac_walk_ctx wctx
;
5217 json_object
*json
= NULL
;
5219 if (!is_evpn_enabled()) {
5221 vty_out(vty
, "{}\n");
5225 json
= json_object_new_object();
5227 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5230 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
5233 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5234 json
, JSON_C_TO_STRING_PRETTY
));
5235 json_object_free(json
);
5240 * Display MACs for all VNIs (VTY command handler).
5242 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
5243 struct zebra_vrf
*zvrf
,
5244 struct in_addr vtep_ip
, bool use_json
)
5246 struct mac_walk_ctx wctx
;
5247 json_object
*json
= NULL
;
5249 if (!is_evpn_enabled())
5253 json
= json_object_new_object();
5255 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5257 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
5258 wctx
.r_vtep_ip
= vtep_ip
;
5260 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
5263 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5264 json
, JSON_C_TO_STRING_PRETTY
));
5265 json_object_free(json
);
5270 * Display specific MAC for a VNI, if present (VTY command handler).
5272 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5273 vni_t vni
, struct ethaddr
*macaddr
,
5278 json_object
*json
= NULL
;
5280 if (!is_evpn_enabled())
5283 zvni
= zvni_lookup(vni
);
5286 vty_out(vty
, "{}\n");
5288 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5291 mac
= zvni_mac_lookup(zvni
, macaddr
);
5294 vty_out(vty
, "{}\n");
5297 "%% Requested MAC does not exist in VNI %u\n",
5303 json
= json_object_new_object();
5305 zvni_print_mac(mac
, vty
, json
);
5309 * Display MACs for a VNI from specific VTEP (VTY command handler).
5311 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5312 vni_t vni
, struct in_addr vtep_ip
,
5317 struct mac_walk_ctx wctx
;
5318 json_object
*json
= NULL
;
5319 json_object
*json_mac
= NULL
;
5321 if (!is_evpn_enabled())
5323 zvni
= zvni_lookup(vni
);
5326 vty_out(vty
, "{}\n");
5328 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5331 num_macs
= num_valid_macs(zvni
);
5336 json
= json_object_new_object();
5337 json_mac
= json_object_new_object();
5340 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5343 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
5344 wctx
.r_vtep_ip
= vtep_ip
;
5345 wctx
.json
= json_mac
;
5346 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
5349 json_object_int_add(json
, "numMacs", wctx
.count
);
5351 json_object_object_add(json
, "macs", json_mac
);
5352 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5353 json
, JSON_C_TO_STRING_PRETTY
));
5354 json_object_free(json
);
5360 * Display VNI information (VTY command handler).
5362 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
5365 json_object
*json
= NULL
;
5367 zebra_l3vni_t
*zl3vni
= NULL
;
5368 zebra_vni_t
*zvni
= NULL
;
5370 if (!is_evpn_enabled())
5374 json
= json_object_new_object();
5378 zl3vni
= zl3vni_lookup(vni
);
5380 zl3vni_print(zl3vni
, (void *)args
);
5382 zvni
= zvni_lookup(vni
);
5385 vty_out(vty
, "{}\n");
5387 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5391 zvni_print(zvni
, (void *)args
);
5395 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5396 json
, JSON_C_TO_STRING_PRETTY
));
5397 json_object_free(json
);
5401 /* Display all global details for EVPN */
5402 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
5407 json_object
*json
= NULL
;
5408 struct zebra_vrf
*zvrf
= NULL
;
5410 if (!is_evpn_enabled())
5413 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
5417 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
5418 num_l2vnis
= hashcount(zvrf
->vni_table
);
5419 num_vnis
= num_l2vnis
+ num_l3vnis
;
5422 json
= json_object_new_object();
5423 json_object_string_add(json
, "advertiseGatewayMacip",
5424 zvrf
->advertise_gw_macip
? "Yes" : "No");
5425 json_object_int_add(json
, "numVnis", num_vnis
);
5426 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
5427 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
5429 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
5430 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
5431 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
5432 zvrf
->advertise_gw_macip
? "Yes" : "No");
5436 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5437 json
, JSON_C_TO_STRING_PRETTY
));
5438 json_object_free(json
);
5443 * Display VNI hash table (VTY command handler).
5445 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5448 json_object
*json
= NULL
;
5451 if (!is_evpn_enabled())
5455 json
= json_object_new_object();
5457 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
5458 "Type", "VxLAN IF", "# MACs", "# ARPs",
5459 "# Remote VTEPs", "Tenant VRF");
5464 /* Display all L2-VNIs */
5465 hash_iterate(zvrf
->vni_table
,
5466 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
5469 /* Display all L3-VNIs */
5470 hash_iterate(zrouter
.l3vni_table
,
5471 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
5475 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5476 json
, JSON_C_TO_STRING_PRETTY
));
5477 json_object_free(json
);
5482 * Display VNI hash table in detail(VTY command handler).
5484 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5487 json_object
*json
= NULL
;
5488 struct zebra_ns
*zns
= NULL
;
5489 struct zvni_evpn_show zes
;
5491 if (!is_evpn_enabled())
5494 zns
= zebra_ns_lookup(NS_DEFAULT
);
5500 json
= json_object_new_object();
5506 /* Display all L2-VNIs */
5507 hash_iterate(zvrf
->vni_table
, (void (*)(struct hash_backet
*,
5508 void *))zvni_print_hash_detail
,
5511 /* Display all L3-VNIs */
5512 hash_iterate(zrouter
.l3vni_table
,
5513 (void (*)(struct hash_backet
*,
5514 void *))zl3vni_print_hash_detail
,
5518 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5519 json
, JSON_C_TO_STRING_PRETTY
));
5520 json_object_free(json
);
5525 * Handle neighbor delete notification from the kernel (on a VLAN device
5526 * / L3 interface). This may result in either the neighbor getting deleted
5527 * from our database or being re-added to the kernel (if it is a valid
5530 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
5531 struct interface
*link_if
,
5534 char buf
[INET6_ADDRSTRLEN
];
5535 char buf2
[ETHER_ADDR_STRLEN
];
5536 zebra_neigh_t
*n
= NULL
;
5537 zebra_vni_t
*zvni
= NULL
;
5538 zebra_mac_t
*zmac
= NULL
;
5539 zebra_l3vni_t
*zl3vni
= NULL
;
5541 /* check if this is a remote neigh entry corresponding to remote
5544 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5546 return zl3vni_local_nh_del(zl3vni
, ip
);
5548 /* We are only interested in neighbors on an SVI that resides on top
5549 * of a VxLAN bridge.
5551 zvni
= zvni_from_svi(ifp
, link_if
);
5555 if (!zvni
->vxlan_if
) {
5557 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
5562 if (IS_ZEBRA_DEBUG_VXLAN
)
5563 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
5564 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
5565 ifp
->ifindex
, zvni
->vni
);
5567 /* If entry doesn't exist, nothing to do. */
5568 n
= zvni_neigh_lookup(zvni
, ip
);
5572 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
5574 if (IS_ZEBRA_DEBUG_VXLAN
)
5576 "Trying to del a neigh %s without a mac %s on VNI %u",
5577 ipaddr2str(ip
, buf
, sizeof(buf
)),
5578 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
5584 /* If it is a remote entry, the kernel has aged this out or someone has
5585 * deleted it, it needs to be re-installed as Quagga is the owner.
5587 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
5588 zvni_neigh_install(zvni
, n
);
5592 /* Remove neighbor from BGP. */
5593 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
5594 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0);
5596 /* Delete this neighbor entry. */
5597 zvni_neigh_del(zvni
, n
);
5599 /* see if the AUTO mac needs to be deleted */
5600 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
5601 && !listcount(zmac
->neigh_list
))
5602 zvni_mac_del(zvni
, zmac
);
5608 * Handle neighbor add or update notification from the kernel (on a VLAN
5609 * device / L3 interface). This is typically for a local neighbor but can
5610 * also be for a remote neighbor (e.g., ageout notification). It could
5611 * also be a "move" scenario.
5613 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
5614 struct interface
*link_if
,
5616 struct ethaddr
*macaddr
,
5621 char buf
[ETHER_ADDR_STRLEN
];
5622 char buf2
[INET6_ADDRSTRLEN
];
5623 zebra_vni_t
*zvni
= NULL
;
5624 zebra_l3vni_t
*zl3vni
= NULL
;
5626 /* check if this is a remote neigh entry corresponding to remote
5629 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5631 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
5633 /* We are only interested in neighbors on an SVI that resides on top
5634 * of a VxLAN bridge.
5636 zvni
= zvni_from_svi(ifp
, link_if
);
5640 if (IS_ZEBRA_DEBUG_VXLAN
)
5642 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
5643 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
5644 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5645 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
5646 is_router
? "router " : "",
5649 /* Is this about a local neighbor or a remote one? */
5651 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
5654 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
5659 * Handle message from client to delete a remote MACIP for a VNI.
5661 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
5665 struct ethaddr macaddr
;
5667 struct in_addr vtep_ip
;
5668 uint16_t l
= 0, ipa_len
;
5669 char buf
[ETHER_ADDR_STRLEN
];
5670 char buf1
[INET6_ADDRSTRLEN
];
5672 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5673 memset(&ip
, 0, sizeof(struct ipaddr
));
5674 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5678 while (l
< hdr
->length
) {
5679 /* Obtain each remote MACIP and process. */
5680 /* Message contains VNI, followed by MAC followed by IP (if any)
5681 * followed by remote VTEP IP.
5683 memset(&ip
, 0, sizeof(ip
));
5684 STREAM_GETL(s
, vni
);
5685 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5686 STREAM_GETL(s
, ipa_len
);
5688 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5690 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5692 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5693 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5694 l
+= IPV4_MAX_BYTELEN
;
5696 if (IS_ZEBRA_DEBUG_VXLAN
)
5698 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
5700 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5701 ipa_len
? " IP " : "",
5703 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
5705 zebra_route_string(client
->proto
));
5707 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
5715 * Handle message from client to add a remote MACIP for a VNI. This
5716 * could be just the add of a MAC address or the add of a neighbor
5719 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
5723 struct ethaddr macaddr
;
5725 struct in_addr vtep_ip
;
5726 uint16_t l
= 0, ipa_len
;
5729 char buf
[ETHER_ADDR_STRLEN
];
5730 char buf1
[INET6_ADDRSTRLEN
];
5732 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5733 memset(&ip
, 0, sizeof(struct ipaddr
));
5734 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5736 if (!EVPN_ENABLED(zvrf
)) {
5737 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
5743 while (l
< hdr
->length
) {
5744 /* Obtain each remote MACIP and process. */
5745 /* Message contains VNI, followed by MAC followed by IP (if any)
5746 * followed by remote VTEP IP.
5748 memset(&ip
, 0, sizeof(ip
));
5749 STREAM_GETL(s
, vni
);
5750 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5751 STREAM_GETL(s
, ipa_len
);
5753 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5755 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5757 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5758 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5759 l
+= IPV4_MAX_BYTELEN
;
5761 /* Get flags - sticky mac and/or gateway mac */
5762 STREAM_GETC(s
, flags
);
5764 STREAM_GETL(s
, seq
);
5767 if (IS_ZEBRA_DEBUG_VXLAN
)
5769 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
5771 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5772 ipa_len
? " IP " : "",
5774 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
5775 flags
, seq
, inet_ntoa(vtep_ip
),
5776 zebra_route_string(client
->proto
));
5778 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
5779 flags
, seq
, vtep_ip
);
5787 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5788 * us, this must involve a multihoming scenario. Treat this as implicit delete
5789 * of any prior local MAC.
5791 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
5792 struct interface
*br_if
,
5793 struct ethaddr
*macaddr
, vlanid_t vid
)
5795 struct zebra_if
*zif
;
5796 struct zebra_l2info_vxlan
*vxl
;
5800 char buf
[ETHER_ADDR_STRLEN
];
5804 vxl
= &zif
->l2info
.vxl
;
5807 /* Check if EVPN is enabled. */
5808 if (!is_evpn_enabled())
5811 /* Locate hash entry; it is expected to exist. */
5812 zvni
= zvni_lookup(vni
);
5816 /* If entry doesn't exist, nothing to do. */
5817 mac
= zvni_mac_lookup(zvni
, macaddr
);
5821 /* Is it a local entry? */
5822 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5825 if (IS_ZEBRA_DEBUG_VXLAN
)
5827 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5828 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5831 /* Remove MAC from BGP. */
5832 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5835 * If there are no neigh associated with the mac delete the mac
5836 * else mark it as AUTO for forward reference
5838 if (!listcount(mac
->neigh_list
)) {
5839 zvni_mac_del(zvni
, mac
);
5841 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5842 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5849 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5850 * This can happen because the remote MAC entries are also added as "dynamic",
5851 * so the kernel can ageout the entry.
5853 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
5854 struct interface
*br_if
,
5855 struct ethaddr
*macaddr
, vlanid_t vid
)
5857 struct zebra_if
*zif
= NULL
;
5858 struct zebra_l2info_vxlan
*vxl
= NULL
;
5860 zebra_vni_t
*zvni
= NULL
;
5861 zebra_l3vni_t
*zl3vni
= NULL
;
5862 zebra_mac_t
*mac
= NULL
;
5863 char buf
[ETHER_ADDR_STRLEN
];
5867 vxl
= &zif
->l2info
.vxl
;
5870 /* Check if EVPN is enabled. */
5871 if (!is_evpn_enabled())
5874 /* check if this is a remote RMAC and readd simillar to remote macs */
5875 zl3vni
= zl3vni_lookup(vni
);
5877 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
5879 /* Locate hash entry; it is expected to exist. */
5880 zvni
= zvni_lookup(vni
);
5884 /* If entry doesn't exist, nothing to do. */
5885 mac
= zvni_mac_lookup(zvni
, macaddr
);
5889 /* Is it a remote entry? */
5890 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
5893 if (IS_ZEBRA_DEBUG_VXLAN
)
5894 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
5895 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5898 zvni_mac_install(zvni
, mac
);
5903 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
5905 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
5906 struct ethaddr
*macaddr
, vlanid_t vid
)
5910 char buf
[ETHER_ADDR_STRLEN
];
5912 /* We are interested in MACs only on ports or (port, VLAN) that
5915 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5918 if (!zvni
->vxlan_if
) {
5920 "VNI %u hash %p doesn't have intf upon local MAC DEL",
5925 if (IS_ZEBRA_DEBUG_VXLAN
)
5926 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
5927 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5928 ifp
->ifindex
, vid
, zvni
->vni
);
5930 /* If entry doesn't exist, nothing to do. */
5931 mac
= zvni_mac_lookup(zvni
, macaddr
);
5935 /* Is it a local entry? */
5936 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5939 /* Update all the neigh entries associated with this mac */
5940 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
5942 /* Remove MAC from BGP. */
5943 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5946 * If there are no neigh associated with the mac delete the mac
5947 * else mark it as AUTO for forward reference
5949 if (!listcount(mac
->neigh_list
)) {
5950 zvni_mac_del(zvni
, mac
);
5952 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5953 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5960 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
5962 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
5963 struct interface
*br_if
,
5964 struct ethaddr
*macaddr
, vlanid_t vid
,
5969 char buf
[ETHER_ADDR_STRLEN
];
5970 bool mac_sticky
= false;
5971 bool inform_client
= false;
5972 bool upd_neigh
= false;
5974 /* We are interested in MACs only on ports or (port, VLAN) that
5977 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5979 if (IS_ZEBRA_DEBUG_VXLAN
)
5981 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5982 sticky
? "sticky " : "",
5983 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5984 ifp
->name
, ifp
->ifindex
, vid
);
5988 if (!zvni
->vxlan_if
) {
5990 "VNI %u hash %p doesn't have intf upon local MAC ADD",
5995 /* Check if we need to create or update or it is a NO-OP. */
5996 mac
= zvni_mac_lookup(zvni
, macaddr
);
5998 if (IS_ZEBRA_DEBUG_VXLAN
)
6000 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
6001 sticky
? "sticky " : "",
6002 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
6003 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
6005 mac
= zvni_mac_add(zvni
, macaddr
);
6008 EC_ZEBRA_MAC_ADD_FAILED
,
6009 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
6010 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
6011 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
6014 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
6015 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
6016 mac
->fwd_info
.local
.vid
= vid
;
6018 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
6019 inform_client
= true;
6022 if (IS_ZEBRA_DEBUG_VXLAN
)
6024 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
6025 sticky
? "sticky " : "",
6026 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
6027 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
6030 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6031 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
6035 * Update any changes and if changes are relevant to
6038 if (mac_sticky
== sticky
6039 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
6040 && mac
->fwd_info
.local
.vid
== vid
) {
6041 if (IS_ZEBRA_DEBUG_VXLAN
)
6043 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
6044 "entry exists and has not changed ",
6045 sticky
? "sticky " : "",
6046 prefix_mac2str(macaddr
, buf
,
6048 ifp
->name
, ifp
->ifindex
, vid
,
6052 if (mac_sticky
!= sticky
) {
6054 SET_FLAG(mac
->flags
,
6057 UNSET_FLAG(mac
->flags
,
6059 inform_client
= true;
6062 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
6063 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
6064 mac
->fwd_info
.local
.vid
= vid
;
6066 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
6067 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
6070 * MAC has either moved or was "internally" created due
6071 * to a neighbor learn and is now actually learnt. If
6072 * it was learnt as a remote sticky MAC, this is an
6075 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
6077 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
6078 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
6079 prefix_mac2str(macaddr
, buf
,
6081 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
6086 /* If an actual move, compute MAC's seq number */
6087 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
6088 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
6090 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
6091 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
6092 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
6093 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
6094 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
6095 mac
->fwd_info
.local
.vid
= vid
;
6097 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
6099 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
6101 * We have to inform BGP of this MAC as well as process
6104 inform_client
= true;
6109 /* Inform BGP if required. */
6110 if (inform_client
) {
6111 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
6112 mac
->flags
, mac
->loc_seq
))
6116 /* Process all neighbors associated with this MAC, if required. */
6118 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6124 * Handle message from client to delete a remote VTEP for a VNI.
6126 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
6129 unsigned short l
= 0;
6131 struct in_addr vtep_ip
;
6133 zebra_vtep_t
*zvtep
;
6134 struct interface
*ifp
;
6135 struct zebra_if
*zif
;
6137 if (!is_evpn_enabled()) {
6139 "%s: EVPN is not enabled yet we have received a vtep del command",
6140 __PRETTY_FUNCTION__
);
6144 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6145 zlog_debug("Recv MACIP DEL for non-default VRF %u",
6152 while (l
< hdr
->length
) {
6153 /* Obtain each remote VTEP and process. */
6154 STREAM_GETL(s
, vni
);
6156 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
6157 l
+= IPV4_MAX_BYTELEN
;
6159 if (IS_ZEBRA_DEBUG_VXLAN
)
6160 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
6161 inet_ntoa(vtep_ip
), vni
,
6162 zebra_route_string(client
->proto
));
6164 /* Locate VNI hash entry - expected to exist. */
6165 zvni
= zvni_lookup(vni
);
6167 if (IS_ZEBRA_DEBUG_VXLAN
)
6169 "Failed to locate VNI hash upon remote VTEP DEL, "
6175 ifp
= zvni
->vxlan_if
;
6178 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
6184 /* If down or not mapped to a bridge, we're done. */
6185 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6188 /* If the remote VTEP does not exist, there's nothing more to
6190 * Otherwise, uninstall any remote MACs pointing to this VTEP
6192 * then, the VTEP entry itself and remove it.
6194 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
6198 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
6199 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
6200 zvni_vtep_uninstall(zvni
, &vtep_ip
);
6201 zvni_vtep_del(zvni
, zvtep
);
6209 * Handle message from client to add a remote VTEP for a VNI.
6211 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
6214 unsigned short l
= 0;
6216 struct in_addr vtep_ip
;
6218 struct interface
*ifp
;
6219 struct zebra_if
*zif
;
6221 if (!is_evpn_enabled()) {
6223 "%s: EVPN not enabled yet we received a vtep_add zapi call",
6224 __PRETTY_FUNCTION__
);
6228 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6229 zlog_debug("Recv MACIP ADD for non-default VRF %u",
6236 while (l
< hdr
->length
) {
6237 /* Obtain each remote VTEP and process. */
6238 STREAM_GETL(s
, vni
);
6240 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
6241 l
+= IPV4_MAX_BYTELEN
;
6243 if (IS_ZEBRA_DEBUG_VXLAN
)
6244 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
6245 inet_ntoa(vtep_ip
), vni
,
6246 zebra_route_string(client
->proto
));
6248 /* Locate VNI hash entry - expected to exist. */
6249 zvni
= zvni_lookup(vni
);
6252 EC_ZEBRA_VTEP_ADD_FAILED
,
6253 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
6258 ifp
= zvni
->vxlan_if
;
6261 EC_ZEBRA_VTEP_ADD_FAILED
,
6262 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
6269 /* If down or not mapped to a bridge, we're done. */
6270 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6273 /* If the remote VTEP already exists,
6274 there's nothing more to do. */
6275 if (zvni_vtep_find(zvni
, &vtep_ip
))
6278 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
6279 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
6280 "Failed to add remote VTEP, VNI %u zvni %p",
6285 zvni_vtep_install(zvni
, &vtep_ip
);
6293 * Add/Del gateway macip to evpn
6295 * 1. SVI interface on a vlan aware bridge
6296 * 2. SVI interface on a vlan unaware bridge
6297 * 3. vrr interface (MACVLAN) associated to a SVI
6298 * We advertise macip routes for an interface if it is associated to VxLan vlan
6300 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
6304 struct ethaddr macaddr
;
6305 zebra_vni_t
*zvni
= NULL
;
6307 memset(&ip
, 0, sizeof(struct ipaddr
));
6308 memset(&macaddr
, 0, sizeof(struct ethaddr
));
6310 /* Check if EVPN is enabled. */
6311 if (!is_evpn_enabled())
6314 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
6315 struct interface
*svi_if
=
6316 NULL
; /* SVI corresponding to the MACVLAN */
6317 struct zebra_if
*ifp_zif
=
6318 NULL
; /* Zebra daemon specific info for MACVLAN */
6319 struct zebra_if
*svi_if_zif
=
6320 NULL
; /* Zebra daemon specific info for SVI*/
6322 ifp_zif
= ifp
->info
;
6327 * for a MACVLAN interface the link represents the svi_if
6329 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
6330 ifp_zif
->link_ifindex
);
6332 zlog_debug("MACVLAN %s(%u) without link information",
6333 ifp
->name
, ifp
->ifindex
);
6337 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
6339 * If it is a vlan aware bridge then the link gives the
6340 * bridge information
6342 struct interface
*svi_if_link
= NULL
;
6344 svi_if_zif
= svi_if
->info
;
6346 svi_if_link
= if_lookup_by_index_per_ns(
6347 zebra_ns_lookup(NS_DEFAULT
),
6348 svi_if_zif
->link_ifindex
);
6349 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
6351 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
6353 * If it is a vlan unaware bridge then svi is the bridge
6356 zvni
= zvni_from_svi(svi_if
, svi_if
);
6358 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
6359 struct zebra_if
*svi_if_zif
=
6360 NULL
; /* Zebra daemon specific info for SVI */
6361 struct interface
*svi_if_link
=
6362 NULL
; /* link info for the SVI = bridge info */
6364 svi_if_zif
= ifp
->info
;
6366 svi_if_link
= if_lookup_by_index_per_ns(
6367 zebra_ns_lookup(NS_DEFAULT
),
6368 svi_if_zif
->link_ifindex
);
6370 zvni
= zvni_from_svi(ifp
, svi_if_link
);
6372 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
6373 zvni
= zvni_from_svi(ifp
, ifp
);
6379 if (!zvni
->vxlan_if
) {
6380 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
6386 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
6388 if (p
->family
== AF_INET
) {
6389 ip
.ipa_type
= IPADDR_V4
;
6390 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
6391 sizeof(struct in_addr
));
6392 } else if (p
->family
== AF_INET6
) {
6393 ip
.ipa_type
= IPADDR_V6
;
6394 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
6395 sizeof(struct in6_addr
));
6400 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
6402 zvni_gw_macip_del(ifp
, zvni
, &ip
);
6408 * Handle SVI interface going down.
6409 * SVI can be associated to either L3-VNI or L2-VNI.
6410 * For L2-VNI: At this point, this is a NOP since
6411 * the kernel deletes the neighbor entries on this SVI (if any).
6412 * We only need to update the vrf corresponding to zvni.
6413 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
6416 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
6418 zebra_l3vni_t
*zl3vni
= NULL
;
6420 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6423 /* process l3-vni down */
6424 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6426 /* remove association with svi-if */
6427 zl3vni
->svi_if
= NULL
;
6429 zebra_vni_t
*zvni
= NULL
;
6431 /* since we dont have svi corresponding to zvni, we associate it
6432 * to default vrf. Note: the corresponding neigh entries on the
6433 * SVI would have already been deleted */
6434 zvni
= zvni_from_svi(ifp
, link_if
);
6436 zvni
->vrf_id
= VRF_DEFAULT
;
6438 /* update the tenant vrf in BGP */
6439 zvni_send_add_to_client(zvni
);
6446 * Handle SVI interface coming up.
6447 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
6449 * For L2-VNI: we need to install any remote neighbors entried (used for
6451 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
6453 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
6455 zebra_vni_t
*zvni
= NULL
;
6456 zebra_l3vni_t
*zl3vni
= NULL
;
6458 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6461 /* associate with svi */
6462 zl3vni
->svi_if
= ifp
;
6464 /* process oper-up */
6465 if (is_l3vni_oper_up(zl3vni
))
6466 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6469 /* process SVI up for l2-vni */
6470 struct neigh_walk_ctx n_wctx
;
6472 zvni
= zvni_from_svi(ifp
, link_if
);
6476 if (!zvni
->vxlan_if
) {
6478 "VNI %u hash %p doesn't have intf upon SVI up",
6483 if (IS_ZEBRA_DEBUG_VXLAN
)
6485 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
6486 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
6487 vrf_id_to_name(ifp
->vrf_id
));
6489 /* update the vrf information for l2-vni and inform bgp */
6490 zvni
->vrf_id
= ifp
->vrf_id
;
6491 zvni_send_add_to_client(zvni
);
6493 /* Install any remote neighbors for this VNI. */
6494 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6496 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6504 * Handle VxLAN interface down
6506 int zebra_vxlan_if_down(struct interface
*ifp
)
6509 struct zebra_if
*zif
= NULL
;
6510 struct zebra_l2info_vxlan
*vxl
= NULL
;
6511 zebra_l3vni_t
*zl3vni
= NULL
;
6514 /* Check if EVPN is enabled. */
6515 if (!is_evpn_enabled())
6520 vxl
= &zif
->l2info
.vxl
;
6523 zl3vni
= zl3vni_lookup(vni
);
6525 /* process-if-down for l3-vni */
6526 if (IS_ZEBRA_DEBUG_VXLAN
)
6527 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
6530 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6532 /* process if-down for l2-vni */
6533 if (IS_ZEBRA_DEBUG_VXLAN
)
6534 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
6537 /* Locate hash entry; it is expected to exist. */
6538 zvni
= zvni_lookup(vni
);
6541 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
6542 ifp
->name
, ifp
->ifindex
, vni
);
6546 assert(zvni
->vxlan_if
== ifp
);
6548 /* Delete this VNI from BGP. */
6549 zvni_send_del_to_client(zvni
->vni
);
6551 /* Free up all neighbors and MACs, if any. */
6552 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6553 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6555 /* Free up all remote VTEPs, if any. */
6556 zvni_vtep_del_all(zvni
, 1);
6562 * Handle VxLAN interface up - update BGP if required.
6564 int zebra_vxlan_if_up(struct interface
*ifp
)
6567 struct zebra_if
*zif
= NULL
;
6568 struct zebra_l2info_vxlan
*vxl
= NULL
;
6569 zebra_vni_t
*zvni
= NULL
;
6570 zebra_l3vni_t
*zl3vni
= NULL
;
6572 /* Check if EVPN is enabled. */
6573 if (!is_evpn_enabled())
6578 vxl
= &zif
->l2info
.vxl
;
6581 zl3vni
= zl3vni_lookup(vni
);
6584 if (IS_ZEBRA_DEBUG_VXLAN
)
6585 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
6588 /* we need to associate with SVI, if any, we can associate with
6589 * svi-if only after association with vxlan-intf is complete
6591 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6593 if (is_l3vni_oper_up(zl3vni
))
6594 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6596 /* Handle L2-VNI add */
6597 struct interface
*vlan_if
= NULL
;
6599 if (IS_ZEBRA_DEBUG_VXLAN
)
6600 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
6603 /* Locate hash entry; it is expected to exist. */
6604 zvni
= zvni_lookup(vni
);
6607 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
6608 ifp
->name
, ifp
->ifindex
, vni
);
6612 assert(zvni
->vxlan_if
== ifp
);
6613 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6614 zif
->brslave_info
.br_if
);
6616 zvni
->vrf_id
= vlan_if
->vrf_id
;
6617 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6619 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6622 /* If part of a bridge, inform BGP about this VNI. */
6623 /* Also, read and populate local MACs and neighbors. */
6624 if (zif
->brslave_info
.br_if
) {
6625 zvni_send_add_to_client(zvni
);
6626 zvni_read_mac_neigh(zvni
, ifp
);
6634 * Handle VxLAN interface delete. Locate and remove entry in hash table
6635 * and update BGP, if required.
6637 int zebra_vxlan_if_del(struct interface
*ifp
)
6640 struct zebra_if
*zif
= NULL
;
6641 struct zebra_l2info_vxlan
*vxl
= NULL
;
6642 zebra_vni_t
*zvni
= NULL
;
6643 zebra_l3vni_t
*zl3vni
= NULL
;
6645 /* Check if EVPN is enabled. */
6646 if (!is_evpn_enabled())
6651 vxl
= &zif
->l2info
.vxl
;
6654 zl3vni
= zl3vni_lookup(vni
);
6657 if (IS_ZEBRA_DEBUG_VXLAN
)
6658 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
6661 /* process oper-down for l3-vni */
6662 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6664 /* remove the association with vxlan_if */
6665 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
6666 zl3vni
->vxlan_if
= NULL
;
6669 /* process if-del for l2-vni*/
6670 if (IS_ZEBRA_DEBUG_VXLAN
)
6671 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
6674 /* Locate hash entry; it is expected to exist. */
6675 zvni
= zvni_lookup(vni
);
6678 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6679 ifp
->name
, ifp
->ifindex
, vni
);
6683 /* remove from l3-vni list */
6684 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
6686 listnode_delete(zl3vni
->l2vnis
, zvni
);
6688 /* Delete VNI from BGP. */
6689 zvni_send_del_to_client(zvni
->vni
);
6691 /* Free up all neighbors and MAC, if any. */
6692 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
6693 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
6695 /* Free up all remote VTEPs, if any. */
6696 zvni_vtep_del_all(zvni
, 0);
6698 /* Delete the hash entry. */
6699 if (zvni_del(zvni
)) {
6700 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
6701 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
6702 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
6710 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6712 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
6715 struct zebra_if
*zif
= NULL
;
6716 struct zebra_l2info_vxlan
*vxl
= NULL
;
6717 zebra_vni_t
*zvni
= NULL
;
6718 zebra_l3vni_t
*zl3vni
= NULL
;
6720 /* Check if EVPN is enabled. */
6721 if (!is_evpn_enabled())
6726 vxl
= &zif
->l2info
.vxl
;
6729 zl3vni
= zl3vni_lookup(vni
);
6732 if (IS_ZEBRA_DEBUG_VXLAN
)
6734 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6735 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6736 inet_ntoa(vxl
->vtep_ip
),
6737 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6739 /* Removed from bridge? Cleanup and return */
6740 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6741 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6742 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6746 /* access-vlan change - process oper down, associate with new
6747 * svi_if and then process oper up again
6749 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6750 if (if_is_operative(ifp
)) {
6751 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6752 zl3vni
->svi_if
= NULL
;
6753 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6754 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6755 if (is_l3vni_oper_up(zl3vni
))
6756 zebra_vxlan_process_l3vni_oper_up(
6762 * local-ip change - process oper down, associate with new
6763 * local-ip and then process oper up again
6765 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
6766 if (if_is_operative(ifp
)) {
6767 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6768 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6769 if (is_l3vni_oper_up(zl3vni
))
6770 zebra_vxlan_process_l3vni_oper_up(
6775 /* Update local tunnel IP. */
6776 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6778 /* if we have a valid new master, process l3-vni oper up */
6779 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
6780 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
6781 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6785 /* Update VNI hash. */
6786 zvni
= zvni_lookup(vni
);
6789 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6790 ifp
->name
, ifp
->ifindex
, vni
);
6794 if (IS_ZEBRA_DEBUG_VXLAN
)
6796 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6797 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6798 inet_ntoa(vxl
->vtep_ip
),
6799 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6801 /* Removed from bridge? Cleanup and return */
6802 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6803 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6804 /* Delete from client, remove all remote VTEPs */
6805 /* Also, free up all MACs and neighbors. */
6806 zvni_send_del_to_client(zvni
->vni
);
6807 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6808 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6809 zvni_vtep_del_all(zvni
, 1);
6813 /* Handle other changes. */
6814 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6815 /* Remove all existing local neigh and MACs for this VNI
6816 * (including from BGP)
6818 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6819 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6822 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6823 zvni
->vxlan_if
= ifp
;
6825 /* Take further actions needed.
6826 * Note that if we are here, there is a change of interest.
6828 /* If down or not mapped to a bridge, we're done. */
6829 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6832 /* Inform BGP, if there is a change of interest. */
6834 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
6835 zvni_send_add_to_client(zvni
);
6837 /* If there is a valid new master or a VLAN mapping change,
6838 * read and populate local MACs and neighbors.
6839 * Also, reinstall any remote MACs and neighbors
6840 * for this VNI (based on new VLAN).
6842 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6843 zvni_read_mac_neigh(zvni
, ifp
);
6844 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6845 struct mac_walk_ctx m_wctx
;
6846 struct neigh_walk_ctx n_wctx
;
6848 zvni_read_mac_neigh(zvni
, ifp
);
6850 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6852 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
6855 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6857 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6866 * Handle VxLAN interface add.
6868 int zebra_vxlan_if_add(struct interface
*ifp
)
6871 struct zebra_if
*zif
= NULL
;
6872 struct zebra_l2info_vxlan
*vxl
= NULL
;
6873 zebra_vni_t
*zvni
= NULL
;
6874 zebra_l3vni_t
*zl3vni
= NULL
;
6876 /* Check if EVPN is enabled. */
6877 if (!is_evpn_enabled())
6882 vxl
= &zif
->l2info
.vxl
;
6885 zl3vni
= zl3vni_lookup(vni
);
6888 /* process if-add for l3-vni*/
6889 if (IS_ZEBRA_DEBUG_VXLAN
)
6891 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6892 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6893 inet_ntoa(vxl
->vtep_ip
),
6894 zif
->brslave_info
.bridge_ifindex
);
6896 /* associate with vxlan_if */
6897 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6898 zl3vni
->vxlan_if
= ifp
;
6900 /* Associate with SVI, if any. We can associate with svi-if only
6901 * after association with vxlan_if is complete */
6902 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6904 if (is_l3vni_oper_up(zl3vni
))
6905 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6908 /* process if-add for l2-vni */
6909 struct interface
*vlan_if
= NULL
;
6911 /* Create or update VNI hash. */
6912 zvni
= zvni_lookup(vni
);
6914 zvni
= zvni_add(vni
);
6917 EC_ZEBRA_VNI_ADD_FAILED
,
6918 "Failed to add VNI hash, IF %s(%u) VNI %u",
6919 ifp
->name
, ifp
->ifindex
, vni
);
6924 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6925 zvni
->vxlan_if
= ifp
;
6926 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6927 zif
->brslave_info
.br_if
);
6929 zvni
->vrf_id
= vlan_if
->vrf_id
;
6930 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6932 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6935 if (IS_ZEBRA_DEBUG_VXLAN
)
6937 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6939 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
6941 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6942 inet_ntoa(vxl
->vtep_ip
),
6943 zif
->brslave_info
.bridge_ifindex
);
6945 /* If down or not mapped to a bridge, we're done. */
6946 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6950 zvni_send_add_to_client(zvni
);
6952 /* Read and populate local MACs and neighbors */
6953 zvni_read_mac_neigh(zvni
, ifp
);
6959 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
6960 char *err
, int err_str_sz
, int filter
,
6963 zebra_l3vni_t
*zl3vni
= NULL
;
6964 struct zebra_vrf
*zvrf_default
= NULL
;
6966 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
6970 if (IS_ZEBRA_DEBUG_VXLAN
)
6971 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
6972 add
? "ADD" : "DEL");
6976 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6978 /* check if the vni is already present under zvrf */
6980 snprintf(err
, err_str_sz
,
6981 "VNI is already configured under the vrf");
6985 /* check if this VNI is already present in the system */
6986 zl3vni
= zl3vni_lookup(vni
);
6988 snprintf(err
, err_str_sz
,
6989 "VNI is already configured as L3-VNI");
6993 /* add the L3-VNI to the global table */
6994 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
6996 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
7000 /* associate the vrf with vni */
7003 /* set the filter in l3vni to denote if we are using l3vni only
7007 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
7009 /* associate with vxlan-intf;
7010 * we need to associate with the vxlan-intf first
7012 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
7014 /* associate with corresponding SVI interface, we can associate
7015 * with svi-if only after vxlan interface association is
7018 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
7020 /* formulate l2vni list */
7021 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
7024 if (is_l3vni_oper_up(zl3vni
))
7025 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
7028 zl3vni
= zl3vni_lookup(vni
);
7030 snprintf(err
, err_str_sz
, "VNI doesn't exist");
7034 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
7035 snprintf(err
, ERR_STR_SZ
,
7036 "prefix-routes-only is not set for the vni");
7040 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7042 /* delete and uninstall all rmacs */
7043 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
7046 /* delete and uninstall all next-hops */
7047 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
7053 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
7058 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
7060 zebra_l3vni_t
*zl3vni
= NULL
;
7063 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
7067 zl3vni
->vrf_id
= zvrf_id(zvrf
);
7068 if (is_l3vni_oper_up(zl3vni
))
7069 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
7073 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
7075 zebra_l3vni_t
*zl3vni
= NULL
;
7078 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
7082 zl3vni
->vrf_id
= VRF_UNKNOWN
;
7083 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7087 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
7089 zebra_l3vni_t
*zl3vni
= NULL
;
7093 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
7099 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
7105 * Handle message from client to specify the flooding mechanism for
7106 * BUM packets. The default is to do head-end (ingress) replication
7107 * and the other supported option is to disable it. This applies to
7108 * all BUM traffic and disabling it applies to both the transmit and
7109 * receive direction.
7111 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
7114 enum vxlan_flood_control flood_ctrl
;
7116 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7117 zlog_err("EVPN flood control for non-default VRF %u",
7123 STREAM_GETC(s
, flood_ctrl
);
7125 if (IS_ZEBRA_DEBUG_VXLAN
)
7126 zlog_debug("EVPN flood control %u, currently %u",
7127 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
7129 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
7132 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
7134 /* Install or uninstall flood entries corresponding to
7137 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
7145 * Handle message from client to enable/disable advertisement of g/w macip
7148 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
7153 zebra_vni_t
*zvni
= NULL
;
7154 struct interface
*ifp
= NULL
;
7155 struct zebra_if
*zif
= NULL
;
7156 struct zebra_l2info_vxlan zl2_info
;
7157 struct interface
*vlan_if
= NULL
;
7159 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7160 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
7166 STREAM_GETC(s
, advertise
);
7167 vni
= stream_get3(s
);
7169 zvni
= zvni_lookup(vni
);
7173 if (zvni
->advertise_subnet
== advertise
)
7176 if (IS_ZEBRA_DEBUG_VXLAN
)
7177 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
7178 advertise
? "enabled" : "disabled", vni
,
7179 zvni
->advertise_subnet
? "enabled" : "disabled");
7182 zvni
->advertise_subnet
= advertise
;
7184 ifp
= zvni
->vxlan_if
;
7190 /* If down or not mapped to a bridge, we're done. */
7191 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7194 zl2_info
= zif
->l2info
.vxl
;
7197 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
7201 if (zvni
->advertise_subnet
)
7202 zvni_advertise_subnet(zvni
, vlan_if
, 1);
7204 zvni_advertise_subnet(zvni
, vlan_if
, 0);
7211 * Handle message from client to enable/disable advertisement of g/w macip
7214 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
7219 zebra_vni_t
*zvni
= NULL
;
7220 struct interface
*ifp
= NULL
;
7222 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7223 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
7229 STREAM_GETC(s
, advertise
);
7230 STREAM_GETL(s
, vni
);
7233 if (IS_ZEBRA_DEBUG_VXLAN
)
7234 zlog_debug("EVPN gateway macip Adv %s, currently %s",
7235 advertise
? "enabled" : "disabled",
7236 advertise_gw_macip_enabled(NULL
)
7240 if (zvrf
->advertise_gw_macip
== advertise
)
7243 zvrf
->advertise_gw_macip
= advertise
;
7245 if (advertise_gw_macip_enabled(zvni
))
7246 hash_iterate(zvrf
->vni_table
,
7247 zvni_gw_macip_add_for_vni_hash
, NULL
);
7249 hash_iterate(zvrf
->vni_table
,
7250 zvni_gw_macip_del_for_vni_hash
, NULL
);
7253 struct zebra_if
*zif
= NULL
;
7254 struct zebra_l2info_vxlan zl2_info
;
7255 struct interface
*vlan_if
= NULL
;
7256 struct interface
*vrr_if
= NULL
;
7258 zvni
= zvni_lookup(vni
);
7262 if (IS_ZEBRA_DEBUG_VXLAN
)
7264 "EVPN gateway macip Adv %s on VNI %d , currently %s",
7265 advertise
? "enabled" : "disabled", vni
,
7266 advertise_gw_macip_enabled(zvni
) ? "enabled"
7269 if (zvni
->advertise_gw_macip
== advertise
)
7272 zvni
->advertise_gw_macip
= advertise
;
7274 ifp
= zvni
->vxlan_if
;
7280 /* If down or not mapped to a bridge, we're done. */
7281 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7284 zl2_info
= zif
->l2info
.vxl
;
7286 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
7287 zif
->brslave_info
.br_if
);
7291 if (advertise_gw_macip_enabled(zvni
)) {
7292 /* Add primary SVI MAC-IP */
7293 zvni_add_macip_for_intf(vlan_if
, zvni
);
7295 /* Add VRR MAC-IP - if any*/
7296 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
7298 zvni_add_macip_for_intf(vrr_if
, zvni
);
7300 /* Del primary MAC-IP */
7301 zvni_del_macip_for_intf(vlan_if
, zvni
);
7303 /* Del VRR MAC-IP - if any*/
7304 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
7306 zvni_del_macip_for_intf(vrr_if
, zvni
);
7316 * Handle message from client to learn (or stop learning) about VNIs and MACs.
7317 * When enabled, the VNI hash table will be built and MAC FDB table read;
7318 * when disabled, the entries should be deleted and remote VTEPs and MACs
7319 * uninstalled from the kernel.
7320 * This also informs the setting for BUM handling at the time this change
7321 * occurs; it is relevant only when specifying "learn".
7323 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
7325 struct stream
*s
= NULL
;
7327 enum vxlan_flood_control flood_ctrl
;
7329 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7330 zlog_debug("EVPN VNI Adv for non-default VRF %u",
7336 STREAM_GETC(s
, advertise
);
7337 STREAM_GETC(s
, flood_ctrl
);
7339 if (IS_ZEBRA_DEBUG_VXLAN
)
7340 zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u",
7341 advertise
? "enabled" : "disabled",
7342 is_evpn_enabled() ? "enabled" : "disabled",
7345 if (zvrf
->advertise_all_vni
== advertise
)
7348 zvrf
->advertise_all_vni
= advertise
;
7349 if (is_evpn_enabled()) {
7350 /* Note BUM handling */
7351 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
7353 /* Build VNI hash table and inform BGP. */
7354 zvni_build_hash_table();
7356 /* Add all SVI (L3 GW) MACs to BGP*/
7357 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
7360 /* Read the MAC FDB */
7361 macfdb_read(zvrf
->zns
);
7363 /* Read neighbors */
7364 neigh_read(zvrf
->zns
);
7366 /* Cleanup VTEPs for all VNIs - uninstall from
7367 * kernel and free entries.
7369 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
7371 /* cleanup all l3vnis */
7372 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
7380 * Allocate VNI hash table for this VRF and do other initialization.
7381 * NOTE: Currently supported only for default VRF.
7383 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
7387 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
7388 "Zebra VRF VNI Table");
7391 /* Cleanup VNI info, but don't free the table. */
7392 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
7396 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
7399 /* Close all VNI handling */
7400 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
7404 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
7405 hash_free(zvrf
->vni_table
);
7408 /* init the l3vni table */
7409 void zebra_vxlan_ns_init(struct zebra_ns
*zns
)
7411 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
7412 "Zebra VRF L3 VNI table");
7415 /* free l3vni table */
7416 void zebra_vxlan_ns_disable(struct zebra_ns
*zns
)
7418 hash_free(zrouter
.l3vni_table
);
7421 /* get the l3vni svi ifindex */
7422 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
7424 zebra_l3vni_t
*zl3vni
= NULL
;
7426 zl3vni
= zl3vni_from_vrf(vrf_id
);
7427 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
7430 return zl3vni
->svi_if
->ifindex
;