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 "zebra/rib.h"
39 #include "zebra/zebra_ns.h"
40 #include "zebra/zserv.h"
41 #include "zebra/debug.h"
42 #include "zebra/interface.h"
43 #include "zebra/zebra_vrf.h"
44 #include "zebra/rt_netlink.h"
45 #include "zebra/zebra_vxlan_private.h"
46 #include "zebra/zebra_vxlan.h"
47 #include "zebra/zebra_memory.h"
48 #include "zebra/zebra_l2.h"
50 DEFINE_MTYPE_STATIC(ZEBRA
, HOST_PREFIX
, "host prefix");
51 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI
, "VNI hash");
52 DEFINE_MTYPE_STATIC(ZEBRA
, ZL3VNI
, "L3 VNI hash");
53 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI_VTEP
, "VNI remote VTEP");
54 DEFINE_MTYPE_STATIC(ZEBRA
, MAC
, "VNI MAC");
55 DEFINE_MTYPE_STATIC(ZEBRA
, NEIGH
, "VNI Neighbor");
59 /* static function declarations */
60 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
62 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
63 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
);
64 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
66 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
68 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
70 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
);
71 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
);
72 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
);
73 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
74 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[]);
76 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
77 struct ipaddr
*ip
, uint8_t flags
,
79 static unsigned int neigh_hash_keymake(void *p
);
80 static int neigh_cmp(const void *p1
, const void *p2
);
81 static void *zvni_neigh_alloc(void *p
);
82 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
84 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
85 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
86 struct in_addr
*r_vtep_ip
);
87 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
89 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
);
90 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
91 struct ethaddr
*macaddr
,
93 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
94 struct ethaddr
*macaddr
,
96 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
97 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
98 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
99 struct interface
*br_if
);
100 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
);
102 /* l3-vni next-hop neigh related APIs */
103 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
105 static void *zl3vni_nh_alloc(void *p
);
106 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
107 struct ipaddr
*vtep_ip
,
108 struct ethaddr
*rmac
);
109 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
110 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
111 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
113 /* l3-vni rmac related APIs */
114 static void zl3vni_print_rmac_hash(struct hash_backet
*, void *);
115 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
116 struct ethaddr
*rmac
);
117 static void *zl3vni_rmac_alloc(void *p
);
118 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
119 struct ethaddr
*rmac
);
120 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
121 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
122 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
124 /* l3-vni related APIs*/
125 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
);
126 static void *zl3vni_alloc(void *p
);
127 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
128 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
129 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t
);
130 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
);
131 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
);
132 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
133 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
135 static unsigned int mac_hash_keymake(void *p
);
136 static int mac_cmp(const void *p1
, const void *p2
);
137 static void *zvni_mac_alloc(void *p
);
138 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
139 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
140 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
141 struct in_addr
*r_vtep_ip
);
142 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
144 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
145 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
147 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
149 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
150 struct interface
*br_if
, vlanid_t vid
);
151 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
152 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
);
153 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
);
155 static unsigned int vni_hash_keymake(void *p
);
156 static int vni_hash_cmp(const void *p1
, const void *p2
);
157 static void *zvni_alloc(void *p
);
158 static zebra_vni_t
*zvni_lookup(vni_t vni
);
159 static zebra_vni_t
*zvni_add(vni_t vni
);
160 static int zvni_del(zebra_vni_t
*zvni
);
161 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
162 static int zvni_send_del_to_client(vni_t vni
);
163 static void zvni_build_hash_table();
164 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
165 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
166 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
167 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
168 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
169 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
170 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
171 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
172 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
173 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
174 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
175 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
177 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
178 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
179 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
182 /* Private functions */
183 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
184 const struct host_rb_entry
*hle2
)
186 if (hle1
->p
.family
< hle2
->p
.family
)
189 if (hle1
->p
.family
> hle2
->p
.family
)
192 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
195 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
198 if (hle1
->p
.family
== AF_INET
) {
199 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
202 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
207 zlog_warn("%s: Unexpected family type: %d", __PRETTY_FUNCTION__
,
212 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
214 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
216 struct host_rb_entry
*hle
;
219 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
226 * Return number of valid MACs in a VNI's MAC hash table - all
227 * remote MACs and non-internal (auto) local MACs count.
229 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
232 uint32_t num_macs
= 0;
234 struct hash_backet
*hb
;
237 hash
= zvni
->mac_table
;
240 for (i
= 0; i
< hash
->size
; i
++) {
241 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
242 mac
= (zebra_mac_t
*)hb
->data
;
243 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
244 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
252 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
254 struct zebra_vrf
*zvrf
;
256 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
257 if (zvrf
&& zvrf
->advertise_gw_macip
)
260 if (zvni
&& zvni
->advertise_gw_macip
)
267 * Helper function to determine maximum width of neighbor IP address for
268 * display - just because we're dealing with IPv6 addresses that can
271 static void zvni_find_neigh_addr_width(struct hash_backet
*backet
, void *ctxt
)
274 char buf
[INET6_ADDRSTRLEN
];
275 struct neigh_walk_ctx
*wctx
= ctxt
;
278 n
= (zebra_neigh_t
*)backet
->data
;
282 ipaddr2str(&n
->ip
, buf
, sizeof(buf
)), width
= strlen(buf
);
283 if (width
> wctx
->addr_width
)
284 wctx
->addr_width
= width
;
288 * Print a specific neighbor entry.
290 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
293 char buf1
[ETHER_ADDR_STRLEN
];
294 char buf2
[INET6_ADDRSTRLEN
];
296 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
297 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
298 vty
= (struct vty
*)ctxt
;
300 vty_out(vty
, "IP: %s\n",
301 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
302 vty_out(vty
, " MAC: %s",
303 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
305 json_object_string_add(json
, "ip", buf2
);
306 json_object_string_add(json
, "mac", buf1
);
308 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
310 vty_out(vty
, " Remote VTEP: %s",
311 inet_ntoa(n
->r_vtep_ip
));
313 json_object_string_add(json
, "remoteVtep",
314 inet_ntoa(n
->r_vtep_ip
));
316 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
319 vty_out(vty
, " State: %s",
320 IS_ZEBRA_NEIGH_ACTIVE(n
) ? "Active"
324 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
326 vty_out(vty
, " Default-gateway");
328 json_object_boolean_true_add(json
, "defaultGateway");
335 * Print neighbor hash entry - called for display of all neighbors.
337 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
340 json_object
*json_vni
= NULL
, *json_row
= NULL
;
342 char buf1
[ETHER_ADDR_STRLEN
];
343 char buf2
[INET6_ADDRSTRLEN
];
344 struct neigh_walk_ctx
*wctx
= ctxt
;
347 json_vni
= wctx
->json
;
348 n
= (zebra_neigh_t
*)backet
->data
;
353 json_row
= json_object_new_object();
355 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
356 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
357 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)
358 && !(wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)) {
359 if (json_vni
== NULL
) {
360 vty_out(vty
, "%*s %-6s %-17s\n", -wctx
->addr_width
,
361 buf2
, "local", buf1
);
363 json_object_string_add(json_row
, "type", "local");
364 json_object_string_add(json_row
, "mac", buf1
);
368 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) {
369 if (IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
)) {
370 if (json_vni
== NULL
) {
371 if (wctx
->count
== 0)
373 "%*s %-6s %-17s %-21s\n",
376 "MAC", "Remote VTEP");
377 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
378 -wctx
->addr_width
, buf2
,
380 inet_ntoa(n
->r_vtep_ip
));
382 json_object_string_add(json_row
, "type",
384 json_object_string_add(json_row
, "mac",
386 json_object_string_add(
387 json_row
, "remoteVtep",
388 inet_ntoa(n
->r_vtep_ip
));
393 if (json_vni
== NULL
) {
394 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
395 -wctx
->addr_width
, buf2
, "remote", buf1
,
396 inet_ntoa(n
->r_vtep_ip
));
398 json_object_string_add(json_row
, "type",
400 json_object_string_add(json_row
, "mac", buf1
);
401 json_object_string_add(json_row
, "remoteVtep",
402 inet_ntoa(n
->r_vtep_ip
));
409 json_object_object_add(json_vni
, buf2
, json_row
);
413 * Print neighbors for all VNI.
415 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
419 json_object
*json
= NULL
, *json_vni
= NULL
;
422 struct neigh_walk_ctx wctx
;
423 char vni_str
[VNI_STR_LEN
];
425 vty
= (struct vty
*)args
[0];
426 json
= (json_object
*)args
[1];
428 zvni
= (zebra_vni_t
*)backet
->data
;
431 vty_out(vty
, "{}\n");
434 num_neigh
= hashcount(zvni
->neigh_table
);
437 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
438 zvni
->vni
, num_neigh
);
440 json_vni
= json_object_new_object();
441 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
442 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
446 json_object_object_add(json
, vni_str
, json_vni
);
450 /* Since we have IPv6 addresses to deal with which can vary widely in
451 * size, we try to be a bit more elegant in display by first computing
454 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
457 wctx
.addr_width
= 15;
458 wctx
.json
= json_vni
;
459 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
462 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
463 "Type", "MAC", "Remote VTEP");
464 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
467 json_object_object_add(json
, vni_str
, json_vni
);
470 /* print a specific next hop for an l3vni */
471 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
474 char buf1
[ETHER_ADDR_STRLEN
];
475 char buf2
[INET6_ADDRSTRLEN
];
476 json_object
*json_hosts
= NULL
;
477 struct host_rb_entry
*hle
;
480 vty_out(vty
, "Ip: %s\n",
481 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
482 vty_out(vty
, " RMAC: %s\n",
483 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
484 vty_out(vty
, " Refcount: %d\n",
485 rb_host_count(&n
->host_rb
));
486 vty_out(vty
, " Prefixes:\n");
487 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
488 vty_out(vty
, " %s\n",
489 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
491 json_hosts
= json_object_new_array();
492 json_object_string_add(
493 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
494 json_object_string_add(
496 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
497 json_object_int_add(json
, "refCount",
498 rb_host_count(&n
->host_rb
));
499 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
500 json_object_array_add(json_hosts
,
501 json_object_new_string(prefix2str(
502 &hle
->p
, buf2
, sizeof(buf2
))));
503 json_object_object_add(json
, "prefixList", json_hosts
);
507 /* Print a specific RMAC entry */
508 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
511 char buf1
[ETHER_ADDR_STRLEN
];
512 char buf2
[PREFIX_STRLEN
];
513 json_object
*json_hosts
= NULL
;
514 struct host_rb_entry
*hle
;
517 vty_out(vty
, "MAC: %s\n",
518 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
519 vty_out(vty
, " Remote VTEP: %s\n",
520 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
521 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
522 vty_out(vty
, " Prefixes:\n");
523 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
524 vty_out(vty
, " %s\n",
525 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
527 json_hosts
= json_object_new_array();
528 json_object_string_add(
530 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
531 json_object_string_add(json
, "vtepIp",
532 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
533 json_object_int_add(json
, "refCount",
534 rb_host_count(&zrmac
->host_rb
));
535 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
536 json_object_array_add(
538 json_object_new_string(prefix2str(
539 &hle
->p
, buf2
, sizeof(buf2
))));
540 json_object_object_add(json
, "prefixList", json_hosts
);
545 * Print a specific MAC entry.
547 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
)
550 zebra_neigh_t
*n
= NULL
;
551 struct listnode
*node
= NULL
;
553 char buf2
[INET6_ADDRSTRLEN
];
555 vty
= (struct vty
*)ctxt
;
556 vty_out(vty
, "MAC: %s",
557 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
)));
558 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
559 struct zebra_ns
*zns
;
560 struct interface
*ifp
;
563 ifindex
= mac
->fwd_info
.local
.ifindex
;
564 zns
= zebra_ns_lookup(NS_DEFAULT
);
565 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
566 if (!ifp
) // unexpected
568 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
569 if (mac
->fwd_info
.local
.vid
)
570 vty_out(vty
, " VLAN: %u", mac
->fwd_info
.local
.vid
);
571 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
572 vty_out(vty
, " Remote VTEP: %s",
573 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
574 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
575 vty_out(vty
, " Auto Mac ");
578 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
579 vty_out(vty
, " Sticky Mac ");
581 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
582 vty_out(vty
, " Default-gateway Mac ");
585 /* print all the associated neigh */
586 vty_out(vty
, " Neighbors:\n");
587 if (!listcount(mac
->neigh_list
))
588 vty_out(vty
, " No Neighbors\n");
590 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
591 vty_out(vty
, " %s %s\n",
592 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
593 CHECK_FLAG(n
->flags
, ZEBRA_MAC_LOCAL
)
594 ? (IS_ZEBRA_NEIGH_ACTIVE(n
)
605 * Print MAC hash entry - called for display of all MACs.
607 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
610 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
613 struct mac_walk_ctx
*wctx
= ctxt
;
616 json_mac_hdr
= wctx
->json
;
617 mac
= (zebra_mac_t
*)backet
->data
;
621 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
624 json_mac
= json_object_new_object();
626 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
627 && !(wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)) {
628 struct zebra_ns
*zns
;
630 struct interface
*ifp
;
633 zns
= zebra_ns_lookup(NS_DEFAULT
);
634 ifindex
= mac
->fwd_info
.local
.ifindex
;
635 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
636 if (!ifp
) // unexpected
638 vid
= mac
->fwd_info
.local
.vid
;
639 if (json_mac_hdr
== NULL
)
640 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
643 json_object_string_add(json_mac
, "type", "local");
644 json_object_string_add(json_mac
, "intf", ifp
->name
);
647 if (json_mac_hdr
== NULL
)
648 vty_out(vty
, " %-5u", vid
);
650 json_object_int_add(json_mac
, "vlan", vid
);
652 if (json_mac_hdr
== NULL
)
655 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
657 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
658 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) {
659 if (IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
661 if (wctx
->count
== 0) {
662 if (json_mac_hdr
== NULL
) {
663 vty_out(vty
, "\nVNI %u\n\n",
666 "%-17s %-6s %-21s %-5s\n",
672 if (json_mac_hdr
== NULL
)
673 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
675 inet_ntoa(mac
->fwd_info
678 json_object_string_add(json_mac
, "type",
680 json_object_string_add(
681 json_mac
, "remoteVtep",
682 inet_ntoa(mac
->fwd_info
684 json_object_object_add(json_mac_hdr
,
690 if (json_mac_hdr
== NULL
)
691 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
693 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
695 json_object_string_add(json_mac
, "type",
697 json_object_string_add(
698 json_mac
, "remoteVtep",
699 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
700 json_object_object_add(json_mac_hdr
, buf1
,
709 * Print MACs for all VNI.
711 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
714 json_object
*json
= NULL
, *json_vni
= NULL
;
715 json_object
*json_mac
= NULL
;
718 struct mac_walk_ctx
*wctx
= ctxt
;
719 char vni_str
[VNI_STR_LEN
];
721 vty
= (struct vty
*)wctx
->vty
;
722 json
= (struct json_object
*)wctx
->json
;
724 zvni
= (zebra_vni_t
*)backet
->data
;
727 vty_out(vty
, "{}\n");
732 /*We are iterating over a new VNI, set the count to 0*/
735 num_macs
= num_valid_macs(zvni
);
740 json_vni
= json_object_new_object();
741 json_mac
= json_object_new_object();
742 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
745 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
747 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
748 zvni
->vni
, num_macs
);
749 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
750 "Intf/Remote VTEP", "VLAN");
752 json_object_int_add(json_vni
, "numMacs", num_macs
);
754 /* assign per-vni to wctx->json object to fill macs
755 * under the vni. Re-assign primary json object to fill
756 * next vni information.
758 wctx
->json
= json_mac
;
759 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
763 json_object_object_add(json_vni
, "macs", json_mac
);
764 json_object_object_add(json
, vni_str
, json_vni
);
768 static void zl3vni_print_nh_hash(struct hash_backet
*backet
, void *ctx
)
770 struct nh_walk_ctx
*wctx
= NULL
;
771 struct vty
*vty
= NULL
;
772 struct json_object
*json_vni
= NULL
;
773 struct json_object
*json_nh
= NULL
;
774 zebra_neigh_t
*n
= NULL
;
775 char buf1
[ETHER_ADDR_STRLEN
];
776 char buf2
[INET6_ADDRSTRLEN
];
778 wctx
= (struct nh_walk_ctx
*)ctx
;
780 json_vni
= wctx
->json
;
782 json_nh
= json_object_new_object();
783 n
= (zebra_neigh_t
*)backet
->data
;
788 vty_out(vty
, "%-15s %-17s\n",
789 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
790 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
792 json_object_string_add(json_nh
, "nexthopIp",
793 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
794 json_object_string_add(
795 json_nh
, "routerMac",
796 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
797 json_object_object_add(json_vni
,
798 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
803 static void zl3vni_print_nh_hash_all_vni(struct hash_backet
*backet
,
806 struct vty
*vty
= NULL
;
807 json_object
*json
= NULL
;
808 json_object
*json_vni
= NULL
;
809 zebra_l3vni_t
*zl3vni
= NULL
;
811 struct nh_walk_ctx wctx
;
812 char vni_str
[VNI_STR_LEN
];
814 vty
= (struct vty
*)args
[0];
815 json
= (struct json_object
*)args
[1];
817 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
820 vty_out(vty
, "{}\n");
824 num_nh
= hashcount(zl3vni
->nh_table
);
829 json_vni
= json_object_new_object();
830 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
834 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
835 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
837 json_object_int_add(json_vni
, "numNextHops", num_nh
);
839 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
841 wctx
.json
= json_vni
;
842 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
844 json_object_object_add(json
, vni_str
, json_vni
);
847 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet
*backet
,
850 struct vty
*vty
= NULL
;
851 json_object
*json
= NULL
;
852 json_object
*json_vni
= NULL
;
853 zebra_l3vni_t
*zl3vni
= NULL
;
855 struct rmac_walk_ctx wctx
;
856 char vni_str
[VNI_STR_LEN
];
858 vty
= (struct vty
*)args
[0];
859 json
= (struct json_object
*)args
[1];
861 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
864 vty_out(vty
, "{}\n");
868 num_rmacs
= hashcount(zl3vni
->rmac_table
);
873 json_vni
= json_object_new_object();
874 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
878 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
879 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
881 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
883 /* assign per-vni to wctx->json object to fill macs
884 * under the vni. Re-assign primary json object to fill
885 * next vni information.
887 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
889 wctx
.json
= json_vni
;
890 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
892 json_object_object_add(json
, vni_str
, json_vni
);
895 static void zl3vni_print_rmac_hash(struct hash_backet
*backet
, void *ctx
)
897 zebra_mac_t
*zrmac
= NULL
;
898 struct rmac_walk_ctx
*wctx
= NULL
;
899 struct vty
*vty
= NULL
;
900 struct json_object
*json
= NULL
;
901 struct json_object
*json_rmac
= NULL
;
902 char buf
[ETHER_ADDR_STRLEN
];
904 wctx
= (struct rmac_walk_ctx
*)ctx
;
908 json_rmac
= json_object_new_object();
909 zrmac
= (zebra_mac_t
*)backet
->data
;
914 vty_out(vty
, "%-17s %-21s\n",
915 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
916 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
918 json_object_string_add(
919 json_rmac
, "routerMac",
920 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
921 json_object_string_add(json_rmac
, "vtepIp",
922 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
923 json_object_object_add(
924 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
929 /* print a specific L3 VNI entry */
930 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
932 char buf
[ETHER_ADDR_STRLEN
];
933 struct vty
*vty
= NULL
;
934 json_object
*json
= NULL
;
935 zebra_vni_t
*zvni
= NULL
;
936 json_object
*json_vni_list
= NULL
;
937 struct listnode
*node
= NULL
, *nnode
= NULL
;
943 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
944 vty_out(vty
, " Type: %s\n", "L3");
945 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
946 vty_out(vty
, " Local Vtep Ip: %s\n",
947 inet_ntoa(zl3vni
->local_vtep_ip
));
948 vty_out(vty
, " Vxlan-Intf: %s\n",
949 zl3vni_vxlan_if_name(zl3vni
));
950 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
951 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
952 vty_out(vty
, " VNI Filter: %s\n",
953 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
954 ? "prefix-routes-only"
956 vty_out(vty
, " Router MAC: %s\n",
957 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
958 vty_out(vty
, " L2 VNIs: ");
959 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
960 vty_out(vty
, "%u ", zvni
->vni
);
963 json_vni_list
= json_object_new_array();
964 json_object_int_add(json
, "vni", zl3vni
->vni
);
965 json_object_string_add(json
, "type", "L3");
966 json_object_string_add(json
, "localVtepIp",
967 inet_ntoa(zl3vni
->local_vtep_ip
));
968 json_object_string_add(json
, "vxlanIntf",
969 zl3vni_vxlan_if_name(zl3vni
));
970 json_object_string_add(json
, "sviIntf",
971 zl3vni_svi_if_name(zl3vni
));
972 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
973 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
974 json_object_string_add(
976 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
977 json_object_string_add(
979 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
980 ? "prefix-routes-only"
982 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
983 json_object_array_add(json_vni_list
,
984 json_object_new_int(zvni
->vni
));
986 json_object_object_add(json
, "l2Vnis", json_vni_list
);
991 * Print a specific VNI entry.
993 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
999 json_object
*json
= NULL
;
1000 json_object
*json_vtep_list
= NULL
;
1001 json_object
*json_ip_str
= NULL
;
1007 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1008 vty_out(vty
, " Type: %s\n", "L2");
1009 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1011 json_object_int_add(json
, "vni", zvni
->vni
);
1012 json_object_string_add(json
, "type", "L2");
1013 json_object_string_add(json
, "vrf",
1014 vrf_id_to_name(zvni
->vrf_id
));
1017 if (!zvni
->vxlan_if
) { // unexpected
1019 vty_out(vty
, " VxLAN interface: unknown\n");
1022 num_macs
= num_valid_macs(zvni
);
1023 num_neigh
= hashcount(zvni
->neigh_table
);
1025 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1026 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1027 vty_out(vty
, " Local VTEP IP: %s\n",
1028 inet_ntoa(zvni
->local_vtep_ip
));
1030 json_object_string_add(json
, "vxlanInterface",
1031 zvni
->vxlan_if
->name
);
1032 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1033 json_object_string_add(json
, "vtepIp",
1034 inet_ntoa(zvni
->local_vtep_ip
));
1035 json_object_string_add(json
, "advertiseGatewayMacip",
1036 zvni
->advertise_gw_macip
? "Yes" : "No");
1037 json_object_int_add(json
, "numMacs", num_macs
);
1038 json_object_int_add(json
, "numArpNd", num_neigh
);
1042 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1045 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1047 json_vtep_list
= json_object_new_array();
1048 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1050 vty_out(vty
, " %s\n",
1051 inet_ntoa(zvtep
->vtep_ip
));
1053 json_ip_str
= json_object_new_string(
1054 inet_ntoa(zvtep
->vtep_ip
));
1055 json_object_array_add(json_vtep_list
,
1060 json_object_object_add(json
, "numRemoteVteps",
1065 " Number of MACs (local and remote) known for this VNI: %u\n",
1068 " Number of ARPs (IPv4 and IPv6, local and remote) "
1069 "known for this VNI: %u\n",
1071 vty_out(vty
, " Advertise-gw-macip: %s\n",
1072 zvni
->advertise_gw_macip
? "Yes" : "No");
1076 /* print a L3 VNI hash entry */
1077 static void zl3vni_print_hash(struct hash_backet
*backet
, void *ctx
[])
1079 struct vty
*vty
= NULL
;
1080 json_object
*json
= NULL
;
1081 json_object
*json_vni
= NULL
;
1082 zebra_l3vni_t
*zl3vni
= NULL
;
1084 vty
= (struct vty
*)ctx
[0];
1085 json
= (json_object
*)ctx
[1];
1087 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1092 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1093 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1094 hashcount(zl3vni
->rmac_table
),
1095 hashcount(zl3vni
->nh_table
), "n/a",
1096 zl3vni_vrf_name(zl3vni
));
1098 char vni_str
[VNI_STR_LEN
];
1100 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1101 json_vni
= json_object_new_object();
1102 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1103 json_object_string_add(json_vni
, "vxlanIf",
1104 zl3vni_vxlan_if_name(zl3vni
));
1105 json_object_int_add(json_vni
, "numMacs",
1106 hashcount(zl3vni
->rmac_table
));
1107 json_object_int_add(json_vni
, "numArpNd",
1108 hashcount(zl3vni
->nh_table
));
1109 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1110 json_object_string_add(json_vni
, "type", "L3");
1111 json_object_string_add(json_vni
, "tenantVrf",
1112 zl3vni_vrf_name(zl3vni
));
1113 json_object_object_add(json
, vni_str
, json_vni
);
1118 * Print a VNI hash entry - called for display of all VNIs.
1120 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1124 zebra_vtep_t
*zvtep
;
1125 uint32_t num_vteps
= 0;
1126 uint32_t num_macs
= 0;
1127 uint32_t num_neigh
= 0;
1128 json_object
*json
= NULL
;
1129 json_object
*json_vni
= NULL
;
1130 json_object
*json_ip_str
= NULL
;
1131 json_object
*json_vtep_list
= NULL
;
1136 zvni
= (zebra_vni_t
*)backet
->data
;
1140 zvtep
= zvni
->vteps
;
1143 zvtep
= zvtep
->next
;
1146 num_macs
= num_valid_macs(zvni
);
1147 num_neigh
= hashcount(zvni
->neigh_table
);
1149 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1151 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1152 num_macs
, num_neigh
, num_vteps
,
1153 vrf_id_to_name(zvni
->vrf_id
));
1155 char vni_str
[VNI_STR_LEN
];
1156 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1157 json_vni
= json_object_new_object();
1158 json_object_int_add(json_vni
, "vni", zvni
->vni
);
1159 json_object_string_add(json_vni
, "type", "L2");
1160 json_object_string_add(json_vni
, "vxlanIf",
1161 zvni
->vxlan_if
? zvni
->vxlan_if
->name
1163 json_object_int_add(json_vni
, "numMacs", num_macs
);
1164 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1165 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
1166 json_object_string_add(json_vni
, "tenantVrf",
1167 vrf_id_to_name(zvni
->vrf_id
));
1169 json_vtep_list
= json_object_new_array();
1170 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1171 json_ip_str
= json_object_new_string(
1172 inet_ntoa(zvtep
->vtep_ip
));
1173 json_object_array_add(json_vtep_list
,
1176 json_object_object_add(json_vni
, "remoteVteps",
1179 json_object_object_add(json
, vni_str
, json_vni
);
1184 * Inform BGP about local MACIP.
1186 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
1187 struct ipaddr
*ip
, uint8_t flags
,
1190 char buf
[ETHER_ADDR_STRLEN
];
1191 char buf2
[INET6_ADDRSTRLEN
];
1193 struct zserv
*client
= NULL
;
1194 struct stream
*s
= NULL
;
1196 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
1197 /* BGP may not be running. */
1201 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
1203 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
1204 stream_putl(s
, vni
);
1205 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
1208 if (IS_IPADDR_V4(ip
))
1209 ipa_len
= IPV4_MAX_BYTELEN
;
1210 else if (IS_IPADDR_V6(ip
))
1211 ipa_len
= IPV6_MAX_BYTELEN
;
1213 stream_putl(s
, ipa_len
); /* IP address length */
1215 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
1217 stream_putl(s
, 0); /* Just MAC. */
1219 stream_putc(s
, flags
); /* sticky mac/gateway mac */
1222 /* Write packet size. */
1223 stream_putw_at(s
, 0, stream_get_endp(s
));
1225 if (IS_ZEBRA_DEBUG_VXLAN
)
1227 "Send MACIP %s flags 0x%x MAC %s IP %s L2-VNI %u to %s",
1228 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
1229 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1230 ipaddr2str(ip
, buf2
, sizeof(buf2
)), vni
,
1231 zebra_route_string(client
->proto
));
1233 if (cmd
== ZEBRA_MACIP_ADD
)
1234 client
->macipadd_cnt
++;
1236 client
->macipdel_cnt
++;
1238 return zserv_send_message(client
, s
);
1242 * Make hash key for neighbors.
1244 static unsigned int neigh_hash_keymake(void *p
)
1246 zebra_neigh_t
*n
= p
;
1247 struct ipaddr
*ip
= &n
->ip
;
1249 if (IS_IPADDR_V4(ip
))
1250 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
1252 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
1253 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
1257 * Compare two neighbor hash structures.
1259 static int neigh_cmp(const void *p1
, const void *p2
)
1261 const zebra_neigh_t
*n1
= p1
;
1262 const zebra_neigh_t
*n2
= p2
;
1264 if (n1
== NULL
&& n2
== NULL
)
1267 if (n1
== NULL
|| n2
== NULL
)
1270 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
1274 * Callback to allocate neighbor hash entry.
1276 static void *zvni_neigh_alloc(void *p
)
1278 const zebra_neigh_t
*tmp_n
= p
;
1281 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
1288 * Add neighbor entry.
1290 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
1291 struct ethaddr
*mac
)
1293 zebra_neigh_t tmp_n
;
1294 zebra_neigh_t
*n
= NULL
;
1295 zebra_mac_t
*zmac
= NULL
;
1297 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
1298 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1299 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
1302 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1303 n
->state
= ZEBRA_NEIGH_INACTIVE
;
1305 /* Associate the neigh to mac */
1306 zmac
= zvni_mac_lookup(zvni
, mac
);
1308 listnode_add_sort(zmac
->neigh_list
, n
);
1314 * Delete neighbor entry.
1316 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1318 zebra_neigh_t
*tmp_n
;
1319 zebra_mac_t
*zmac
= NULL
;
1321 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
1323 listnode_delete(zmac
->neigh_list
, n
);
1325 /* Free the VNI hash entry and allocated memory. */
1326 tmp_n
= hash_release(zvni
->neigh_table
, n
);
1328 XFREE(MTYPE_NEIGH
, tmp_n
);
1334 * Free neighbor hash entry (callback)
1336 static void zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
1338 struct neigh_walk_ctx
*wctx
= arg
;
1339 zebra_neigh_t
*n
= backet
->data
;
1341 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1342 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
1343 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
1344 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
1345 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
1346 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
1347 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1348 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
1351 if (wctx
->uninstall
)
1352 zvni_neigh_uninstall(wctx
->zvni
, n
);
1354 zvni_neigh_del(wctx
->zvni
, n
);
1361 * Delete all neighbor entries from specific VTEP for a particular VNI.
1363 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
1364 struct in_addr
*r_vtep_ip
)
1366 struct neigh_walk_ctx wctx
;
1368 if (!zvni
->neigh_table
)
1371 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1373 wctx
.uninstall
= uninstall
;
1374 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
1375 wctx
.r_vtep_ip
= *r_vtep_ip
;
1377 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1381 * Delete all neighbor entries for this VNI.
1383 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
1386 struct neigh_walk_ctx wctx
;
1388 if (!zvni
->neigh_table
)
1391 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1393 wctx
.uninstall
= uninstall
;
1394 wctx
.upd_client
= upd_client
;
1397 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1401 * Look up neighbor hash entry.
1403 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
1408 memset(&tmp
, 0, sizeof(tmp
));
1409 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
1410 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
1415 /* Process all neigh associated to a mac upon local mac add event */
1416 static void zvni_process_neigh_on_local_mac_add(zebra_vni_t
*zvni
,
1419 zebra_neigh_t
*n
= NULL
;
1420 struct listnode
*node
= NULL
;
1421 char buf
[ETHER_ADDR_STRLEN
];
1422 char buf2
[INET6_ADDRSTRLEN
];
1424 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1425 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1426 /* MAC is learnt locally, program all inactive neigh
1427 * pointing to this mac */
1428 if (IS_ZEBRA_NEIGH_INACTIVE(n
)) {
1429 if (IS_ZEBRA_DEBUG_VXLAN
)
1431 "neigh %s (MAC %s) on L2-VNI %u is now ACTIVE",
1432 ipaddr2str(&n
->ip
, buf2
,
1434 prefix_mac2str(&n
->emac
, buf
,
1438 ZEBRA_NEIGH_SET_ACTIVE(n
);
1439 zvni_neigh_send_add_to_client(
1440 zvni
->vni
, &n
->ip
, &n
->emac
, n
->flags
);
1442 if (IS_ZEBRA_DEBUG_VXLAN
)
1444 "neigh %s (MAC %s) on VNI %u should NOT be ACTIVE",
1445 ipaddr2str(&n
->ip
, buf2
,
1447 prefix_mac2str(&n
->emac
, buf
,
1451 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1452 /* TODO: assume the neigh has moved too ?? */
1457 /* Process all neigh associated to a mac upon local mac del event */
1458 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
1461 zebra_neigh_t
*n
= NULL
;
1462 struct listnode
*node
= NULL
;
1463 char buf
[ETHER_ADDR_STRLEN
];
1464 char buf2
[INET6_ADDRSTRLEN
];
1466 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1467 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1468 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1469 if (IS_ZEBRA_DEBUG_VXLAN
)
1471 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1472 ipaddr2str(&n
->ip
, buf2
,
1474 prefix_mac2str(&n
->emac
, buf
,
1478 ZEBRA_NEIGH_SET_INACTIVE(n
);
1479 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1482 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1483 if (IS_ZEBRA_DEBUG_VXLAN
)
1485 "local MAC %s getting deleted on VNI %u has remote neigh %s",
1486 prefix_mac2str(&n
->emac
, buf
,
1489 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1494 /* process all neigh associated to a mac entry upon remote mac add */
1495 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
1498 zebra_neigh_t
*n
= NULL
;
1499 struct listnode
*node
= NULL
;
1500 char buf
[ETHER_ADDR_STRLEN
];
1501 char buf2
[INET6_ADDRSTRLEN
];
1503 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1504 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1505 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1506 if (IS_ZEBRA_DEBUG_VXLAN
)
1508 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1509 ipaddr2str(&n
->ip
, buf2
,
1511 prefix_mac2str(&n
->emac
, buf
,
1515 ZEBRA_NEIGH_SET_INACTIVE(n
);
1516 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1523 /* process all neigh associated to mac entry upon remote mac del */
1524 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
1527 zebra_neigh_t
*n
= NULL
;
1528 struct listnode
*node
= NULL
;
1529 char buf
[ETHER_ADDR_STRLEN
];
1530 char buf2
[INET6_ADDRSTRLEN
];
1532 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1533 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1534 if (IS_ZEBRA_DEBUG_VXLAN
)
1536 "remote MAC %s getting deleted on VNI %u has local neigh %s",
1537 prefix_mac2str(&n
->emac
, buf
,
1540 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1546 * Inform BGP about local neighbor addition.
1548 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
1549 struct ethaddr
*macaddr
,
1550 uint8_t neigh_flags
)
1554 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
1555 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
1557 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1562 * Inform BGP about local neighbor deletion.
1564 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
1565 struct ethaddr
*macaddr
, uint8_t flags
)
1567 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1572 * Install remote neighbor into the kernel.
1574 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1576 struct zebra_if
*zif
;
1577 struct zebra_l2info_vxlan
*vxl
;
1578 struct interface
*vlan_if
;
1580 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1583 zif
= zvni
->vxlan_if
->info
;
1586 vxl
= &zif
->l2info
.vxl
;
1588 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1592 return kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
);
1596 * Uninstall remote neighbor from the kernel.
1598 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1600 struct zebra_if
*zif
;
1601 struct zebra_l2info_vxlan
*vxl
;
1602 struct interface
*vlan_if
;
1604 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1607 if (!zvni
->vxlan_if
) {
1608 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
1613 zif
= zvni
->vxlan_if
->info
;
1616 vxl
= &zif
->l2info
.vxl
;
1617 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1621 return kernel_del_neigh(vlan_if
, &n
->ip
);
1625 * Install neighbor hash entry - called upon access VLAN change.
1627 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
1630 struct neigh_walk_ctx
*wctx
= ctxt
;
1632 n
= (zebra_neigh_t
*)backet
->data
;
1636 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
1637 zvni_neigh_install(wctx
->zvni
, n
);
1640 /* Get the VRR interface for SVI if any */
1641 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
1643 struct zebra_vrf
*zvrf
= NULL
;
1644 struct interface
*tmp_if
= NULL
;
1645 struct zebra_if
*zif
= NULL
;
1647 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1650 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
1655 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
1658 if (zif
->link
== ifp
)
1665 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1667 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1668 struct connected
*c
= NULL
;
1669 struct ethaddr macaddr
;
1671 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1673 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1676 memset(&ip
, 0, sizeof(struct ipaddr
));
1677 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1680 if (c
->address
->family
== AF_INET
) {
1681 ip
.ipa_type
= IPADDR_V4
;
1682 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1683 sizeof(struct in_addr
));
1684 } else if (c
->address
->family
== AF_INET6
) {
1685 ip
.ipa_type
= IPADDR_V6
;
1686 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1687 sizeof(struct in6_addr
));
1692 zvni_gw_macip_del(ifp
, zvni
, &ip
);
1698 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1700 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1701 struct connected
*c
= NULL
;
1702 struct ethaddr macaddr
;
1704 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1706 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1709 memset(&ip
, 0, sizeof(struct ipaddr
));
1710 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1713 if (c
->address
->family
== AF_INET
) {
1714 ip
.ipa_type
= IPADDR_V4
;
1715 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1716 sizeof(struct in_addr
));
1717 } else if (c
->address
->family
== AF_INET6
) {
1718 ip
.ipa_type
= IPADDR_V6
;
1719 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1720 sizeof(struct in6_addr
));
1725 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
1731 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
1734 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1735 struct connected
*c
= NULL
;
1736 struct ethaddr macaddr
;
1738 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1740 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1743 memcpy(&p
, c
->address
, sizeof(struct prefix
));
1745 /* skip link local address */
1746 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
1751 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1752 ZEBRA_IP_PREFIX_ROUTE_ADD
);
1754 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1755 ZEBRA_IP_PREFIX_ROUTE_DEL
);
1761 * zvni_gw_macip_add_to_client
1763 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
1764 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
1766 char buf
[ETHER_ADDR_STRLEN
];
1767 char buf2
[INET6_ADDRSTRLEN
];
1768 zebra_neigh_t
*n
= NULL
;
1769 zebra_mac_t
*mac
= NULL
;
1770 struct zebra_if
*zif
= NULL
;
1771 struct zebra_l2info_vxlan
*vxl
= NULL
;
1773 zif
= zvni
->vxlan_if
->info
;
1777 vxl
= &zif
->l2info
.vxl
;
1779 mac
= zvni_mac_lookup(zvni
, macaddr
);
1781 mac
= zvni_mac_add(zvni
, macaddr
);
1783 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
1784 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1785 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
1790 /* Set "local" forwarding info. */
1791 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
1792 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
1793 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
1794 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
1795 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
1796 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
1798 n
= zvni_neigh_lookup(zvni
, ip
);
1800 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
1803 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1804 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
1805 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1806 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
1811 /* Set "local" forwarding info. */
1812 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
1813 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
1814 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
1815 n
->ifindex
= ifp
->ifindex
;
1817 /* Only advertise in BGP if the knob is enabled */
1818 if (!advertise_gw_macip_enabled(zvni
))
1821 if (IS_ZEBRA_DEBUG_VXLAN
)
1823 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP",
1824 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1825 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1826 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1828 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, n
->flags
);
1834 * zvni_gw_macip_del_from_client
1836 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
1839 char buf1
[ETHER_ADDR_STRLEN
];
1840 char buf2
[INET6_ADDRSTRLEN
];
1841 zebra_neigh_t
*n
= NULL
;
1842 zebra_mac_t
*mac
= NULL
;
1844 /* If the neigh entry is not present nothing to do*/
1845 n
= zvni_neigh_lookup(zvni
, ip
);
1849 /* mac entry should be present */
1850 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
1852 zlog_err("MAC %s doesnt exists for neigh %s on VNI %u",
1853 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
1854 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1858 /* If the entry is not local nothing to do*/
1859 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
1862 /* only need to delete the entry from bgp if we sent it before */
1863 if (IS_ZEBRA_DEBUG_VXLAN
)
1865 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
1866 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1867 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
1868 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1870 /* Remove neighbor from BGP. */
1871 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
1872 ZEBRA_MACIP_TYPE_GW
);
1874 /* Delete this neighbor entry. */
1875 zvni_neigh_del(zvni
, n
);
1877 /* see if the mac needs to be deleted as well*/
1879 zvni_deref_ip2mac(zvni
, mac
, 0);
1884 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
1887 zebra_vni_t
*zvni
= NULL
;
1888 struct zebra_if
*zif
= NULL
;
1889 struct zebra_l2info_vxlan zl2_info
;
1890 struct interface
*vlan_if
= NULL
;
1891 struct interface
*vrr_if
= NULL
;
1892 struct interface
*ifp
;
1894 /* Add primary SVI MAC*/
1895 zvni
= (zebra_vni_t
*)backet
->data
;
1899 ifp
= zvni
->vxlan_if
;
1904 /* If down or not mapped to a bridge, we're done. */
1905 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1908 zl2_info
= zif
->l2info
.vxl
;
1911 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1915 /* Del primary MAC-IP */
1916 zvni_del_macip_for_intf(vlan_if
, zvni
);
1918 /* Del VRR MAC-IP - if any*/
1919 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1921 zvni_del_macip_for_intf(vrr_if
, zvni
);
1926 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
1929 zebra_vni_t
*zvni
= NULL
;
1930 struct zebra_if
*zif
= NULL
;
1931 struct zebra_l2info_vxlan zl2_info
;
1932 struct interface
*vlan_if
= NULL
;
1933 struct interface
*vrr_if
= NULL
;
1934 struct interface
*ifp
= NULL
;
1936 zvni
= (zebra_vni_t
*)backet
->data
;
1940 ifp
= zvni
->vxlan_if
;
1945 /* If down or not mapped to a bridge, we're done. */
1946 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1948 zl2_info
= zif
->l2info
.vxl
;
1951 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1955 /* Add primary SVI MAC-IP */
1956 zvni_add_macip_for_intf(vlan_if
, zvni
);
1958 /* Add VRR MAC-IP - if any*/
1959 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1961 zvni_add_macip_for_intf(vrr_if
, zvni
);
1966 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
1967 struct interface
*ifp
,
1969 struct ethaddr
*macaddr
)
1971 char buf
[ETHER_ADDR_STRLEN
];
1972 char buf2
[INET6_ADDRSTRLEN
];
1973 zebra_neigh_t
*n
= NULL
;
1974 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
1976 /* create a dummy MAC if the MAC is not already present */
1977 zmac
= zvni_mac_lookup(zvni
, macaddr
);
1979 if (IS_ZEBRA_DEBUG_VXLAN
)
1981 "AUTO MAC %s created for neigh %s on VNI %u",
1982 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1983 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1985 zmac
= zvni_mac_add(zvni
, macaddr
);
1987 zlog_warn("Failed to add MAC %s VNI %u",
1988 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1993 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
1994 memset(&zmac
->flags
, 0, sizeof(uint32_t));
1995 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
1998 /* If same entry already exists, it might be a change or it might be a
1999 * move from remote to local.
2001 n
= zvni_neigh_lookup(zvni
, ip
);
2003 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2004 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2006 /* Update any params and return - client doesn't
2007 * care about a purely local change.
2009 n
->ifindex
= ifp
->ifindex
;
2013 /* If the MAC has changed,
2014 * need to issue a delete first
2015 * as this means a different MACIP route.
2016 * Also, need to do some unlinking/relinking.
2018 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2020 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2022 listnode_delete(old_zmac
->neigh_list
, n
);
2023 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
2026 /* Update the forwarding info. */
2027 n
->ifindex
= ifp
->ifindex
;
2028 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2030 /* Link to new MAC */
2031 listnode_add_sort(zmac
->neigh_list
, n
);
2034 /* Neighbor has moved from remote to local. */
2036 /* If MAC has changed, do the unlink/link */
2037 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2039 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2041 listnode_delete(old_zmac
->neigh_list
,
2043 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
2046 /* Link to new MAC */
2047 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2048 listnode_add_sort(zmac
->neigh_list
, n
);
2051 /* Mark appropriately */
2052 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2053 n
->r_vtep_ip
.s_addr
= 0;
2054 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2055 n
->ifindex
= ifp
->ifindex
;
2058 /* New neighbor - create */
2059 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2062 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2063 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2064 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2065 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2068 /* Set "local" forwarding info. */
2069 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2070 n
->ifindex
= ifp
->ifindex
;
2073 /* Before we program this in BGP, we need to check if MAC is locally
2076 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
2077 if (IS_ZEBRA_DEBUG_VXLAN
)
2079 "Skipping neigh %s add to client as MAC %s is not local on VNI %u",
2080 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2081 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2088 if (IS_ZEBRA_DEBUG_VXLAN
)
2089 zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u",
2090 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2091 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2093 ZEBRA_NEIGH_SET_ACTIVE(n
);
2095 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, 0);
2098 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
2099 struct interface
*ifp
,
2101 struct ethaddr
*macaddr
,
2104 char buf
[ETHER_ADDR_STRLEN
];
2105 char buf2
[INET6_ADDRSTRLEN
];
2106 zebra_neigh_t
*n
= NULL
;
2107 zebra_mac_t
*zmac
= NULL
;
2109 /* If the neighbor is unknown, there is no further action. */
2110 n
= zvni_neigh_lookup(zvni
, ip
);
2114 /* If a remote entry, see if it needs to be refreshed */
2115 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2117 if (state
& NUD_STALE
)
2118 zvni_neigh_install(zvni
, n
);
2121 /* We got a "remote" neighbor notification for an entry
2122 * we think is local. This can happen in a multihoming
2123 * scenario - but only if the MAC is already "remote".
2124 * Just mark our entry as "remote".
2126 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2127 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2128 zlog_err("Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
2129 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
2130 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2135 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2136 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2137 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
2144 * Make hash key for MAC.
2146 static unsigned int mac_hash_keymake(void *p
)
2148 zebra_mac_t
*pmac
= p
;
2149 const void *pnt
= (void *)pmac
->macaddr
.octet
;
2151 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
2155 * Compare two MAC addresses.
2157 static int mac_cmp(const void *p1
, const void *p2
)
2159 const zebra_mac_t
*pmac1
= p1
;
2160 const zebra_mac_t
*pmac2
= p2
;
2162 if (pmac1
== NULL
&& pmac2
== NULL
)
2165 if (pmac1
== NULL
|| pmac2
== NULL
)
2168 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
2173 * Callback to allocate MAC hash entry.
2175 static void *zvni_mac_alloc(void *p
)
2177 const zebra_mac_t
*tmp_mac
= p
;
2180 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2183 return ((void *)mac
);
2189 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
2191 zebra_mac_t tmp_mac
;
2192 zebra_mac_t
*mac
= NULL
;
2194 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
2195 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
2196 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
2199 mac
->neigh_list
= list_new();
2200 mac
->neigh_list
->cmp
= (int (*)(void *, void *))neigh_cmp
;
2208 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2210 zebra_mac_t
*tmp_mac
;
2212 list_delete_and_null(&mac
->neigh_list
);
2214 /* Free the VNI hash entry and allocated memory. */
2215 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
2217 XFREE(MTYPE_MAC
, tmp_mac
);
2223 * Free MAC hash entry (callback)
2225 static void zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2227 struct mac_walk_ctx
*wctx
= arg
;
2228 zebra_mac_t
*mac
= backet
->data
;
2230 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
2231 || ((wctx
->flags
& DEL_REMOTE_MAC
)
2232 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
2233 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
2234 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
2235 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
2236 &wctx
->r_vtep_ip
))) {
2237 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
2238 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
2239 &mac
->macaddr
, mac
->flags
);
2242 if (wctx
->uninstall
)
2243 zvni_mac_uninstall(wctx
->zvni
, mac
, 0);
2245 zvni_mac_del(wctx
->zvni
, mac
);
2252 * Delete all MAC entries from specific VTEP for a particular VNI.
2254 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2255 struct in_addr
*r_vtep_ip
)
2257 struct mac_walk_ctx wctx
;
2259 if (!zvni
->mac_table
)
2262 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2264 wctx
.uninstall
= uninstall
;
2265 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
2266 wctx
.r_vtep_ip
= *r_vtep_ip
;
2268 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2272 * Delete all MAC entries for this VNI.
2274 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2277 struct mac_walk_ctx wctx
;
2279 if (!zvni
->mac_table
)
2282 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2284 wctx
.uninstall
= uninstall
;
2285 wctx
.upd_client
= upd_client
;
2288 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2292 * Look up MAC hash entry.
2294 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
2299 memset(&tmp
, 0, sizeof(tmp
));
2300 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
2301 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
2307 * Inform BGP about local MAC addition.
2309 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2314 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2315 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2316 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2317 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2319 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2324 * Inform BGP about local MAC deletion.
2326 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2331 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2332 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2333 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2334 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2336 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2341 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2342 * notifications, to see if they are of interest.
2344 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
2345 struct interface
*br_if
, vlanid_t vid
)
2347 struct zebra_ns
*zns
;
2348 struct route_node
*rn
;
2349 struct interface
*tmp_if
= NULL
;
2350 struct zebra_if
*zif
;
2351 struct zebra_l2info_bridge
*br
;
2352 struct zebra_l2info_vxlan
*vxl
= NULL
;
2353 uint8_t bridge_vlan_aware
;
2357 /* Determine if bridge is VLAN-aware or not */
2360 br
= &zif
->l2info
.br
;
2361 bridge_vlan_aware
= br
->vlan_aware
;
2363 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2364 /* TODO: Optimize with a hash. */
2365 zns
= zebra_ns_lookup(NS_DEFAULT
);
2366 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2367 tmp_if
= (struct interface
*)rn
->info
;
2371 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2373 if (!if_is_operative(tmp_if
))
2375 vxl
= &zif
->l2info
.vxl
;
2377 if (zif
->brslave_info
.br_if
!= br_if
)
2380 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2389 zvni
= zvni_lookup(vxl
->vni
);
2394 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2395 * neighbor notifications, to see if they are of interest.
2397 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
2398 struct interface
*br_if
)
2400 struct zebra_ns
*zns
;
2401 struct route_node
*rn
;
2402 struct interface
*tmp_if
= NULL
;
2403 struct zebra_if
*zif
;
2404 struct zebra_l2info_bridge
*br
;
2405 struct zebra_l2info_vxlan
*vxl
= NULL
;
2406 uint8_t bridge_vlan_aware
;
2414 /* Make sure the linked interface is a bridge. */
2415 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
2418 /* Determine if bridge is VLAN-aware or not */
2421 br
= &zif
->l2info
.br
;
2422 bridge_vlan_aware
= br
->vlan_aware
;
2423 if (bridge_vlan_aware
) {
2424 struct zebra_l2info_vlan
*vl
;
2426 if (!IS_ZEBRA_IF_VLAN(ifp
))
2431 vl
= &zif
->l2info
.vl
;
2435 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2436 /* TODO: Optimize with a hash. */
2437 zns
= zebra_ns_lookup(NS_DEFAULT
);
2438 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2439 tmp_if
= (struct interface
*)rn
->info
;
2443 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2445 if (!if_is_operative(tmp_if
))
2447 vxl
= &zif
->l2info
.vxl
;
2449 if (zif
->brslave_info
.br_if
!= br_if
)
2452 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2461 zvni
= zvni_lookup(vxl
->vni
);
2465 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
2467 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
2468 * linked to the bridge
2469 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
2472 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
2474 struct zebra_ns
*zns
;
2475 struct route_node
*rn
;
2476 struct interface
*tmp_if
= NULL
;
2477 struct zebra_if
*zif
;
2478 struct zebra_l2info_bridge
*br
;
2479 struct zebra_l2info_vlan
*vl
;
2480 uint8_t bridge_vlan_aware
;
2483 /* Defensive check, caller expected to invoke only with valid bridge. */
2487 /* Determine if bridge is VLAN-aware or not */
2490 br
= &zif
->l2info
.br
;
2491 bridge_vlan_aware
= br
->vlan_aware
;
2493 /* Check oper status of the SVI. */
2494 if (!bridge_vlan_aware
)
2495 return if_is_operative(br_if
) ? br_if
: NULL
;
2497 /* Identify corresponding VLAN interface. */
2498 /* TODO: Optimize with a hash. */
2499 zns
= zebra_ns_lookup(NS_DEFAULT
);
2500 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2501 tmp_if
= (struct interface
*)rn
->info
;
2502 /* Check oper status of the SVI. */
2503 if (!tmp_if
|| !if_is_operative(tmp_if
))
2506 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
2507 || zif
->link
!= br_if
)
2509 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
2511 if (vl
->vid
== vid
) {
2517 return found
? tmp_if
: NULL
;
2521 * Install remote MAC into the kernel.
2523 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2525 struct zebra_if
*zif
;
2526 struct zebra_l2info_vxlan
*vxl
;
2529 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2532 zif
= zvni
->vxlan_if
->info
;
2535 vxl
= &zif
->l2info
.vxl
;
2537 sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0;
2539 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
2540 mac
->fwd_info
.r_vtep_ip
, sticky
);
2544 * Uninstall remote MAC from the kernel. In the scenario where the MAC
2545 * moves to remote, we have to uninstall any existing local entry first.
2547 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
)
2549 struct zebra_if
*zif
;
2550 struct zebra_l2info_vxlan
*vxl
;
2551 struct in_addr vtep_ip
= {.s_addr
= 0};
2552 struct zebra_ns
*zns
;
2553 struct interface
*ifp
;
2555 if (!local
&& !(mac
->flags
& ZEBRA_MAC_REMOTE
))
2558 if (!zvni
->vxlan_if
) {
2559 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2564 zif
= zvni
->vxlan_if
->info
;
2567 vxl
= &zif
->l2info
.vxl
;
2570 zns
= zebra_ns_lookup(NS_DEFAULT
);
2571 ifp
= if_lookup_by_index_per_ns(zns
,
2572 mac
->fwd_info
.local
.ifindex
);
2573 if (!ifp
) // unexpected
2576 ifp
= zvni
->vxlan_if
;
2577 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
2580 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
,
2585 * Install MAC hash entry - called upon access VLAN change.
2587 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
2590 struct mac_walk_ctx
*wctx
= ctxt
;
2592 mac
= (zebra_mac_t
*)backet
->data
;
2596 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
2597 zvni_mac_install(wctx
->zvni
, mac
);
2601 * Decrement neighbor refcount of MAC; uninstall and free it if
2604 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
2607 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)
2608 || !list_isempty(mac
->neigh_list
))
2612 zvni_mac_uninstall(zvni
, mac
, 0);
2614 zvni_mac_del(zvni
, mac
);
2618 * Read and populate local MACs and neighbors corresponding to this VNI.
2620 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
2622 struct zebra_ns
*zns
;
2623 struct zebra_if
*zif
;
2624 struct interface
*vlan_if
;
2625 struct zebra_l2info_vxlan
*vxl
;
2626 struct interface
*vrr_if
;
2629 vxl
= &zif
->l2info
.vxl
;
2630 zns
= zebra_ns_lookup(NS_DEFAULT
);
2632 if (IS_ZEBRA_DEBUG_VXLAN
)
2634 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2635 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2636 zif
->brslave_info
.bridge_ifindex
);
2638 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
2639 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2642 /* Add SVI MAC-IP */
2643 zvni_add_macip_for_intf(vlan_if
, zvni
);
2645 /* Add VRR MAC-IP - if any*/
2646 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2648 zvni_add_macip_for_intf(vrr_if
, zvni
);
2650 neigh_read_for_vlan(zns
, vlan_if
);
2655 * Hash function for VNI.
2657 static unsigned int vni_hash_keymake(void *p
)
2659 const zebra_vni_t
*zvni
= p
;
2661 return (jhash_1word(zvni
->vni
, 0));
2665 * Compare 2 VNI hash entries.
2667 static int vni_hash_cmp(const void *p1
, const void *p2
)
2669 const zebra_vni_t
*zvni1
= p1
;
2670 const zebra_vni_t
*zvni2
= p2
;
2672 return (zvni1
->vni
== zvni2
->vni
);
2676 * Callback to allocate VNI hash entry.
2678 static void *zvni_alloc(void *p
)
2680 const zebra_vni_t
*tmp_vni
= p
;
2683 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
2684 zvni
->vni
= tmp_vni
->vni
;
2685 return ((void *)zvni
);
2689 * Look up VNI hash entry.
2691 static zebra_vni_t
*zvni_lookup(vni_t vni
)
2693 struct zebra_vrf
*zvrf
;
2694 zebra_vni_t tmp_vni
;
2695 zebra_vni_t
*zvni
= NULL
;
2697 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2699 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
2701 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
2707 * Add VNI hash entry.
2709 static zebra_vni_t
*zvni_add(vni_t vni
)
2711 struct zebra_vrf
*zvrf
;
2712 zebra_vni_t tmp_zvni
;
2713 zebra_vni_t
*zvni
= NULL
;
2715 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2717 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
2719 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
2722 /* Create hash table for MAC */
2724 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
2726 /* Create hash table for neighbors */
2727 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
2728 "Zebra VNI Neighbor Table");
2734 * Delete VNI hash entry.
2736 static int zvni_del(zebra_vni_t
*zvni
)
2738 struct zebra_vrf
*zvrf
;
2739 zebra_vni_t
*tmp_zvni
;
2741 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2744 zvni
->vxlan_if
= NULL
;
2746 /* Free the neighbor hash table. */
2747 hash_free(zvni
->neigh_table
);
2748 zvni
->neigh_table
= NULL
;
2750 /* Free the MAC hash table. */
2751 hash_free(zvni
->mac_table
);
2752 zvni
->mac_table
= NULL
;
2754 /* Free the VNI hash entry and allocated memory. */
2755 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
2757 XFREE(MTYPE_ZVNI
, tmp_zvni
);
2763 * Inform BGP about local VNI addition.
2765 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
2767 struct zserv
*client
;
2770 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2771 /* BGP may not be running. */
2775 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2777 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
2778 stream_putl(s
, zvni
->vni
);
2779 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
2780 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
2782 /* Write packet size. */
2783 stream_putw_at(s
, 0, stream_get_endp(s
));
2785 if (IS_ZEBRA_DEBUG_VXLAN
)
2786 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
2787 inet_ntoa(zvni
->local_vtep_ip
),
2788 vrf_id_to_name(zvni
->vrf_id
),
2789 zebra_route_string(client
->proto
));
2791 client
->vniadd_cnt
++;
2792 return zserv_send_message(client
, s
);
2796 * Inform BGP about local VNI deletion.
2798 static int zvni_send_del_to_client(vni_t vni
)
2800 struct zserv
*client
;
2803 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2804 /* BGP may not be running. */
2808 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2811 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
2812 stream_putl(s
, vni
);
2814 /* Write packet size. */
2815 stream_putw_at(s
, 0, stream_get_endp(s
));
2817 if (IS_ZEBRA_DEBUG_VXLAN
)
2818 zlog_debug("Send VNI_DEL %u to %s", vni
,
2819 zebra_route_string(client
->proto
));
2821 client
->vnidel_cnt
++;
2822 return zserv_send_message(client
, s
);
2826 * Build the VNI hash table by going over the VxLAN interfaces. This
2827 * is called when EVPN (advertise-all-vni) is enabled.
2829 static void zvni_build_hash_table()
2831 struct zebra_ns
*zns
;
2832 struct route_node
*rn
;
2833 struct interface
*ifp
;
2835 /* Walk VxLAN interfaces and create VNI hash. */
2836 zns
= zebra_ns_lookup(NS_DEFAULT
);
2837 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2839 zebra_vni_t
*zvni
= NULL
;
2840 zebra_l3vni_t
*zl3vni
= NULL
;
2841 struct zebra_if
*zif
;
2842 struct zebra_l2info_vxlan
*vxl
;
2844 ifp
= (struct interface
*)rn
->info
;
2848 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2851 vxl
= &zif
->l2info
.vxl
;
2854 /* L3-VNI and L2-VNI are handled seperately */
2855 zl3vni
= zl3vni_lookup(vni
);
2858 if (IS_ZEBRA_DEBUG_VXLAN
)
2860 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
2861 ifp
->name
, ifp
->ifindex
, vni
);
2863 /* associate with vxlan_if */
2864 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
2865 zl3vni
->vxlan_if
= ifp
;
2868 * we need to associate with SVI.
2869 * we can associate with svi-if only after association
2870 * with vxlan-intf is complete
2872 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
2874 if (is_l3vni_oper_up(zl3vni
))
2875 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
2878 struct interface
*vlan_if
= NULL
;
2880 if (IS_ZEBRA_DEBUG_VXLAN
)
2882 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
2883 ifp
->name
, ifp
->ifindex
, vni
,
2884 inet_ntoa(vxl
->vtep_ip
));
2886 /* VNI hash entry is not expected to exist. */
2887 zvni
= zvni_lookup(vni
);
2890 "VNI hash already present for IF %s(%u) L2-VNI %u",
2891 ifp
->name
, ifp
->ifindex
, vni
);
2895 zvni
= zvni_add(vni
);
2898 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
2899 ifp
->name
, ifp
->ifindex
, vni
);
2903 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
2904 zvni
->vxlan_if
= ifp
;
2905 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
2906 zif
->brslave_info
.br_if
);
2908 zvni
->vrf_id
= vlan_if
->vrf_id
;
2909 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
2911 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
2915 /* Inform BGP if intf is up and mapped to bridge. */
2916 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
2917 zvni_send_add_to_client(zvni
);
2923 * See if remote VTEP matches with prefix.
2925 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
2927 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
2931 * Locate remote VTEP in VNI hash table.
2933 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2935 zebra_vtep_t
*zvtep
;
2940 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2941 if (zvni_vtep_match(vtep_ip
, zvtep
))
2949 * Add remote VTEP to VNI hash table.
2951 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2953 zebra_vtep_t
*zvtep
;
2955 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
2957 zlog_err("Failed to alloc VTEP entry, VNI %u", zvni
->vni
);
2961 zvtep
->vtep_ip
= *vtep_ip
;
2964 zvni
->vteps
->prev
= zvtep
;
2965 zvtep
->next
= zvni
->vteps
;
2966 zvni
->vteps
= zvtep
;
2972 * Remove remote VTEP from VNI hash table.
2974 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
2977 zvtep
->next
->prev
= zvtep
->prev
;
2979 zvtep
->prev
->next
= zvtep
->next
;
2981 zvni
->vteps
= zvtep
->next
;
2983 zvtep
->prev
= zvtep
->next
= NULL
;
2984 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
2990 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
2991 * uninstall from kernel if asked to.
2993 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
2995 zebra_vtep_t
*zvtep
, *zvtep_next
;
3000 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
3001 zvtep_next
= zvtep
->next
;
3003 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
3004 zvni_vtep_del(zvni
, zvtep
);
3011 * Install remote VTEP into the kernel.
3013 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3015 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3019 * Uninstall remote VTEP from the kernel.
3021 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3023 if (!zvni
->vxlan_if
) {
3024 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
3029 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3033 * Cleanup VNI/VTEP and update kernel
3035 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
3037 zebra_vni_t
*zvni
= NULL
;
3038 zebra_l3vni_t
*zl3vni
= NULL
;
3039 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
3041 zvni
= (zebra_vni_t
*)backet
->data
;
3045 /* remove from l3-vni list */
3047 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
3049 listnode_delete(zl3vni
->l2vnis
, zvni
);
3051 /* Free up all neighbors and MACs, if any. */
3052 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
3053 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
3055 /* Free up all remote VTEPs, if any. */
3056 zvni_vtep_del_all(zvni
, 1);
3058 /* Delete the hash entry. */
3063 static void zl3vni_cleanup_all(struct hash_backet
*backet
, void *args
)
3065 zebra_l3vni_t
*zl3vni
= NULL
;
3067 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
3071 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
3074 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
3075 struct prefix
*host
)
3077 struct host_rb_entry lookup
;
3078 struct host_rb_entry
*hle
;
3080 memset(&lookup
, 0, sizeof(lookup
));
3081 memcpy(&lookup
.p
, host
, sizeof(*host
));
3083 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3087 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
3088 memcpy(hle
, &lookup
, sizeof(lookup
));
3090 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
3093 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
3095 struct host_rb_entry lookup
;
3096 struct host_rb_entry
*hle
;
3098 memset(&lookup
, 0, sizeof(lookup
));
3099 memcpy(&lookup
.p
, host
, sizeof(*host
));
3101 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3103 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
3104 XFREE(MTYPE_HOST_PREFIX
, hle
);
3111 * Look up MAC hash entry.
3113 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
3114 struct ethaddr
*rmac
)
3119 memset(&tmp
, 0, sizeof(tmp
));
3120 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
3121 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
3127 * Callback to allocate RMAC hash entry.
3129 static void *zl3vni_rmac_alloc(void *p
)
3131 const zebra_mac_t
*tmp_rmac
= p
;
3134 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3137 return ((void *)zrmac
);
3141 * Add RMAC entry to l3-vni
3143 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
3145 zebra_mac_t tmp_rmac
;
3146 zebra_mac_t
*zrmac
= NULL
;
3148 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
3149 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
3150 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
3153 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
3155 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
3156 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
3164 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3166 zebra_mac_t
*tmp_rmac
;
3167 struct host_rb_entry
*hle
;
3169 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3170 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
3172 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
3173 XFREE(MTYPE_HOST_PREFIX
, hle
);
3176 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
3178 XFREE(MTYPE_MAC
, tmp_rmac
);
3184 * Install remote RMAC into the kernel.
3186 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3188 struct zebra_if
*zif
= NULL
;
3189 struct zebra_l2info_vxlan
*vxl
= NULL
;
3191 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3192 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3195 zif
= zl3vni
->vxlan_if
->info
;
3199 vxl
= &zif
->l2info
.vxl
;
3201 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3202 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3206 * Uninstall remote RMAC from the kernel.
3208 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3210 char buf
[ETHER_ADDR_STRLEN
];
3211 struct zebra_if
*zif
= NULL
;
3212 struct zebra_l2info_vxlan
*vxl
= NULL
;
3214 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3215 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3218 if (!zl3vni
->vxlan_if
) {
3220 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
3221 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
3222 zl3vni
->vni
, zl3vni
);
3226 zif
= zl3vni
->vxlan_if
->info
;
3230 vxl
= &zif
->l2info
.vxl
;
3232 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3233 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3236 /* handle rmac add */
3237 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
3238 struct ipaddr
*vtep_ip
,
3239 struct prefix
*host_prefix
)
3241 char buf
[ETHER_ADDR_STRLEN
];
3242 char buf1
[INET6_ADDRSTRLEN
];
3243 zebra_mac_t
*zrmac
= NULL
;
3245 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3248 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
3251 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
3252 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3254 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
3257 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
3258 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
3260 /* install rmac in kernel */
3261 zl3vni_rmac_install(zl3vni
, zrmac
);
3264 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
3270 /* handle rmac delete */
3271 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
3272 struct prefix
*host_prefix
)
3274 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
3276 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3277 /* uninstall from kernel */
3278 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3280 /* del the rmac entry */
3281 zl3vni_rmac_del(zl3vni
, zrmac
);
3286 * Look up nh hash entry on a l3-vni.
3288 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3293 memset(&tmp
, 0, sizeof(tmp
));
3294 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
3295 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
3302 * Callback to allocate NH hash entry on L3-VNI.
3304 static void *zl3vni_nh_alloc(void *p
)
3306 const zebra_neigh_t
*tmp_n
= p
;
3309 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
3316 * Add neighbor entry.
3318 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3319 struct ethaddr
*mac
)
3321 zebra_neigh_t tmp_n
;
3322 zebra_neigh_t
*n
= NULL
;
3324 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
3325 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
3326 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
3329 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
3331 memcpy(&n
->emac
, mac
, ETH_ALEN
);
3332 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3333 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
3339 * Delete neighbor entry.
3341 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3343 zebra_neigh_t
*tmp_n
;
3344 struct host_rb_entry
*hle
;
3346 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
3347 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
3349 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
3350 XFREE(MTYPE_HOST_PREFIX
, hle
);
3353 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
3355 XFREE(MTYPE_NEIGH
, tmp_n
);
3361 * Install remote nh as neigh into the kernel.
3363 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3365 if (!is_l3vni_oper_up(zl3vni
))
3368 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3369 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3372 return kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
);
3376 * Uninstall remote nh from the kernel.
3378 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3380 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3381 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3384 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
3387 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
3390 /* add remote vtep as a neigh entry */
3391 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
3392 struct ethaddr
*rmac
,
3393 struct prefix
*host_prefix
)
3395 char buf
[ETHER_ADDR_STRLEN
];
3396 char buf1
[INET6_ADDRSTRLEN
];
3397 zebra_neigh_t
*nh
= NULL
;
3399 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3401 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
3405 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
3406 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
3407 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3412 /* install the nh neigh in kernel */
3413 zl3vni_nh_install(zl3vni
, nh
);
3416 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
3421 /* handle nh neigh delete */
3422 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
3423 struct prefix
*host_prefix
)
3425 rb_delete_host(&nh
->host_rb
, host_prefix
);
3427 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
3428 /* uninstall from kernel */
3429 zl3vni_nh_uninstall(zl3vni
, nh
);
3431 /* delete the nh entry */
3432 zl3vni_nh_del(zl3vni
, nh
);
3436 /* handle neigh update from kernel - the only thing of interest is to
3437 * readd stale entries.
3439 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3443 zebra_neigh_t
*n
= NULL
;
3445 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3449 /* all next hop neigh are remote and installed by frr.
3450 * If the kernel has aged this entry, re-install.
3452 if (state
& NUD_STALE
)
3453 zl3vni_nh_install(zl3vni
, n
);
3458 /* handle neigh delete from kernel */
3459 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3461 zebra_neigh_t
*n
= NULL
;
3463 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3467 /* all next hop neigh are remote and installed by frr.
3468 * If we get an age out notification for these neigh entries, we have to
3471 zl3vni_nh_install(zl3vni
, n
);
3477 * Hash function for L3 VNI.
3479 static unsigned int l3vni_hash_keymake(void *p
)
3481 const zebra_l3vni_t
*zl3vni
= p
;
3483 return jhash_1word(zl3vni
->vni
, 0);
3487 * Compare 2 L3 VNI hash entries.
3489 static int l3vni_hash_cmp(const void *p1
, const void *p2
)
3491 const zebra_l3vni_t
*zl3vni1
= p1
;
3492 const zebra_l3vni_t
*zl3vni2
= p2
;
3494 return (zl3vni1
->vni
== zl3vni2
->vni
);
3498 * Callback to allocate L3 VNI hash entry.
3500 static void *zl3vni_alloc(void *p
)
3502 zebra_l3vni_t
*zl3vni
= NULL
;
3503 const zebra_l3vni_t
*tmp_l3vni
= p
;
3505 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
3506 zl3vni
->vni
= tmp_l3vni
->vni
;
3507 return ((void *)zl3vni
);
3511 * Look up L3 VNI hash entry.
3513 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
3515 struct zebra_ns
*zns
;
3516 zebra_l3vni_t tmp_l3vni
;
3517 zebra_l3vni_t
*zl3vni
= NULL
;
3519 zns
= zebra_ns_lookup(NS_DEFAULT
);
3521 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
3522 tmp_l3vni
.vni
= vni
;
3523 zl3vni
= hash_lookup(zns
->l3vni_table
, &tmp_l3vni
);
3529 * Add L3 VNI hash entry.
3531 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
3533 zebra_l3vni_t tmp_zl3vni
;
3534 struct zebra_ns
*zns
= NULL
;
3535 zebra_l3vni_t
*zl3vni
= NULL
;
3537 zns
= zebra_ns_lookup(NS_DEFAULT
);
3540 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
3541 tmp_zl3vni
.vni
= vni
;
3543 zl3vni
= hash_get(zns
->l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
3546 zl3vni
->vrf_id
= vrf_id
;
3547 zl3vni
->svi_if
= NULL
;
3548 zl3vni
->vxlan_if
= NULL
;
3549 zl3vni
->l2vnis
= list_new();
3550 zl3vni
->l2vnis
->cmp
= (int (*)(void *, void *))vni_hash_cmp
;
3552 /* Create hash table for remote RMAC */
3553 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
3554 "Zebra L3-VNI RMAC-Table");
3556 /* Create hash table for neighbors */
3557 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3558 "Zebra L3-VNI next-hop table");
3564 * Delete L3 VNI hash entry.
3566 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
3568 struct zebra_ns
*zns
;
3569 zebra_l3vni_t
*tmp_zl3vni
;
3571 zns
= zebra_ns_lookup(NS_DEFAULT
);
3574 /* free the list of l2vnis */
3575 list_delete_and_null(&zl3vni
->l2vnis
);
3576 zl3vni
->l2vnis
= NULL
;
3578 /* Free the rmac table */
3579 hash_free(zl3vni
->rmac_table
);
3580 zl3vni
->rmac_table
= NULL
;
3582 /* Free the nh table */
3583 hash_free(zl3vni
->nh_table
);
3584 zl3vni
->nh_table
= NULL
;
3586 /* Free the VNI hash entry and allocated memory. */
3587 tmp_zl3vni
= hash_release(zns
->l3vni_table
, zl3vni
);
3589 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
3594 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
3596 struct zebra_ns
*zns
= NULL
;
3597 struct route_node
*rn
= NULL
;
3598 struct interface
*ifp
= NULL
;
3600 /* loop through all vxlan-interface */
3601 zns
= zebra_ns_lookup(NS_DEFAULT
);
3602 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3604 struct zebra_if
*zif
= NULL
;
3605 struct zebra_l2info_vxlan
*vxl
= NULL
;
3607 ifp
= (struct interface
*)rn
->info
;
3612 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3615 vxl
= &zif
->l2info
.vxl
;
3616 if (vxl
->vni
== zl3vni
->vni
) {
3617 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3625 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
3627 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
3628 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
3633 if (!zl3vni
->vxlan_if
)
3636 zif
= zl3vni
->vxlan_if
->info
;
3640 vxl
= &zif
->l2info
.vxl
;
3642 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3645 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
3647 struct zebra_vrf
*zvrf
= NULL
;
3649 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
3653 return zl3vni_lookup(zvrf
->l3vni
);
3657 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3658 * neighbor notifications, to see if they are of interest.
3660 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
3661 struct interface
*br_if
)
3665 uint8_t bridge_vlan_aware
= 0;
3666 zebra_l3vni_t
*zl3vni
= NULL
;
3667 struct zebra_ns
*zns
= NULL
;
3668 struct route_node
*rn
= NULL
;
3669 struct zebra_if
*zif
= NULL
;
3670 struct interface
*tmp_if
= NULL
;
3671 struct zebra_l2info_bridge
*br
= NULL
;
3672 struct zebra_l2info_vxlan
*vxl
= NULL
;
3677 /* Make sure the linked interface is a bridge. */
3678 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3681 /* Determine if bridge is VLAN-aware or not */
3684 br
= &zif
->l2info
.br
;
3685 bridge_vlan_aware
= br
->vlan_aware
;
3686 if (bridge_vlan_aware
) {
3687 struct zebra_l2info_vlan
*vl
;
3689 if (!IS_ZEBRA_IF_VLAN(ifp
))
3694 vl
= &zif
->l2info
.vl
;
3698 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3699 /* TODO: Optimize with a hash. */
3700 zns
= zebra_ns_lookup(NS_DEFAULT
);
3701 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3702 tmp_if
= (struct interface
*)rn
->info
;
3706 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3708 if (!if_is_operative(tmp_if
))
3710 vxl
= &zif
->l2info
.vxl
;
3712 if (zif
->brslave_info
.br_if
!= br_if
)
3715 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3724 zl3vni
= zl3vni_lookup(vxl
->vni
);
3729 * Inform BGP about l3-vni.
3731 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
3733 struct stream
*s
= NULL
;
3734 struct zserv
*client
= NULL
;
3735 struct ethaddr rmac
;
3736 char buf
[ETHER_ADDR_STRLEN
];
3738 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3739 /* BGP may not be running. */
3744 memset(&rmac
, 0, sizeof(struct ethaddr
));
3745 zl3vni_get_rmac(zl3vni
, &rmac
);
3747 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3749 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
3750 stream_putl(s
, zl3vni
->vni
);
3751 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
3752 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
3753 stream_put(s
, &zl3vni
->filter
, sizeof(int));
3755 /* Write packet size. */
3756 stream_putw_at(s
, 0, stream_get_endp(s
));
3758 if (IS_ZEBRA_DEBUG_VXLAN
)
3760 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
3761 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3762 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
3763 inet_ntoa(zl3vni
->local_vtep_ip
),
3764 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
3765 ? "prefix-routes-only"
3767 zebra_route_string(client
->proto
));
3769 client
->l3vniadd_cnt
++;
3770 return zserv_send_message(client
, s
);
3774 * Inform BGP about local l3-VNI deletion.
3776 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
3778 struct stream
*s
= NULL
;
3779 struct zserv
*client
= NULL
;
3781 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3782 /* BGP may not be running. */
3786 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3788 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
3789 stream_putl(s
, zl3vni
->vni
);
3791 /* Write packet size. */
3792 stream_putw_at(s
, 0, stream_get_endp(s
));
3794 if (IS_ZEBRA_DEBUG_VXLAN
)
3795 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
3796 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3797 zebra_route_string(client
->proto
));
3799 client
->l3vnidel_cnt
++;
3800 return zserv_send_message(client
, s
);
3803 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
3808 /* send l3vni add to BGP */
3809 zl3vni_send_add_to_client(zl3vni
);
3812 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
3817 /* send l3-vni del to BGP*/
3818 zl3vni_send_del_to_client(zl3vni
);
3821 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
, void *ctxt
)
3823 zebra_vni_t
*zvni
= (zebra_vni_t
*)backet
->data
;
3824 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
3826 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
3827 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3831 * handle transition of vni from l2 to l3 and vice versa
3833 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
3836 zebra_vni_t
*zvni
= NULL
;
3838 /* There is a possibility that VNI notification was already received
3839 * from kernel and we programmed it as L2-VNI
3840 * In such a case we need to delete this L2-VNI first, so
3841 * that it can be reprogrammed as L3-VNI in the system. It is also
3842 * possible that the vrf-vni mapping is removed from FRR while the vxlan
3843 * interface is still present in kernel. In this case to keep it
3844 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
3847 /* Locate hash entry */
3848 zvni
= zvni_lookup(vni
);
3852 if (IS_ZEBRA_DEBUG_VXLAN
)
3853 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
3855 /* Delete VNI from BGP. */
3856 zvni_send_del_to_client(zvni
->vni
);
3858 /* Free up all neighbors and MAC, if any. */
3859 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
3860 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
3862 /* Free up all remote VTEPs, if any. */
3863 zvni_vtep_del_all(zvni
, 0);
3865 /* Delete the hash entry. */
3866 if (zvni_del(zvni
)) {
3867 zlog_err("Failed to del VNI hash %p, VNI %u", zvni
,
3872 /* TODO_MITESH: This needs to be thought through. We don't have
3873 * enough information at this point to reprogram the vni as
3874 * l2-vni. One way is to store the required info in l3-vni and
3875 * used it solely for this purpose
3882 /* delete and uninstall rmac hash entry */
3883 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
, void *ctx
)
3885 zebra_mac_t
*zrmac
= NULL
;
3886 zebra_l3vni_t
*zl3vni
= NULL
;
3888 zrmac
= (zebra_mac_t
*)backet
->data
;
3889 zl3vni
= (zebra_l3vni_t
*)ctx
;
3890 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3891 zl3vni_rmac_del(zl3vni
, zrmac
);
3894 /* delete and uninstall nh hash entry */
3895 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
, void *ctx
)
3897 zebra_neigh_t
*n
= NULL
;
3898 zebra_l3vni_t
*zl3vni
= NULL
;
3900 n
= (zebra_neigh_t
*)backet
->data
;
3901 zl3vni
= (zebra_l3vni_t
*)ctx
;
3902 zl3vni_nh_uninstall(zl3vni
, n
);
3903 zl3vni_nh_del(zl3vni
, n
);
3906 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
3909 struct zserv
*client
= NULL
;
3910 struct stream
*s
= NULL
;
3911 char buf
[PREFIX_STRLEN
];
3913 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3914 /* BGP may not be running. */
3918 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3920 zclient_create_header(s
, cmd
, vrf_id
);
3921 stream_put(s
, p
, sizeof(struct prefix
));
3923 /* Write packet size. */
3924 stream_putw_at(s
, 0, stream_get_endp(s
));
3926 if (IS_ZEBRA_DEBUG_VXLAN
)
3927 zlog_debug("Send ip prefix %s %s on vrf %s",
3928 prefix2str(p
, buf
, sizeof(buf
)),
3929 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
3930 vrf_id_to_name(vrf_id
));
3932 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
3933 client
->prefixadd_cnt
++;
3935 client
->prefixdel_cnt
++;
3937 return zserv_send_message(client
, s
);
3940 /* re-add remote rmac if needed */
3941 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
3942 struct ethaddr
*rmac
)
3944 char buf
[ETHER_ADDR_STRLEN
];
3945 zebra_mac_t
*zrmac
= NULL
;
3947 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3951 if (IS_ZEBRA_DEBUG_VXLAN
)
3952 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
3953 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
3955 zl3vni_rmac_install(zl3vni
, zrmac
);
3959 /* Public functions */
3961 int is_l3vni_for_prefix_routes_only(vni_t vni
)
3963 zebra_l3vni_t
*zl3vni
= NULL
;
3965 zl3vni
= zl3vni_lookup(vni
);
3969 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
3972 /* handle evpn route in vrf table */
3973 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
3974 struct ipaddr
*vtep_ip
,
3975 struct prefix
*host_prefix
)
3977 zebra_l3vni_t
*zl3vni
= NULL
;
3978 struct ipaddr ipv4_vtep
;
3980 zl3vni
= zl3vni_from_vrf(vrf_id
);
3981 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
3985 * add the next hop neighbor -
3986 * neigh to be installed is the ipv6 nexthop neigh
3988 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
3991 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
3992 * address. Rmac is programmed against the ipv4 vtep because we only
3993 * support ipv4 tunnels in the h/w right now
3995 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
3996 ipv4_vtep
.ipa_type
= IPADDR_V4
;
3997 if (vtep_ip
->ipa_type
== IPADDR_V6
)
3998 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
3999 &(ipv4_vtep
.ipaddr_v4
));
4001 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
4002 sizeof(struct in_addr
));
4005 * add the rmac - remote rmac to be installed is against the ipv4
4008 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
4011 /* handle evpn vrf route delete */
4012 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
4013 struct ipaddr
*vtep_ip
,
4014 struct prefix
*host_prefix
)
4016 zebra_l3vni_t
*zl3vni
= NULL
;
4017 zebra_neigh_t
*nh
= NULL
;
4018 zebra_mac_t
*zrmac
= NULL
;
4020 zl3vni
= zl3vni_from_vrf(vrf_id
);
4024 /* find the next hop entry and rmac entry */
4025 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4028 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
4030 /* delete the next hop entry */
4031 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
4033 /* delete the rmac entry */
4035 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
4039 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
4040 struct ethaddr
*rmac
,
4043 zebra_l3vni_t
*zl3vni
= NULL
;
4044 zebra_mac_t
*zrmac
= NULL
;
4045 json_object
*json
= NULL
;
4047 if (!is_evpn_enabled()) {
4049 vty_out(vty
, "{}\n");
4054 json
= json_object_new_object();
4056 zl3vni
= zl3vni_lookup(l3vni
);
4059 vty_out(vty
, "{}\n");
4061 vty_out(vty
, "%% L3-VNI %u doesnt exist\n", l3vni
);
4065 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4068 vty_out(vty
, "{}\n");
4071 "%% Requested RMAC doesnt exist in L3-VNI %u",
4076 zl3vni_print_rmac(zrmac
, vty
, json
);
4079 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4080 json
, JSON_C_TO_STRING_PRETTY
));
4081 json_object_free(json
);
4085 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
,
4088 zebra_l3vni_t
*zl3vni
;
4090 struct rmac_walk_ctx wctx
;
4091 json_object
*json
= NULL
;
4093 if (!is_evpn_enabled())
4096 zl3vni
= zl3vni_lookup(l3vni
);
4099 vty_out(vty
, "{}\n");
4101 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4104 num_rmacs
= hashcount(zl3vni
->rmac_table
);
4109 json
= json_object_new_object();
4111 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
4115 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
4117 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
4119 json_object_int_add(json
, "numRmacs", num_rmacs
);
4121 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
4124 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4125 json
, JSON_C_TO_STRING_PRETTY
));
4126 json_object_free(json
);
4130 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, uint8_t use_json
)
4132 struct zebra_ns
*zns
= NULL
;
4133 json_object
*json
= NULL
;
4136 if (!is_evpn_enabled()) {
4138 vty_out(vty
, "{}\n");
4142 zns
= zebra_ns_lookup(NS_DEFAULT
);
4145 vty_out(vty
, "{}\n");
4150 json
= json_object_new_object();
4154 hash_iterate(zns
->l3vni_table
,
4155 (void (*)(struct hash_backet
*,
4156 void *))zl3vni_print_rmac_hash_all_vni
,
4160 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4161 json
, JSON_C_TO_STRING_PRETTY
));
4162 json_object_free(json
);
4166 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
4167 struct ipaddr
*ip
, uint8_t use_json
)
4169 zebra_l3vni_t
*zl3vni
= NULL
;
4170 zebra_neigh_t
*n
= NULL
;
4171 json_object
*json
= NULL
;
4173 if (!is_evpn_enabled()) {
4175 vty_out(vty
, "{}\n");
4180 json
= json_object_new_object();
4182 zl3vni
= zl3vni_lookup(l3vni
);
4185 vty_out(vty
, "{}\n");
4187 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4191 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4194 vty_out(vty
, "{}\n");
4197 "%% Requested next-hop not present for L3-VNI %u",
4202 zl3vni_print_nh(n
, vty
, json
);
4205 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4206 json
, JSON_C_TO_STRING_PRETTY
));
4207 json_object_free(json
);
4211 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, uint8_t use_json
)
4214 struct nh_walk_ctx wctx
;
4215 json_object
*json
= NULL
;
4216 zebra_l3vni_t
*zl3vni
= NULL
;
4218 if (!is_evpn_enabled())
4221 zl3vni
= zl3vni_lookup(l3vni
);
4224 vty_out(vty
, "{}\n");
4226 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4230 num_nh
= hashcount(zl3vni
->nh_table
);
4235 json
= json_object_new_object();
4240 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
4242 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
4244 json_object_int_add(json
, "numNextHops", num_nh
);
4246 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
4249 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4250 json
, JSON_C_TO_STRING_PRETTY
));
4251 json_object_free(json
);
4255 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, uint8_t use_json
)
4257 struct zebra_ns
*zns
= NULL
;
4258 json_object
*json
= NULL
;
4261 if (!is_evpn_enabled()) {
4263 vty_out(vty
, "{}\n");
4267 zns
= zebra_ns_lookup(NS_DEFAULT
);
4272 json
= json_object_new_object();
4276 hash_iterate(zns
->l3vni_table
,
4277 (void (*)(struct hash_backet
*,
4278 void *))zl3vni_print_nh_hash_all_vni
,
4282 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4283 json
, JSON_C_TO_STRING_PRETTY
));
4284 json_object_free(json
);
4290 * Display L3 VNI information (VTY command handler).
4292 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, uint8_t use_json
)
4295 json_object
*json
= NULL
;
4296 zebra_l3vni_t
*zl3vni
= NULL
;
4298 if (!is_evpn_enabled()) {
4300 vty_out(vty
, "{}\n");
4304 zl3vni
= zl3vni_lookup(vni
);
4307 vty_out(vty
, "{}\n");
4309 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4314 json
= json_object_new_object();
4318 zl3vni_print(zl3vni
, (void *)args
);
4321 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4322 json
, JSON_C_TO_STRING_PRETTY
));
4323 json_object_free(json
);
4327 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4328 json_object
*json_vrfs
)
4330 char buf
[ETHER_ADDR_STRLEN
];
4331 zebra_l3vni_t
*zl3vni
= NULL
;
4333 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4338 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
4339 zvrf_name(zvrf
), zl3vni
->vni
,
4340 zl3vni_vxlan_if_name(zl3vni
),
4341 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
4342 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4344 json_object
*json_vrf
= NULL
;
4345 json_vrf
= json_object_new_object();
4346 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
4347 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
4348 json_object_string_add(json_vrf
, "vxlanIntf",
4349 zl3vni_vxlan_if_name(zl3vni
));
4350 json_object_string_add(json_vrf
, "sviIntf",
4351 zl3vni_svi_if_name(zl3vni
));
4352 json_object_string_add(json_vrf
, "state",
4353 zl3vni_state2str(zl3vni
));
4354 json_object_string_add(
4355 json_vrf
, "routerMac",
4356 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4357 json_object_array_add(json_vrfs
, json_vrf
);
4362 * Display Neighbors for a VNI (VTY command handler).
4364 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4365 vni_t vni
, uint8_t use_json
)
4369 struct neigh_walk_ctx wctx
;
4370 json_object
*json
= NULL
;
4372 if (!is_evpn_enabled())
4374 zvni
= zvni_lookup(vni
);
4377 vty_out(vty
, "{}\n");
4379 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4382 num_neigh
= hashcount(zvni
->neigh_table
);
4387 json
= json_object_new_object();
4389 /* Since we have IPv6 addresses to deal with which can vary widely in
4390 * size, we try to be a bit more elegant in display by first computing
4391 * the maximum width.
4393 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4396 wctx
.addr_width
= 15;
4398 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4402 "Number of ARPs (local and remote) known for this VNI: %u\n",
4404 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
4405 "Type", "MAC", "Remote VTEP");
4407 json_object_int_add(json
, "numArpNd", num_neigh
);
4409 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4411 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4412 json
, JSON_C_TO_STRING_PRETTY
));
4413 json_object_free(json
);
4418 * Display neighbors across all VNIs (VTY command handler).
4420 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4423 json_object
*json
= NULL
;
4426 if (!is_evpn_enabled())
4430 json
= json_object_new_object();
4434 hash_iterate(zvrf
->vni_table
,
4435 (void (*)(struct hash_backet
*,
4436 void *))zvni_print_neigh_hash_all_vni
,
4439 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4440 json
, JSON_C_TO_STRING_PRETTY
));
4441 json_object_free(json
);
4446 * Display specific neighbor for a VNI, if present (VTY command handler).
4448 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
4449 struct zebra_vrf
*zvrf
, vni_t vni
,
4450 struct ipaddr
*ip
, uint8_t use_json
)
4454 json_object
*json
= NULL
;
4456 if (!is_evpn_enabled())
4458 zvni
= zvni_lookup(vni
);
4461 vty_out(vty
, "{}\n");
4463 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4466 n
= zvni_neigh_lookup(zvni
, ip
);
4470 "%% Requested neighbor does not exist in VNI %u\n",
4475 json
= json_object_new_object();
4477 zvni_print_neigh(n
, vty
, json
);
4480 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4481 json
, JSON_C_TO_STRING_PRETTY
));
4482 json_object_free(json
);
4487 * Display neighbors for a VNI from specific VTEP (VTY command handler).
4488 * By definition, these are remote neighbors.
4490 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4491 vni_t vni
, struct in_addr vtep_ip
,
4496 struct neigh_walk_ctx wctx
;
4497 json_object
*json
= NULL
;
4499 if (!is_evpn_enabled())
4501 zvni
= zvni_lookup(vni
);
4504 vty_out(vty
, "{}\n");
4506 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4509 num_neigh
= hashcount(zvni
->neigh_table
);
4513 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4516 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
4517 wctx
.r_vtep_ip
= vtep_ip
;
4519 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4522 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4523 json
, JSON_C_TO_STRING_PRETTY
));
4524 json_object_free(json
);
4529 * Display MACs for a VNI (VTY command handler).
4531 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4532 vni_t vni
, uint8_t use_json
)
4536 struct mac_walk_ctx wctx
;
4537 json_object
*json
= NULL
;
4538 json_object
*json_mac
= NULL
;
4540 if (!is_evpn_enabled())
4542 zvni
= zvni_lookup(vni
);
4545 vty_out(vty
, "{}\n");
4547 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4550 num_macs
= num_valid_macs(zvni
);
4555 json
= json_object_new_object();
4556 json_mac
= json_object_new_object();
4559 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4562 wctx
.json
= json_mac
;
4566 "Number of MACs (local and remote) known for this VNI: %u\n",
4568 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
4569 "Intf/Remote VTEP", "VLAN");
4571 json_object_int_add(json
, "numMacs", num_macs
);
4573 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4576 json_object_object_add(json
, "macs", json_mac
);
4577 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4578 json
, JSON_C_TO_STRING_PRETTY
));
4579 json_object_free(json
);
4584 * Display MACs for all VNIs (VTY command handler).
4586 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4589 struct mac_walk_ctx wctx
;
4590 json_object
*json
= NULL
;
4592 if (!is_evpn_enabled()) {
4594 vty_out(vty
, "{}\n");
4598 json
= json_object_new_object();
4600 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4603 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4606 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4607 json
, JSON_C_TO_STRING_PRETTY
));
4608 json_object_free(json
);
4613 * Display MACs for all VNIs (VTY command handler).
4615 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
4616 struct zebra_vrf
*zvrf
,
4617 struct in_addr vtep_ip
,
4620 struct mac_walk_ctx wctx
;
4621 json_object
*json
= NULL
;
4623 if (!is_evpn_enabled())
4627 json
= json_object_new_object();
4629 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4631 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4632 wctx
.r_vtep_ip
= vtep_ip
;
4634 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4637 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4638 json
, JSON_C_TO_STRING_PRETTY
));
4639 json_object_free(json
);
4644 * Display specific MAC for a VNI, if present (VTY command handler).
4646 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4647 vni_t vni
, struct ethaddr
*macaddr
)
4652 if (!is_evpn_enabled())
4654 zvni
= zvni_lookup(vni
);
4656 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4659 mac
= zvni_mac_lookup(zvni
, macaddr
);
4661 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
4666 zvni_print_mac(mac
, vty
);
4670 * Display MACs for a VNI from specific VTEP (VTY command handler).
4672 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4673 vni_t vni
, struct in_addr vtep_ip
,
4678 struct mac_walk_ctx wctx
;
4679 json_object
*json
= NULL
;
4680 json_object
*json_mac
= NULL
;
4682 if (!is_evpn_enabled())
4684 zvni
= zvni_lookup(vni
);
4687 vty_out(vty
, "{}\n");
4689 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4692 num_macs
= num_valid_macs(zvni
);
4697 json
= json_object_new_object();
4698 json_mac
= json_object_new_object();
4701 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4704 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4705 wctx
.r_vtep_ip
= vtep_ip
;
4706 wctx
.json
= json_mac
;
4707 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4710 json_object_int_add(json
, "numMacs", wctx
.count
);
4712 json_object_object_add(json
, "macs", json_mac
);
4713 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4714 json
, JSON_C_TO_STRING_PRETTY
));
4715 json_object_free(json
);
4721 * Display VNI information (VTY command handler).
4723 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
4726 json_object
*json
= NULL
;
4728 zebra_l3vni_t
*zl3vni
= NULL
;
4729 zebra_vni_t
*zvni
= NULL
;
4731 if (!is_evpn_enabled())
4735 json
= json_object_new_object();
4739 zl3vni
= zl3vni_lookup(vni
);
4741 zl3vni_print(zl3vni
, (void *)args
);
4743 zvni
= zvni_lookup(vni
);
4746 vty_out(vty
, "{}\n");
4748 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4752 zvni_print(zvni
, (void *)args
);
4756 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4757 json
, JSON_C_TO_STRING_PRETTY
));
4758 json_object_free(json
);
4762 /* Display all global details for EVPN */
4763 void zebra_vxlan_print_evpn(struct vty
*vty
, uint8_t uj
)
4768 json_object
*json
= NULL
;
4769 struct zebra_ns
*zns
= NULL
;
4770 struct zebra_vrf
*zvrf
= NULL
;
4772 if (!is_evpn_enabled())
4775 zns
= zebra_ns_lookup(NS_DEFAULT
);
4779 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
4783 num_l3vnis
= hashcount(zns
->l3vni_table
);
4784 num_l2vnis
= hashcount(zvrf
->vni_table
);
4785 num_vnis
= num_l2vnis
+ num_l3vnis
;
4788 json
= json_object_new_object();
4789 json_object_string_add(json
, "advertiseGatewayMacip",
4790 zvrf
->advertise_gw_macip
? "Yes" : "No");
4791 json_object_int_add(json
, "numVnis", num_vnis
);
4792 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4793 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4795 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
4796 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
4797 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
4798 zvrf
->advertise_gw_macip
? "Yes" : "No");
4802 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4803 json
, JSON_C_TO_STRING_PRETTY
));
4804 json_object_free(json
);
4809 * Display VNI hash table (VTY command handler).
4811 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4814 json_object
*json
= NULL
;
4815 struct zebra_ns
*zns
= NULL
;
4818 if (!is_evpn_enabled())
4821 zns
= zebra_ns_lookup(NS_DEFAULT
);
4827 json
= json_object_new_object();
4829 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
4830 "Type", "VxLAN IF", "# MACs", "# ARPs",
4831 "# Remote VTEPs", "Tenant VRF");
4836 /* Display all L2-VNIs */
4837 hash_iterate(zvrf
->vni_table
,
4838 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
4841 /* Display all L3-VNIs */
4842 hash_iterate(zns
->l3vni_table
,
4843 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
4847 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4848 json
, JSON_C_TO_STRING_PRETTY
));
4849 json_object_free(json
);
4854 * Handle neighbor delete notification from the kernel (on a VLAN device
4855 * / L3 interface). This may result in either the neighbor getting deleted
4856 * from our database or being re-added to the kernel (if it is a valid
4859 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
4860 struct interface
*link_if
,
4863 char buf
[INET6_ADDRSTRLEN
];
4864 char buf2
[ETHER_ADDR_STRLEN
];
4865 zebra_neigh_t
*n
= NULL
;
4866 zebra_vni_t
*zvni
= NULL
;
4867 zebra_mac_t
*zmac
= NULL
;
4868 zebra_l3vni_t
*zl3vni
= NULL
;
4870 /* check if this is a remote neigh entry corresponding to remote
4873 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4875 return zl3vni_local_nh_del(zl3vni
, ip
);
4877 /* We are only interested in neighbors on an SVI that resides on top
4878 * of a VxLAN bridge.
4880 zvni
= zvni_from_svi(ifp
, link_if
);
4884 if (!zvni
->vxlan_if
) {
4886 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
4891 if (IS_ZEBRA_DEBUG_VXLAN
)
4892 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
4893 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
4894 ifp
->ifindex
, zvni
->vni
);
4896 /* If entry doesn't exist, nothing to do. */
4897 n
= zvni_neigh_lookup(zvni
, ip
);
4901 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
4903 if (IS_ZEBRA_DEBUG_VXLAN
)
4905 "Trying to del a neigh %s without a mac %s on VNI %u",
4906 ipaddr2str(ip
, buf
, sizeof(buf
)),
4907 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
4913 /* If it is a remote entry, the kernel has aged this out or someone has
4914 * deleted it, it needs to be re-installed as Quagga is the owner.
4916 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
4917 zvni_neigh_install(zvni
, n
);
4921 /* Remove neighbor from BGP. */
4922 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
4923 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0);
4925 /* Delete this neighbor entry. */
4926 zvni_neigh_del(zvni
, n
);
4928 /* see if the AUTO mac needs to be deleted */
4929 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
4930 && !listcount(zmac
->neigh_list
))
4931 zvni_mac_del(zvni
, zmac
);
4937 * Handle neighbor add or update notification from the kernel (on a VLAN
4938 * device / L3 interface). This is typically for a local neighbor but can
4939 * also be for a remote neighbor (e.g., ageout notification). It could
4940 * also be a "move" scenario.
4942 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
4943 struct interface
*link_if
,
4945 struct ethaddr
*macaddr
,
4947 uint8_t ext_learned
)
4949 char buf
[ETHER_ADDR_STRLEN
];
4950 char buf2
[INET6_ADDRSTRLEN
];
4951 zebra_vni_t
*zvni
= NULL
;
4952 zebra_l3vni_t
*zl3vni
= NULL
;
4954 /* check if this is a remote neigh entry corresponding to remote
4957 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4959 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
4961 /* We are only interested in neighbors on an SVI that resides on top
4962 * of a VxLAN bridge.
4964 zvni
= zvni_from_svi(ifp
, link_if
);
4968 if (IS_ZEBRA_DEBUG_VXLAN
)
4970 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u",
4971 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
4972 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
4973 ifp
->ifindex
, state
, ext_learned
? "ext-learned " : "",
4976 /* Is this about a local neighbor or a remote one? */
4978 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
);
4980 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
4985 * Handle message from client to delete a remote MACIP for a VNI.
4987 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
4991 struct ethaddr macaddr
;
4993 struct in_addr vtep_ip
;
4997 unsigned short l
= 0, ipa_len
;
4998 char buf
[ETHER_ADDR_STRLEN
];
4999 char buf1
[INET6_ADDRSTRLEN
];
5000 struct interface
*ifp
= NULL
;
5001 struct zebra_if
*zif
= NULL
;
5003 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5004 memset(&ip
, 0, sizeof(struct ipaddr
));
5005 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5009 while (l
< hdr
->length
) {
5010 /* Obtain each remote MACIP and process. */
5011 /* Message contains VNI, followed by MAC followed by IP (if any)
5012 * followed by remote VTEP IP.
5016 memset(&ip
, 0, sizeof(ip
));
5017 STREAM_GETL(s
, vni
);
5018 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5019 STREAM_GETL(s
, ipa_len
);
5021 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5023 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5025 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5026 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5027 l
+= IPV4_MAX_BYTELEN
;
5029 if (IS_ZEBRA_DEBUG_VXLAN
)
5031 "Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
5032 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5033 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5035 zebra_route_string(client
->proto
));
5037 /* Locate VNI hash entry - expected to exist. */
5038 zvni
= zvni_lookup(vni
);
5040 if (IS_ZEBRA_DEBUG_VXLAN
)
5042 "Failed to locate VNI hash upon remote MACIP DEL, "
5047 ifp
= zvni
->vxlan_if
;
5050 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
5056 /* If down or not mapped to a bridge, we're done. */
5057 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5060 /* The remote VTEP specified is normally expected to exist, but
5062 * possible that the peer may delete the VTEP before deleting
5064 * referring to the VTEP, in which case the handler (see
5066 * would have already deleted the MACs.
5068 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5071 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5073 n
= zvni_neigh_lookup(zvni
, &ip
);
5076 zlog_err("Failed to locate MAC %s for neigh %s VNI %u",
5077 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5078 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5082 /* If the remote mac or neighbor doesn't exist there is nothing
5084 * to do. Otherwise, uninstall the entry and then remove it.
5089 /* Ignore the delete if this mac is a gateway mac-ip */
5090 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5091 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5093 "%u: Ignore Del for MAC %s neigh %s on VNI %u as it is configured as a default gateway",
5095 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5096 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5100 /* Uninstall remote neighbor or MAC. */
5102 /* When the MAC changes for an IP, it is possible the
5104 * update the new MAC before trying to delete the "old"
5106 * (as these are two different MACIP routes). Do the
5108 * if the MAC matches.
5110 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5111 && (memcmp(n
->emac
.octet
, macaddr
.octet
, ETH_ALEN
)
5113 zvni_neigh_uninstall(zvni
, n
);
5114 zvni_neigh_del(zvni
, n
);
5115 zvni_deref_ip2mac(zvni
, mac
, 1);
5118 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5119 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5121 if (list_isempty(mac
->neigh_list
)) {
5122 zvni_mac_uninstall(zvni
, mac
, 0);
5123 zvni_mac_del(zvni
, mac
);
5125 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5135 * Handle message from client to add a remote MACIP for a VNI. This
5136 * could be just the add of a MAC address or the add of a neighbor
5139 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
5143 struct ethaddr macaddr
;
5145 struct in_addr vtep_ip
;
5147 zebra_vtep_t
*zvtep
;
5148 zebra_mac_t
*mac
, *old_mac
;
5150 unsigned short l
= 0, ipa_len
;
5151 int update_mac
= 0, update_neigh
= 0;
5152 char buf
[ETHER_ADDR_STRLEN
];
5153 char buf1
[INET6_ADDRSTRLEN
];
5156 struct interface
*ifp
= NULL
;
5157 struct zebra_if
*zif
= NULL
;
5159 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5160 memset(&ip
, 0, sizeof(struct ipaddr
));
5161 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5163 if (!EVPN_ENABLED(zvrf
)) {
5165 "%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
5166 __PRETTY_FUNCTION__
);
5172 while (l
< hdr
->length
) {
5173 /* Obtain each remote MACIP and process. */
5174 /* Message contains VNI, followed by MAC followed by IP (if any)
5175 * followed by remote VTEP IP.
5177 update_mac
= update_neigh
= 0;
5180 memset(&ip
, 0, sizeof(ip
));
5181 STREAM_GETL(s
, vni
);
5182 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5183 STREAM_GETL(s
, ipa_len
);
5185 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5187 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5189 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5190 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5191 l
+= IPV4_MAX_BYTELEN
;
5193 /* Get flags - sticky mac and/or gateway mac */
5194 STREAM_GETC(s
, flags
);
5195 sticky
= CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5198 if (IS_ZEBRA_DEBUG_VXLAN
)
5200 "Recv MACIP Add MAC %s IP %s VNI %u Remote VTEP %s with flags 0x%x from %s",
5201 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5202 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5203 inet_ntoa(vtep_ip
), flags
,
5204 zebra_route_string(client
->proto
));
5206 /* Locate VNI hash entry - expected to exist. */
5207 zvni
= zvni_lookup(vni
);
5210 "Failed to locate VNI hash upon remote MACIP ADD, VNI %u",
5214 ifp
= zvni
->vxlan_if
;
5217 "VNI %u hash %p doesn't have intf upon remote MACIP add",
5223 /* If down or not mapped to a bridge, we're done. */
5224 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5227 /* The remote VTEP specified should normally exist, but it is
5229 * that when peering comes up, peer may advertise MACIP routes
5231 * advertising type-3 routes.
5233 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5235 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5237 "Failed to add remote VTEP, VNI %u zvni %p",
5242 zvni_vtep_install(zvni
, &vtep_ip
);
5245 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5247 /* Ignore the update if the mac is already present
5249 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)
5250 && CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5251 if (IS_ZEBRA_DEBUG_VXLAN
)
5253 "%u:Ignore MAC %s IP %s on VNI %u as MAC is already configured as gateway mac",
5255 prefix_mac2str(&macaddr
, buf
,
5257 ipaddr2str(&ip
, buf1
, sizeof(buf1
)),
5262 /* check if the remote MAC is unknown or has a change.
5263 * If so, that needs to be updated first. Note that client could
5264 * install MAC and MACIP separately or just install the latter.
5266 if (!mac
|| !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5267 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0)
5269 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
))
5274 mac
= zvni_mac_add(zvni
, &macaddr
);
5277 "Failed to add MAC %s VNI %u Remote VTEP %s",
5278 prefix_mac2str(&macaddr
, buf
,
5280 vni
, inet_ntoa(vtep_ip
));
5284 /* Is this MAC created for a MACIP? */
5286 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5289 /* Set "auto" and "remote" forwarding info. */
5290 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5291 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5292 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5293 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5296 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5298 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5300 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5302 /* Install the entry. */
5303 zvni_mac_install(zvni
, mac
);
5306 /* If there is no IP, continue - after clearing AUTO flag of
5309 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5313 /* Check if the remote neighbor itself is unknown or has a
5315 * If so, create or update and then install the entry.
5317 n
= zvni_neigh_lookup(zvni
, &ip
);
5318 if (!n
|| !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5319 || (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
)) != 0)
5320 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
))
5325 n
= zvni_neigh_add(zvni
, &ip
, &macaddr
);
5328 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5329 ipaddr2str(&ip
, buf1
,
5331 prefix_mac2str(&macaddr
, buf
,
5333 vni
, inet_ntoa(vtep_ip
));
5337 } else if (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
))
5339 /* MAC change, update neigh list for old and new
5341 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5343 listnode_delete(old_mac
->neigh_list
, n
);
5344 zvni_deref_ip2mac(zvni
, old_mac
, 1);
5346 listnode_add_sort(mac
->neigh_list
, n
);
5347 memcpy(&n
->emac
, &macaddr
, ETH_ALEN
);
5350 /* Set "remote" forwarding info. */
5351 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5352 /* TODO: Handle MAC change. */
5353 n
->r_vtep_ip
= vtep_ip
;
5354 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5356 /* Install the entry. */
5357 zvni_neigh_install(zvni
, n
);
5366 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5367 * us, this must involve a multihoming scenario. Treat this as implicit delete
5368 * of any prior local MAC.
5370 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
5371 struct interface
*br_if
,
5372 struct ethaddr
*macaddr
, vlanid_t vid
)
5374 struct zebra_if
*zif
;
5375 struct zebra_l2info_vxlan
*vxl
;
5379 char buf
[ETHER_ADDR_STRLEN
];
5383 vxl
= &zif
->l2info
.vxl
;
5386 /* Check if EVPN is enabled. */
5387 if (!is_evpn_enabled())
5390 /* Locate hash entry; it is expected to exist. */
5391 zvni
= zvni_lookup(vni
);
5395 /* If entry doesn't exist, nothing to do. */
5396 mac
= zvni_mac_lookup(zvni
, macaddr
);
5400 /* Is it a local entry? */
5401 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5404 if (IS_ZEBRA_DEBUG_VXLAN
)
5406 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5407 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5410 /* Remove MAC from BGP. */
5411 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5414 * If there are no neigh associated with the mac delete the mac
5415 * else mark it as AUTO for forward reference
5417 if (!listcount(mac
->neigh_list
)) {
5418 zvni_mac_del(zvni
, mac
);
5420 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5421 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5428 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5429 * This can happen because the remote MAC entries are also added as "dynamic",
5430 * so the kernel can ageout the entry.
5432 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
5433 struct interface
*br_if
,
5434 struct ethaddr
*macaddr
, vlanid_t vid
)
5436 struct zebra_if
*zif
= NULL
;
5437 struct zebra_l2info_vxlan
*vxl
= NULL
;
5439 zebra_vni_t
*zvni
= NULL
;
5440 zebra_l3vni_t
*zl3vni
= NULL
;
5441 zebra_mac_t
*mac
= NULL
;
5442 char buf
[ETHER_ADDR_STRLEN
];
5446 vxl
= &zif
->l2info
.vxl
;
5449 /* Check if EVPN is enabled. */
5450 if (!is_evpn_enabled())
5453 /* check if this is a remote RMAC and readd simillar to remote macs */
5454 zl3vni
= zl3vni_lookup(vni
);
5456 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
5458 /* Locate hash entry; it is expected to exist. */
5459 zvni
= zvni_lookup(vni
);
5463 /* If entry doesn't exist, nothing to do. */
5464 mac
= zvni_mac_lookup(zvni
, macaddr
);
5468 /* Is it a remote entry? */
5469 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
5472 if (IS_ZEBRA_DEBUG_VXLAN
)
5473 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
5474 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5477 zvni_mac_install(zvni
, mac
);
5482 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
5484 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
5485 struct ethaddr
*macaddr
, vlanid_t vid
)
5489 char buf
[ETHER_ADDR_STRLEN
];
5491 /* We are interested in MACs only on ports or (port, VLAN) that
5494 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5497 if (!zvni
->vxlan_if
) {
5498 zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL",
5503 if (IS_ZEBRA_DEBUG_VXLAN
)
5504 zlog_debug("Del MAC %s intf %s(%u) VID %u -> VNI %u",
5505 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5506 ifp
->ifindex
, vid
, zvni
->vni
);
5508 /* If entry doesn't exist, nothing to do. */
5509 mac
= zvni_mac_lookup(zvni
, macaddr
);
5513 /* Is it a local entry? */
5514 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5517 /* Remove MAC from BGP. */
5518 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5520 /* Update all the neigh entries associated with this mac */
5521 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
5524 * If there are no neigh associated with the mac delete the mac
5525 * else mark it as AUTO for forward reference
5527 if (!listcount(mac
->neigh_list
)) {
5528 zvni_mac_del(zvni
, mac
);
5530 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5531 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5538 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
5540 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
5541 struct interface
*br_if
,
5542 struct ethaddr
*macaddr
, vlanid_t vid
,
5547 char buf
[ETHER_ADDR_STRLEN
];
5551 /* We are interested in MACs only on ports or (port, VLAN) that
5554 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5556 if (IS_ZEBRA_DEBUG_VXLAN
)
5558 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5559 sticky
? "sticky " : "",
5560 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5561 ifp
->name
, ifp
->ifindex
, vid
);
5565 if (!zvni
->vxlan_if
) {
5566 zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD",
5571 if (IS_ZEBRA_DEBUG_VXLAN
)
5572 zlog_debug("Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
5573 sticky
? "sticky " : "",
5574 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5575 ifp
->ifindex
, vid
, zvni
->vni
);
5577 /* If same entry already exists, nothing to do. */
5578 mac
= zvni_mac_lookup(zvni
, macaddr
);
5580 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5581 mac_sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5587 * return if nothing has changed.
5588 * inform bgp if sticky flag has changed
5589 * update locally and do not inform bgp if local
5590 * parameters like interface has changed
5592 if (mac_sticky
== sticky
5593 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
5594 && mac
->fwd_info
.local
.vid
== vid
) {
5595 if (IS_ZEBRA_DEBUG_VXLAN
)
5597 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
5598 "entry exists and has not changed ",
5599 sticky
? "sticky " : "",
5600 prefix_mac2str(macaddr
, buf
,
5602 ifp
->name
, ifp
->ifindex
, vid
,
5605 } else if (mac_sticky
!= sticky
) {
5608 add
= 0; /* This is an update of local
5611 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5613 * If we have already learned the MAC as a remote sticky
5615 * this is a operator error and we must log a warning
5617 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
5619 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
5620 prefix_mac2str(macaddr
, buf
,
5622 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
5630 mac
= zvni_mac_add(zvni
, macaddr
);
5632 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
5633 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5634 ifp
->name
, ifp
->ifindex
, vid
);
5639 /* Set "local" forwarding info. */
5640 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5641 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5642 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5643 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5644 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
5645 mac
->fwd_info
.local
.vid
= vid
;
5648 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5650 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5652 /* Inform BGP if required. */
5654 zvni_process_neigh_on_local_mac_add(zvni
, mac
);
5655 return zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
5663 * Handle message from client to delete a remote VTEP for a VNI.
5665 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
5668 unsigned short l
= 0;
5670 struct in_addr vtep_ip
;
5672 zebra_vtep_t
*zvtep
;
5673 struct interface
*ifp
;
5674 struct zebra_if
*zif
;
5676 if (!is_evpn_enabled()) {
5678 "%s: EVPN is not enabled yet we have received a vtep del command",
5679 __PRETTY_FUNCTION__
);
5683 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5684 zlog_err("Recv MACIP DEL for non-default VRF %u",
5691 while (l
< hdr
->length
) {
5692 /* Obtain each remote VTEP and process. */
5693 STREAM_GETL(s
, vni
);
5695 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5696 l
+= IPV4_MAX_BYTELEN
;
5698 if (IS_ZEBRA_DEBUG_VXLAN
)
5699 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
5700 inet_ntoa(vtep_ip
), vni
,
5701 zebra_route_string(client
->proto
));
5703 /* Locate VNI hash entry - expected to exist. */
5704 zvni
= zvni_lookup(vni
);
5706 if (IS_ZEBRA_DEBUG_VXLAN
)
5708 "Failed to locate VNI hash upon remote VTEP DEL, "
5714 ifp
= zvni
->vxlan_if
;
5717 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
5723 /* If down or not mapped to a bridge, we're done. */
5724 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5727 /* If the remote VTEP does not exist, there's nothing more to
5729 * Otherwise, uninstall any remote MACs pointing to this VTEP
5731 * then, the VTEP entry itself and remove it.
5733 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5737 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
5738 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
5739 zvni_vtep_uninstall(zvni
, &vtep_ip
);
5740 zvni_vtep_del(zvni
, zvtep
);
5748 * Handle message from client to add a remote VTEP for a VNI.
5750 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
5753 unsigned short l
= 0;
5755 struct in_addr vtep_ip
;
5757 struct interface
*ifp
;
5758 struct zebra_if
*zif
;
5760 if (!is_evpn_enabled()) {
5762 "%s: EVPN not enabled yet we received a vtep_add zapi call",
5763 __PRETTY_FUNCTION__
);
5767 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5768 zlog_err("Recv MACIP ADD for non-default VRF %u",
5775 while (l
< hdr
->length
) {
5776 /* Obtain each remote VTEP and process. */
5777 STREAM_GETL(s
, vni
);
5779 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5780 l
+= IPV4_MAX_BYTELEN
;
5782 if (IS_ZEBRA_DEBUG_VXLAN
)
5783 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
5784 inet_ntoa(vtep_ip
), vni
,
5785 zebra_route_string(client
->proto
));
5787 /* Locate VNI hash entry - expected to exist. */
5788 zvni
= zvni_lookup(vni
);
5791 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
5796 ifp
= zvni
->vxlan_if
;
5799 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
5806 /* If down or not mapped to a bridge, we're done. */
5807 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5810 /* If the remote VTEP already exists,
5811 there's nothing more to do. */
5812 if (zvni_vtep_find(zvni
, &vtep_ip
))
5815 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5816 zlog_err("Failed to add remote VTEP, VNI %u zvni %p",
5821 zvni_vtep_install(zvni
, &vtep_ip
);
5829 * Add/Del gateway macip to evpn
5831 * 1. SVI interface on a vlan aware bridge
5832 * 2. SVI interface on a vlan unaware bridge
5833 * 3. vrr interface (MACVLAN) associated to a SVI
5834 * We advertise macip routes for an interface if it is associated to VxLan vlan
5836 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
5840 struct ethaddr macaddr
;
5841 zebra_vni_t
*zvni
= NULL
;
5843 memset(&ip
, 0, sizeof(struct ipaddr
));
5844 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5846 /* Check if EVPN is enabled. */
5847 if (!is_evpn_enabled())
5850 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
5851 struct interface
*svi_if
=
5852 NULL
; /* SVI corresponding to the MACVLAN */
5853 struct zebra_if
*ifp_zif
=
5854 NULL
; /* Zebra daemon specific info for MACVLAN */
5855 struct zebra_if
*svi_if_zif
=
5856 NULL
; /* Zebra daemon specific info for SVI*/
5858 ifp_zif
= ifp
->info
;
5863 * for a MACVLAN interface the link represents the svi_if
5865 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
5866 ifp_zif
->link_ifindex
);
5868 zlog_err("MACVLAN %s(%u) without link information",
5869 ifp
->name
, ifp
->ifindex
);
5873 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
5875 * If it is a vlan aware bridge then the link gives the
5876 * bridge information
5878 struct interface
*svi_if_link
= NULL
;
5880 svi_if_zif
= svi_if
->info
;
5882 svi_if_link
= if_lookup_by_index_per_ns(
5883 zebra_ns_lookup(NS_DEFAULT
),
5884 svi_if_zif
->link_ifindex
);
5885 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
5887 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
5889 * If it is a vlan unaware bridge then svi is the bridge
5892 zvni
= zvni_from_svi(svi_if
, svi_if
);
5894 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
5895 struct zebra_if
*svi_if_zif
=
5896 NULL
; /* Zebra daemon specific info for SVI */
5897 struct interface
*svi_if_link
=
5898 NULL
; /* link info for the SVI = bridge info */
5900 svi_if_zif
= ifp
->info
;
5902 svi_if_link
= if_lookup_by_index_per_ns(
5903 zebra_ns_lookup(NS_DEFAULT
),
5904 svi_if_zif
->link_ifindex
);
5906 zvni
= zvni_from_svi(ifp
, svi_if_link
);
5908 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
5909 zvni
= zvni_from_svi(ifp
, ifp
);
5915 if (!zvni
->vxlan_if
) {
5916 zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
5922 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
5924 if (p
->family
== AF_INET
) {
5925 ip
.ipa_type
= IPADDR_V4
;
5926 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
5927 sizeof(struct in_addr
));
5928 } else if (p
->family
== AF_INET6
) {
5929 ip
.ipa_type
= IPADDR_V6
;
5930 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
5931 sizeof(struct in6_addr
));
5936 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
5938 zvni_gw_macip_del(ifp
, zvni
, &ip
);
5944 * Handle SVI interface going down.
5945 * SVI can be associated to either L3-VNI or L2-VNI.
5946 * For L2-VNI: At this point, this is a NOP since
5947 * the kernel deletes the neighbor entries on this SVI (if any).
5948 * We only need to update the vrf corresponding to zvni.
5949 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
5952 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
5954 zebra_l3vni_t
*zl3vni
= NULL
;
5956 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5959 /* process l3-vni down */
5960 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
5962 /* remove association with svi-if */
5963 zl3vni
->svi_if
= NULL
;
5965 zebra_vni_t
*zvni
= NULL
;
5967 /* since we dont have svi corresponding to zvni, we associate it
5968 * to default vrf. Note: the corresponding neigh entries on the
5969 * SVI would have already been deleted */
5970 zvni
= zvni_from_svi(ifp
, link_if
);
5972 zvni
->vrf_id
= VRF_DEFAULT
;
5974 /* update the tenant vrf in BGP */
5975 zvni_send_add_to_client(zvni
);
5982 * Handle SVI interface coming up.
5983 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
5985 * For L2-VNI: we need to install any remote neighbors entried (used for
5987 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
5989 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
5991 zebra_vni_t
*zvni
= NULL
;
5992 zebra_l3vni_t
*zl3vni
= NULL
;
5994 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5997 /* associate with svi */
5998 zl3vni
->svi_if
= ifp
;
6000 /* process oper-up */
6001 if (is_l3vni_oper_up(zl3vni
))
6002 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6005 /* process SVI up for l2-vni */
6006 struct neigh_walk_ctx n_wctx
;
6008 zvni
= zvni_from_svi(ifp
, link_if
);
6012 if (!zvni
->vxlan_if
) {
6013 zlog_err("VNI %u hash %p doesn't have intf upon SVI up",
6018 if (IS_ZEBRA_DEBUG_VXLAN
)
6020 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
6021 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
6022 vrf_id_to_name(ifp
->vrf_id
));
6024 /* update the vrf information for l2-vni and inform bgp */
6025 zvni
->vrf_id
= ifp
->vrf_id
;
6026 zvni_send_add_to_client(zvni
);
6028 /* Install any remote neighbors for this VNI. */
6029 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6031 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6039 * Handle VxLAN interface down
6041 int zebra_vxlan_if_down(struct interface
*ifp
)
6044 struct zebra_if
*zif
= NULL
;
6045 struct zebra_l2info_vxlan
*vxl
= NULL
;
6046 zebra_l3vni_t
*zl3vni
= NULL
;
6049 /* Check if EVPN is enabled. */
6050 if (!is_evpn_enabled())
6055 vxl
= &zif
->l2info
.vxl
;
6058 zl3vni
= zl3vni_lookup(vni
);
6060 /* process-if-down for l3-vni */
6061 if (IS_ZEBRA_DEBUG_VXLAN
)
6062 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
6065 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6067 /* process if-down for l2-vni */
6068 if (IS_ZEBRA_DEBUG_VXLAN
)
6069 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
6072 /* Locate hash entry; it is expected to exist. */
6073 zvni
= zvni_lookup(vni
);
6076 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
6077 ifp
->name
, ifp
->ifindex
, vni
);
6081 assert(zvni
->vxlan_if
== ifp
);
6083 /* Delete this VNI from BGP. */
6084 zvni_send_del_to_client(zvni
->vni
);
6086 /* Free up all neighbors and MACs, if any. */
6087 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6088 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6090 /* Free up all remote VTEPs, if any. */
6091 zvni_vtep_del_all(zvni
, 1);
6097 * Handle VxLAN interface up - update BGP if required.
6099 int zebra_vxlan_if_up(struct interface
*ifp
)
6102 struct zebra_if
*zif
= NULL
;
6103 struct zebra_l2info_vxlan
*vxl
= NULL
;
6104 zebra_vni_t
*zvni
= NULL
;
6105 zebra_l3vni_t
*zl3vni
= NULL
;
6107 /* Check if EVPN is enabled. */
6108 if (!is_evpn_enabled())
6113 vxl
= &zif
->l2info
.vxl
;
6116 zl3vni
= zl3vni_lookup(vni
);
6119 if (IS_ZEBRA_DEBUG_VXLAN
)
6120 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
6123 /* we need to associate with SVI, if any, we can associate with
6124 * svi-if only after association with vxlan-intf is complete
6126 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6128 if (is_l3vni_oper_up(zl3vni
))
6129 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6131 /* Handle L2-VNI add */
6132 struct interface
*vlan_if
= NULL
;
6134 if (IS_ZEBRA_DEBUG_VXLAN
)
6135 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
6138 /* Locate hash entry; it is expected to exist. */
6139 zvni
= zvni_lookup(vni
);
6142 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
6143 ifp
->name
, ifp
->ifindex
, vni
);
6147 assert(zvni
->vxlan_if
== ifp
);
6148 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6149 zif
->brslave_info
.br_if
);
6151 zvni
->vrf_id
= vlan_if
->vrf_id
;
6152 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6154 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6157 /* If part of a bridge, inform BGP about this VNI. */
6158 /* Also, read and populate local MACs and neighbors. */
6159 if (zif
->brslave_info
.br_if
) {
6160 zvni_send_add_to_client(zvni
);
6161 zvni_read_mac_neigh(zvni
, ifp
);
6169 * Handle VxLAN interface delete. Locate and remove entry in hash table
6170 * and update BGP, if required.
6172 int zebra_vxlan_if_del(struct interface
*ifp
)
6175 struct zebra_if
*zif
= NULL
;
6176 struct zebra_l2info_vxlan
*vxl
= NULL
;
6177 zebra_vni_t
*zvni
= NULL
;
6178 zebra_l3vni_t
*zl3vni
= NULL
;
6180 /* Check if EVPN is enabled. */
6181 if (!is_evpn_enabled())
6186 vxl
= &zif
->l2info
.vxl
;
6189 zl3vni
= zl3vni_lookup(vni
);
6192 if (IS_ZEBRA_DEBUG_VXLAN
)
6193 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
6196 /* process oper-down for l3-vni */
6197 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6199 /* remove the association with vxlan_if */
6200 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
6201 zl3vni
->vxlan_if
= NULL
;
6204 /* process if-del for l2-vni*/
6205 if (IS_ZEBRA_DEBUG_VXLAN
)
6206 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
6209 /* Locate hash entry; it is expected to exist. */
6210 zvni
= zvni_lookup(vni
);
6213 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6214 ifp
->name
, ifp
->ifindex
, vni
);
6218 /* remove from l3-vni list */
6219 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
6221 listnode_delete(zl3vni
->l2vnis
, zvni
);
6223 /* Delete VNI from BGP. */
6224 zvni_send_del_to_client(zvni
->vni
);
6226 /* Free up all neighbors and MAC, if any. */
6227 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
6228 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
6230 /* Free up all remote VTEPs, if any. */
6231 zvni_vtep_del_all(zvni
, 0);
6233 /* Delete the hash entry. */
6234 if (zvni_del(zvni
)) {
6235 zlog_err("Failed to del VNI hash %p, IF %s(%u) VNI %u",
6236 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
6244 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6246 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
6249 struct zebra_if
*zif
= NULL
;
6250 struct zebra_l2info_vxlan
*vxl
= NULL
;
6251 zebra_vni_t
*zvni
= NULL
;
6252 zebra_l3vni_t
*zl3vni
= NULL
;
6254 /* Check if EVPN is enabled. */
6255 if (!is_evpn_enabled())
6260 vxl
= &zif
->l2info
.vxl
;
6263 zl3vni
= zl3vni_lookup(vni
);
6266 if (IS_ZEBRA_DEBUG_VXLAN
)
6268 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6269 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6270 inet_ntoa(vxl
->vtep_ip
),
6271 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6273 /* Removed from bridge? Cleanup and return */
6274 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6275 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6276 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6280 /* access-vlan change - process oper down, associate with new
6281 * svi_if and then process oper up again
6283 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6284 if (if_is_operative(ifp
)) {
6285 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6286 zl3vni
->svi_if
= NULL
;
6287 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6288 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6289 if (is_l3vni_oper_up(zl3vni
))
6290 zebra_vxlan_process_l3vni_oper_up(
6296 * local-ip change - process oper down, associate with new
6297 * local-ip and then process oper up again
6299 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
6300 if (if_is_operative(ifp
)) {
6301 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6302 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6303 if (is_l3vni_oper_up(zl3vni
))
6304 zebra_vxlan_process_l3vni_oper_up(
6309 /* Update local tunnel IP. */
6310 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6312 /* if we have a valid new master, process l3-vni oper up */
6313 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
6314 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
6315 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6319 /* Update VNI hash. */
6320 zvni
= zvni_lookup(vni
);
6323 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6324 ifp
->name
, ifp
->ifindex
, vni
);
6328 if (IS_ZEBRA_DEBUG_VXLAN
)
6330 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6331 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6332 inet_ntoa(vxl
->vtep_ip
),
6333 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6335 /* Removed from bridge? Cleanup and return */
6336 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6337 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6338 /* Delete from client, remove all remote VTEPs */
6339 /* Also, free up all MACs and neighbors. */
6340 zvni_send_del_to_client(zvni
->vni
);
6341 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6342 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6343 zvni_vtep_del_all(zvni
, 1);
6347 /* Handle other changes. */
6348 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6349 /* Remove all existing local neigh and MACs for this VNI
6350 * (including from BGP)
6352 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6353 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6356 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6357 zvni
->vxlan_if
= ifp
;
6359 /* Take further actions needed.
6360 * Note that if we are here, there is a change of interest.
6362 /* If down or not mapped to a bridge, we're done. */
6363 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6366 /* Inform BGP, if there is a change of interest. */
6368 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
6369 zvni_send_add_to_client(zvni
);
6371 /* If there is a valid new master or a VLAN mapping change,
6372 * read and populate local MACs and neighbors.
6373 * Also, reinstall any remote MACs and neighbors
6374 * for this VNI (based on new VLAN).
6376 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6377 zvni_read_mac_neigh(zvni
, ifp
);
6378 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6379 struct mac_walk_ctx m_wctx
;
6380 struct neigh_walk_ctx n_wctx
;
6382 zvni_read_mac_neigh(zvni
, ifp
);
6384 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6386 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
6389 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6391 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6400 * Handle VxLAN interface add.
6402 int zebra_vxlan_if_add(struct interface
*ifp
)
6405 struct zebra_if
*zif
= NULL
;
6406 struct zebra_l2info_vxlan
*vxl
= NULL
;
6407 zebra_vni_t
*zvni
= NULL
;
6408 zebra_l3vni_t
*zl3vni
= NULL
;
6410 /* Check if EVPN is enabled. */
6411 if (!is_evpn_enabled())
6416 vxl
= &zif
->l2info
.vxl
;
6419 zl3vni
= zl3vni_lookup(vni
);
6422 /* process if-add for l3-vni*/
6423 if (IS_ZEBRA_DEBUG_VXLAN
)
6425 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6426 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6427 inet_ntoa(vxl
->vtep_ip
),
6428 zif
->brslave_info
.bridge_ifindex
);
6430 /* associate with vxlan_if */
6431 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6432 zl3vni
->vxlan_if
= ifp
;
6434 /* Associate with SVI, if any. We can associate with svi-if only
6435 * after association with vxlan_if is complete */
6436 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6438 if (is_l3vni_oper_up(zl3vni
))
6439 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6442 /* process if-add for l2-vni */
6443 struct interface
*vlan_if
= NULL
;
6445 /* Create or update VNI hash. */
6446 zvni
= zvni_lookup(vni
);
6448 zvni
= zvni_add(vni
);
6451 "Failed to add VNI hash, IF %s(%u) VNI %u",
6452 ifp
->name
, ifp
->ifindex
, vni
);
6457 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6458 zvni
->vxlan_if
= ifp
;
6459 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6460 zif
->brslave_info
.br_if
);
6462 zvni
->vrf_id
= vlan_if
->vrf_id
;
6463 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6465 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6468 if (IS_ZEBRA_DEBUG_VXLAN
)
6470 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6472 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
6474 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6475 inet_ntoa(vxl
->vtep_ip
),
6476 zif
->brslave_info
.bridge_ifindex
);
6478 /* If down or not mapped to a bridge, we're done. */
6479 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6483 zvni_send_add_to_client(zvni
);
6485 /* Read and populate local MACs and neighbors */
6486 zvni_read_mac_neigh(zvni
, ifp
);
6492 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
6493 char *err
, int err_str_sz
, int filter
,
6496 zebra_l3vni_t
*zl3vni
= NULL
;
6497 struct zebra_vrf
*zvrf_default
= NULL
;
6499 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
6503 if (IS_ZEBRA_DEBUG_VXLAN
)
6504 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
6505 add
? "ADD" : "DEL");
6509 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6511 /* check if the vni is already present under zvrf */
6513 snprintf(err
, err_str_sz
,
6514 "VNI is already configured under the vrf");
6518 /* check if this VNI is already present in the system */
6519 zl3vni
= zl3vni_lookup(vni
);
6521 snprintf(err
, err_str_sz
,
6522 "VNI is already configured as L3-VNI");
6526 /* add the L3-VNI to the global table */
6527 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
6529 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
6533 /* associate the vrf with vni */
6536 /* set the filter in l3vni to denote if we are using l3vni only
6540 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
6542 /* associate with vxlan-intf;
6543 * we need to associate with the vxlan-intf first
6545 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
6547 /* associate with corresponding SVI interface, we can associate
6548 * with svi-if only after vxlan interface association is
6551 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6553 /* formulate l2vni list */
6554 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
6557 if (is_l3vni_oper_up(zl3vni
))
6558 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6561 zl3vni
= zl3vni_lookup(vni
);
6563 snprintf(err
, err_str_sz
, "VNI doesn't exist");
6567 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
6568 snprintf(err
, ERR_STR_SZ
,
6569 "prefix-routes-only is not set for the vni");
6573 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6575 /* delete and uninstall all rmacs */
6576 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
6579 /* delete and uninstall all next-hops */
6580 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
6586 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6591 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
6593 zebra_l3vni_t
*zl3vni
= NULL
;
6596 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6600 zl3vni
->vrf_id
= zvrf_id(zvrf
);
6601 if (is_l3vni_oper_up(zl3vni
))
6602 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6606 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
6608 zebra_l3vni_t
*zl3vni
= NULL
;
6611 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6615 zl3vni
->vrf_id
= VRF_UNKNOWN
;
6616 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6620 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
6622 zebra_l3vni_t
*zl3vni
= NULL
;
6626 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6632 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
6638 * Handle message from client to enable/disable advertisement of g/w macip
6641 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
6646 zebra_vni_t
*zvni
= NULL
;
6647 struct interface
*ifp
= NULL
;
6648 struct zebra_if
*zif
= NULL
;
6649 struct zebra_l2info_vxlan zl2_info
;
6650 struct interface
*vlan_if
= NULL
;
6652 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6653 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6659 STREAM_GETC(s
, advertise
);
6660 vni
= stream_get3(s
);
6662 zvni
= zvni_lookup(vni
);
6666 if (zvni
->advertise_subnet
== advertise
)
6669 if (IS_ZEBRA_DEBUG_VXLAN
)
6670 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
6671 advertise
? "enabled" : "disabled", vni
,
6672 zvni
->advertise_subnet
? "enabled" : "disabled");
6675 zvni
->advertise_subnet
= advertise
;
6677 ifp
= zvni
->vxlan_if
;
6683 /* If down or not mapped to a bridge, we're done. */
6684 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6687 zl2_info
= zif
->l2info
.vxl
;
6690 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
6694 if (zvni
->advertise_subnet
)
6695 zvni_advertise_subnet(zvni
, vlan_if
, 1);
6697 zvni_advertise_subnet(zvni
, vlan_if
, 0);
6704 * Handle message from client to enable/disable advertisement of g/w macip
6707 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
6712 zebra_vni_t
*zvni
= NULL
;
6713 struct interface
*ifp
= NULL
;
6715 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6716 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6722 STREAM_GETC(s
, advertise
);
6723 STREAM_GETL(s
, vni
);
6726 if (IS_ZEBRA_DEBUG_VXLAN
)
6727 zlog_debug("EVPN gateway macip Adv %s, currently %s",
6728 advertise
? "enabled" : "disabled",
6729 advertise_gw_macip_enabled(NULL
)
6733 if (zvrf
->advertise_gw_macip
== advertise
)
6736 zvrf
->advertise_gw_macip
= advertise
;
6738 if (advertise_gw_macip_enabled(zvni
))
6739 hash_iterate(zvrf
->vni_table
,
6740 zvni_gw_macip_add_for_vni_hash
, NULL
);
6742 hash_iterate(zvrf
->vni_table
,
6743 zvni_gw_macip_del_for_vni_hash
, NULL
);
6746 struct zebra_if
*zif
= NULL
;
6747 struct zebra_l2info_vxlan zl2_info
;
6748 struct interface
*vlan_if
= NULL
;
6749 struct interface
*vrr_if
= NULL
;
6751 zvni
= zvni_lookup(vni
);
6755 if (IS_ZEBRA_DEBUG_VXLAN
)
6757 "EVPN gateway macip Adv %s on VNI %d , currently %s",
6758 advertise
? "enabled" : "disabled", vni
,
6759 advertise_gw_macip_enabled(zvni
) ? "enabled"
6762 if (zvni
->advertise_gw_macip
== advertise
)
6765 zvni
->advertise_gw_macip
= advertise
;
6767 ifp
= zvni
->vxlan_if
;
6773 /* If down or not mapped to a bridge, we're done. */
6774 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6777 zl2_info
= zif
->l2info
.vxl
;
6779 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
6780 zif
->brslave_info
.br_if
);
6784 if (advertise_gw_macip_enabled(zvni
)) {
6785 /* Add primary SVI MAC-IP */
6786 zvni_add_macip_for_intf(vlan_if
, zvni
);
6788 /* Add VRR MAC-IP - if any*/
6789 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6791 zvni_add_macip_for_intf(vrr_if
, zvni
);
6793 /* Del primary MAC-IP */
6794 zvni_del_macip_for_intf(vlan_if
, zvni
);
6796 /* Del VRR MAC-IP - if any*/
6797 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6799 zvni_del_macip_for_intf(vrr_if
, zvni
);
6809 * Handle message from client to learn (or stop learning) about VNIs and MACs.
6810 * When enabled, the VNI hash table will be built and MAC FDB table read;
6811 * when disabled, the entries should be deleted and remote VTEPs and MACs
6812 * uninstalled from the kernel.
6814 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
6816 struct stream
*s
= NULL
;
6818 struct zebra_ns
*zns
= NULL
;
6820 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6821 zlog_err("EVPN VNI Adv for non-default VRF %u", zvrf_id(zvrf
));
6826 STREAM_GETC(s
, advertise
);
6828 if (IS_ZEBRA_DEBUG_VXLAN
)
6829 zlog_debug("EVPN VNI Adv %s, currently %s",
6830 advertise
? "enabled" : "disabled",
6831 is_evpn_enabled() ? "enabled" : "disabled");
6833 if (zvrf
->advertise_all_vni
== advertise
)
6836 zvrf
->advertise_all_vni
= advertise
;
6837 if (is_evpn_enabled()) {
6838 /* Build VNI hash table and inform BGP. */
6839 zvni_build_hash_table();
6841 /* Add all SVI (L3 GW) MACs to BGP*/
6842 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
6845 /* Read the MAC FDB */
6846 macfdb_read(zvrf
->zns
);
6848 /* Read neighbors */
6849 neigh_read(zvrf
->zns
);
6851 /* Cleanup VTEPs for all VNIs - uninstall from
6852 * kernel and free entries.
6854 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6856 /* cleanup all l3vnis */
6857 zns
= zebra_ns_lookup(NS_DEFAULT
);
6861 hash_iterate(zns
->l3vni_table
, zl3vni_cleanup_all
, NULL
);
6869 * Allocate VNI hash table for this VRF and do other initialization.
6870 * NOTE: Currently supported only for default VRF.
6872 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
6876 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
6877 "Zebra VRF VNI Table");
6880 /* Cleanup VNI info, but don't free the table. */
6881 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
6885 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6888 /* Close all VNI handling */
6889 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
6893 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6894 hash_free(zvrf
->vni_table
);
6897 /* init the l3vni table */
6898 void zebra_vxlan_ns_init(struct zebra_ns
*zns
)
6900 zns
->l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
6901 "Zebra VRF L3 VNI table");
6904 /* free l3vni table */
6905 void zebra_vxlan_ns_disable(struct zebra_ns
*zns
)
6907 hash_free(zns
->l3vni_table
);
6910 /* get the l3vni svi ifindex */
6911 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
6913 zebra_l3vni_t
*zl3vni
= NULL
;
6915 zl3vni
= zl3vni_from_vrf(vrf_id
);
6916 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
6919 return zl3vni
->svi_if
->ifindex
;