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");
60 /* static function declarations */
61 static int ip_prefix_send_to_client(vrf_id_t vrf_id
,
64 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
65 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
);
66 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
68 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
70 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
72 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
);
73 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
);
74 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
);
75 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
76 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[]);
78 static int zvni_macip_send_msg_to_client(vni_t vni
,
79 struct ethaddr
*macaddr
,
80 struct ipaddr
*ip
, u_char flags
,
82 static unsigned int neigh_hash_keymake(void *p
);
83 static int neigh_cmp(const void *p1
, const void *p2
);
84 static void *zvni_neigh_alloc(void *p
);
85 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
87 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
88 static int zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
);
89 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
90 struct in_addr
*r_vtep_ip
);
91 static void zvni_neigh_del_all(zebra_vni_t
*zvni
,
92 int uninstall
, int upd_client
, u_int32_t flags
);
93 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
);
94 static int zvni_neigh_send_add_to_client(vni_t vni
,
96 struct ethaddr
*macaddr
, u_char flags
);
97 static int zvni_neigh_send_del_to_client(vni_t vni
,
99 struct ethaddr
*macaddr
, u_char flags
);
100 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
101 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
102 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
103 struct interface
*br_if
);
104 static struct interface
*zvni_map_to_svi(vlanid_t vid
,
105 struct interface
*br_if
);
107 /* l3-vni next-hop neigh related APIs */
108 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
110 static void *zl3vni_nh_alloc(void *p
);
111 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
112 struct ipaddr
*vtep_ip
,
113 struct ethaddr
*rmac
);
114 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
115 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
116 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
118 /* l3-vni rmac related APIs */
119 static void zl3vni_print_rmac_hash(struct hash_backet
*, void *);
120 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
121 struct ethaddr
*rmac
);
122 static void *zl3vni_rmac_alloc(void *p
);
123 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
124 struct ethaddr
*rmac
);
125 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
126 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
127 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
,
130 /* l3-vni related APIs*/
131 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
);
132 static void *zl3vni_alloc(void *p
);
133 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
134 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
135 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t
);
136 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
);
137 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
);
138 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
139 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
141 static unsigned int mac_hash_keymake(void *p
);
142 static int mac_cmp(const void *p1
, const void *p2
);
143 static void *zvni_mac_alloc(void *p
);
144 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
145 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
146 static int zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
);
147 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
148 struct in_addr
*r_vtep_ip
);
149 static void zvni_mac_del_all(zebra_vni_t
*zvni
,
150 int uninstall
, int upd_client
, u_int32_t flags
);
151 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
152 static int zvni_mac_send_add_to_client(vni_t vni
,
153 struct ethaddr
*macaddr
, u_char flags
);
154 static int zvni_mac_send_del_to_client(vni_t vni
,
155 struct ethaddr
*macaddr
, u_char flags
);
156 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
157 struct interface
*br_if
, vlanid_t vid
);
158 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
159 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
);
160 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
);
162 static unsigned int vni_hash_keymake(void *p
);
163 static int vni_hash_cmp(const void *p1
, const void *p2
);
164 static void *zvni_alloc(void *p
);
165 static zebra_vni_t
*zvni_lookup(vni_t vni
);
166 static zebra_vni_t
*zvni_add(vni_t vni
);
167 static int zvni_del(zebra_vni_t
*zvni
);
168 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
169 static int zvni_send_del_to_client(vni_t vni
);
170 static void zvni_build_hash_table();
171 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
172 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
173 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
174 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
175 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
176 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
177 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
178 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
179 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
180 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
181 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
182 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
184 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
185 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
186 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
189 /* Private functions */
192 * Return number of valid MACs in a VNI's MAC hash table - all
193 * remote MACs and non-internal (auto) local MACs count.
195 static u_int32_t
num_valid_macs(zebra_vni_t
*zvni
)
198 u_int32_t num_macs
= 0;
200 struct hash_backet
*hb
;
203 hash
= zvni
->mac_table
;
206 for (i
= 0; i
< hash
->size
; i
++) {
207 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
208 mac
= (zebra_mac_t
*)hb
->data
;
209 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
210 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
218 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
220 struct zebra_vrf
*zvrf
;
222 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
223 if (zvrf
&& zvrf
->advertise_gw_macip
)
226 if (zvni
&& zvni
->advertise_gw_macip
)
233 * Helper function to determine maximum width of neighbor IP address for
234 * display - just because we're dealing with IPv6 addresses that can
237 static void zvni_find_neigh_addr_width(struct hash_backet
*backet
, void *ctxt
)
240 char buf
[INET6_ADDRSTRLEN
];
241 struct neigh_walk_ctx
*wctx
= ctxt
;
244 n
= (zebra_neigh_t
*)backet
->data
;
248 ipaddr2str(&n
->ip
, buf
, sizeof(buf
)), width
= strlen(buf
);
249 if (width
> wctx
->addr_width
)
250 wctx
->addr_width
= width
;
254 * Print a specific neighbor entry.
256 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
259 char buf1
[ETHER_ADDR_STRLEN
];
260 char buf2
[INET6_ADDRSTRLEN
];
262 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
263 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
264 vty
= (struct vty
*)ctxt
;
266 vty_out(vty
, "IP: %s\n",
267 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
268 vty_out(vty
, " MAC: %s",
269 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
271 json_object_string_add(json
, "ip", buf2
);
272 json_object_string_add(json
, "mac", buf1
);
274 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
276 vty_out(vty
, " Remote VTEP: %s",
277 inet_ntoa(n
->r_vtep_ip
));
279 json_object_string_add(json
, "remoteVtep",
280 inet_ntoa(n
->r_vtep_ip
));
282 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
285 vty_out(vty
, " State: %s",
286 IS_ZEBRA_NEIGH_ACTIVE(n
) ? "Active"
290 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
292 vty_out(vty
, " Default-gateway");
294 json_object_boolean_true_add(json
, "defaultGateway");
301 * Print neighbor hash entry - called for display of all neighbors.
303 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
306 json_object
*json_vni
= NULL
, *json_row
= NULL
;
308 char buf1
[ETHER_ADDR_STRLEN
];
309 char buf2
[INET6_ADDRSTRLEN
];
310 struct neigh_walk_ctx
*wctx
= ctxt
;
313 json_vni
= wctx
->json
;
314 n
= (zebra_neigh_t
*)backet
->data
;
319 json_row
= json_object_new_object();
321 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
322 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
323 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)
324 && !(wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)) {
325 if (json_vni
== NULL
) {
326 vty_out(vty
, "%*s %-6s %-17s\n", -wctx
->addr_width
,
327 buf2
, "local", buf1
);
329 json_object_string_add(json_row
, "type", "local");
330 json_object_string_add(json_row
, "mac", buf1
);
334 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) {
335 if (IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
)) {
336 if (json_vni
== NULL
) {
337 if (wctx
->count
== 0)
339 "%*s %-6s %-17s %-21s\n",
342 "MAC", "Remote VTEP");
343 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
344 -wctx
->addr_width
, buf2
,
346 inet_ntoa(n
->r_vtep_ip
));
348 json_object_string_add(json_row
, "type",
350 json_object_string_add(json_row
, "mac",
352 json_object_string_add(
353 json_row
, "remoteVtep",
354 inet_ntoa(n
->r_vtep_ip
));
359 if (json_vni
== NULL
) {
360 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
361 -wctx
->addr_width
, buf2
, "remote", buf1
,
362 inet_ntoa(n
->r_vtep_ip
));
364 json_object_string_add(json_row
, "type",
366 json_object_string_add(json_row
, "mac", buf1
);
367 json_object_string_add(json_row
, "remoteVtep",
368 inet_ntoa(n
->r_vtep_ip
));
375 json_object_object_add(json_vni
, buf2
, json_row
);
379 * Print neighbors for all VNI.
381 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
385 json_object
*json
= NULL
, *json_vni
= NULL
;
388 struct neigh_walk_ctx wctx
;
389 char vni_str
[VNI_STR_LEN
];
391 vty
= (struct vty
*)args
[0];
392 json
= (json_object
*)args
[1];
394 zvni
= (zebra_vni_t
*)backet
->data
;
397 vty_out(vty
, "{}\n");
400 num_neigh
= hashcount(zvni
->neigh_table
);
403 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
404 zvni
->vni
, num_neigh
);
406 json_vni
= json_object_new_object();
407 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
408 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
412 json_object_object_add(json
, vni_str
, json_vni
);
416 /* Since we have IPv6 addresses to deal with which can vary widely in
417 * size, we try to be a bit more elegant in display by first computing
420 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
423 wctx
.addr_width
= 15;
424 wctx
.json
= json_vni
;
425 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
428 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
429 "Type", "MAC", "Remote VTEP");
430 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
433 json_object_object_add(json
, vni_str
, json_vni
);
436 /* print a specific next hop for an l3vni */
437 static void zl3vni_print_nh(zebra_neigh_t
*n
,
441 char buf1
[ETHER_ADDR_STRLEN
];
442 char buf2
[INET6_ADDRSTRLEN
];
443 struct listnode
*node
= NULL
;
444 struct prefix
*p
= NULL
;
445 json_object
*json_hosts
= NULL
;
448 vty_out(vty
, "Ip: %s\n",
449 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
450 vty_out(vty
, " RMAC: %s\n",
451 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
452 vty_out(vty
, " Refcount: %d\n", listcount(n
->host_list
));
453 vty_out(vty
, " Prefixes:\n");
454 for (ALL_LIST_ELEMENTS_RO(n
->host_list
, node
, p
))
455 vty_out(vty
, " %s\n",
456 prefix2str(p
, buf2
, sizeof(buf2
)));
458 json_hosts
= json_object_new_array();
459 json_object_string_add(json
, "ip",
460 ipaddr2str(&(n
->ip
), buf2
,
462 json_object_string_add(json
, "routerMac",
463 prefix_mac2str(&n
->emac
, buf2
,
465 json_object_int_add(json
, "refCount", listcount(n
->host_list
));
466 for (ALL_LIST_ELEMENTS_RO(n
->host_list
, node
, p
))
467 json_object_array_add(json_hosts
,
468 json_object_new_string(
471 json_object_object_add(json
, "prefixList", json_hosts
);
475 /* Print a specific RMAC entry */
476 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
,
480 char buf1
[ETHER_ADDR_STRLEN
];
481 char buf2
[PREFIX_STRLEN
];
482 struct listnode
*node
= NULL
;
483 struct prefix
*p
= NULL
;
484 json_object
*json_hosts
= NULL
;
487 vty_out(vty
, "MAC: %s\n",
488 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
489 vty_out(vty
, " Remote VTEP: %s\n",
490 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
491 vty_out(vty
, " Refcount: %d\n", listcount(zrmac
->host_list
));
492 vty_out(vty
, " Prefixes:\n");
493 for (ALL_LIST_ELEMENTS_RO(zrmac
->host_list
, node
, p
))
494 vty_out(vty
, " %s\n",
495 prefix2str(p
, buf2
, sizeof(buf2
)));
497 json_hosts
= json_object_new_array();
498 json_object_string_add(json
, "routerMac",
499 prefix_mac2str(&zrmac
->macaddr
,
502 json_object_string_add(json
, "vtepIp",
503 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
504 json_object_int_add(json
, "refCount",
505 listcount(zrmac
->host_list
));
506 for (ALL_LIST_ELEMENTS_RO(zrmac
->host_list
, node
, p
))
507 json_object_array_add(json_hosts
,
508 json_object_new_string(
511 json_object_object_add(json
, "prefixList", json_hosts
);
516 * Print a specific MAC entry.
518 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
)
521 zebra_neigh_t
*n
= NULL
;
522 struct listnode
*node
= NULL
;
524 char buf2
[INET6_ADDRSTRLEN
];
526 vty
= (struct vty
*)ctxt
;
527 vty_out(vty
, "MAC: %s",
528 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
)));
529 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
530 struct zebra_ns
*zns
;
531 struct interface
*ifp
;
534 ifindex
= mac
->fwd_info
.local
.ifindex
;
535 zns
= zebra_ns_lookup(NS_DEFAULT
);
536 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
537 if (!ifp
) // unexpected
539 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
540 if (mac
->fwd_info
.local
.vid
)
541 vty_out(vty
, " VLAN: %u", mac
->fwd_info
.local
.vid
);
542 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
543 vty_out(vty
, " Remote VTEP: %s",
544 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
545 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
546 vty_out(vty
, " Auto Mac ");
549 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
550 vty_out(vty
, " Sticky Mac ");
552 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
553 vty_out(vty
, " Default-gateway Mac ");
556 /* print all the associated neigh */
557 vty_out(vty
, " Neighbors:\n");
558 if (!listcount(mac
->neigh_list
))
559 vty_out(vty
, " No Neighbors\n");
561 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
562 vty_out(vty
, " %s %s\n",
563 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
564 CHECK_FLAG(n
->flags
, ZEBRA_MAC_LOCAL
)
565 ? (IS_ZEBRA_NEIGH_ACTIVE(n
)
576 * Print MAC hash entry - called for display of all MACs.
578 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
581 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
584 struct mac_walk_ctx
*wctx
= ctxt
;
587 json_mac_hdr
= wctx
->json
;
588 mac
= (zebra_mac_t
*)backet
->data
;
592 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
595 json_mac
= json_object_new_object();
597 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
598 && !(wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)) {
599 struct zebra_ns
*zns
;
601 struct interface
*ifp
;
604 zns
= zebra_ns_lookup(NS_DEFAULT
);
605 ifindex
= mac
->fwd_info
.local
.ifindex
;
606 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
607 if (!ifp
) // unexpected
609 vid
= mac
->fwd_info
.local
.vid
;
610 if (json_mac_hdr
== NULL
)
611 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
614 json_object_string_add(json_mac
, "type", "local");
615 json_object_string_add(json_mac
, "intf", ifp
->name
);
618 if (json_mac_hdr
== NULL
)
619 vty_out(vty
, " %-5u", vid
);
621 json_object_int_add(json_mac
, "vlan", vid
);
623 if (json_mac_hdr
== NULL
)
626 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
628 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
629 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) {
630 if (IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
632 if (wctx
->count
== 0) {
633 if (json_mac_hdr
== NULL
) {
634 vty_out(vty
, "\nVNI %u\n\n",
637 "%-17s %-6s %-21s %-5s\n",
643 if (json_mac_hdr
== NULL
)
644 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
646 inet_ntoa(mac
->fwd_info
649 json_object_string_add(json_mac
, "type",
651 json_object_string_add(
652 json_mac
, "remoteVtep",
653 inet_ntoa(mac
->fwd_info
655 json_object_object_add(json_mac_hdr
,
661 if (json_mac_hdr
== NULL
)
662 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
664 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
666 json_object_string_add(json_mac
, "type",
668 json_object_string_add(
669 json_mac
, "remoteVtep",
670 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
671 json_object_object_add(json_mac_hdr
, buf1
,
680 * Print MACs for all VNI.
682 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
685 json_object
*json
= NULL
, *json_vni
= NULL
;
686 json_object
*json_mac
= NULL
;
689 struct mac_walk_ctx
*wctx
= ctxt
;
690 char vni_str
[VNI_STR_LEN
];
692 vty
= (struct vty
*)wctx
->vty
;
693 json
= (struct json_object
*)wctx
->json
;
695 zvni
= (zebra_vni_t
*)backet
->data
;
698 vty_out(vty
, "{}\n");
703 /*We are iterating over a new VNI, set the count to 0*/
706 num_macs
= num_valid_macs(zvni
);
711 json_vni
= json_object_new_object();
712 json_mac
= json_object_new_object();
713 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
716 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
718 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
719 zvni
->vni
, num_macs
);
720 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
721 "Intf/Remote VTEP", "VLAN");
723 json_object_int_add(json_vni
, "numMacs", num_macs
);
725 /* assign per-vni to wctx->json object to fill macs
726 * under the vni. Re-assign primary json object to fill
727 * next vni information.
729 wctx
->json
= json_mac
;
730 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
734 json_object_object_add(json_vni
, "macs", json_mac
);
735 json_object_object_add(json
, vni_str
, json_vni
);
739 static void zl3vni_print_nh_hash(struct hash_backet
*backet
,
742 struct nh_walk_ctx
*wctx
= NULL
;
743 struct vty
*vty
= NULL
;
744 struct json_object
*json_vni
= NULL
;
745 struct json_object
*json_nh
= NULL
;
746 zebra_neigh_t
*n
= NULL
;
747 char buf1
[ETHER_ADDR_STRLEN
];
748 char buf2
[INET6_ADDRSTRLEN
];
750 wctx
= (struct nh_walk_ctx
*)ctx
;
752 json_vni
= wctx
->json
;
754 json_nh
= json_object_new_object();
755 n
= (zebra_neigh_t
*)backet
->data
;
760 vty_out(vty
, "%-15s %-17s\n",
761 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
762 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
764 json_object_string_add(json_nh
, "nexthopIp",
765 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
766 json_object_string_add(json_nh
, "routerMac",
767 prefix_mac2str(&n
->emac
, buf1
,
769 json_object_object_add(json_vni
,
770 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
775 static void zl3vni_print_nh_hash_all_vni(struct hash_backet
*backet
,
778 struct vty
*vty
= NULL
;
779 json_object
*json
= NULL
;
780 json_object
*json_vni
= NULL
;
781 zebra_l3vni_t
*zl3vni
= NULL
;
783 struct nh_walk_ctx wctx
;
784 char vni_str
[VNI_STR_LEN
];
786 vty
= (struct vty
*)args
[0];
787 json
= (struct json_object
*)args
[1];
789 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
792 vty_out(vty
, "{}\n");
796 num_nh
= hashcount(zl3vni
->nh_table
);
801 json_vni
= json_object_new_object();
802 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
806 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n",
807 zl3vni
->vni
, num_nh
);
808 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
810 json_object_int_add(json_vni
, "numNextHops", num_nh
);
812 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
814 wctx
.json
= json_vni
;
815 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
817 json_object_object_add(json
, vni_str
, json_vni
);
820 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet
*backet
,
823 struct vty
*vty
= NULL
;
824 json_object
*json
= NULL
;
825 json_object
*json_vni
= NULL
;
826 zebra_l3vni_t
*zl3vni
= NULL
;
828 struct rmac_walk_ctx wctx
;
829 char vni_str
[VNI_STR_LEN
];
831 vty
= (struct vty
*)args
[0];
832 json
= (struct json_object
*)args
[1];
834 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
837 vty_out(vty
, "{}\n");
841 num_rmacs
= hashcount(zl3vni
->rmac_table
);
846 json_vni
= json_object_new_object();
847 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
851 vty_out(vty
, "\nVNI %u #RMACs %u\n\n",
852 zl3vni
->vni
, num_rmacs
);
853 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
855 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
857 /* assign per-vni to wctx->json object to fill macs
858 * under the vni. Re-assign primary json object to fill
859 * next vni information.
861 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
863 wctx
.json
= json_vni
;
864 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
866 json_object_object_add(json
, vni_str
, json_vni
);
869 static void zl3vni_print_rmac_hash(struct hash_backet
*backet
,
872 zebra_mac_t
*zrmac
= NULL
;
873 struct rmac_walk_ctx
*wctx
= NULL
;
874 struct vty
*vty
= NULL
;
875 struct json_object
*json
= NULL
;
876 struct json_object
*json_rmac
= NULL
;
877 char buf
[ETHER_ADDR_STRLEN
];
879 wctx
= (struct rmac_walk_ctx
*)ctx
;
883 json_rmac
= json_object_new_object();
884 zrmac
= (zebra_mac_t
*)backet
->data
;
889 vty_out(vty
, "%-17s %-21s\n",
890 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
891 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
893 json_object_string_add(json_rmac
, "routerMac",
894 prefix_mac2str(&zrmac
->macaddr
, buf
,
896 json_object_string_add(json_rmac
, "vtepIp",
897 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
898 json_object_object_add(json
,
899 prefix_mac2str(&zrmac
->macaddr
, buf
,
905 /* print a specific L3 VNI entry */
906 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
908 char buf
[ETHER_ADDR_STRLEN
];
909 struct vty
*vty
= NULL
;
910 json_object
*json
= NULL
;
911 zebra_vni_t
*zvni
= NULL
;
912 json_object
*json_vni_list
= NULL
;
913 struct listnode
*node
= NULL
, *nnode
= NULL
;
919 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
920 vty_out(vty
, " Type: %s\n", "L3");
921 vty_out(vty
, " Tenant VRF: %s\n",
922 zl3vni_vrf_name(zl3vni
));
923 vty_out(vty
, " Local Vtep Ip: %s\n",
924 inet_ntoa(zl3vni
->local_vtep_ip
));
925 vty_out(vty
, " Vxlan-Intf: %s\n",
926 zl3vni_vxlan_if_name(zl3vni
));
927 vty_out(vty
, " SVI-If: %s\n",
928 zl3vni_svi_if_name(zl3vni
));
929 vty_out(vty
, " State: %s\n",
930 zl3vni_state2str(zl3vni
));
931 vty_out(vty
, " VNI Filter: %s\n",
932 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ?
933 "prefix-routes-only" : "none");
934 vty_out(vty
, " Router MAC: %s\n",
935 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
936 vty_out(vty
, " L2 VNIs: ");
937 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
938 vty_out(vty
, "%u ", zvni
->vni
);
941 json_vni_list
= json_object_new_array();
942 json_object_int_add(json
, "vni", zl3vni
->vni
);
943 json_object_string_add(json
, "type", "L3");
944 json_object_string_add(json
, "localVtepIp",
945 inet_ntoa(zl3vni
->local_vtep_ip
));
946 json_object_string_add(json
, "vxlanIntf",
947 zl3vni_vxlan_if_name(zl3vni
));
948 json_object_string_add(json
, "sviIntf",
949 zl3vni_svi_if_name(zl3vni
));
950 json_object_string_add(json
, "state",
951 zl3vni_state2str(zl3vni
));
952 json_object_string_add(json
, "vrf",
953 zl3vni_vrf_name(zl3vni
));
954 json_object_string_add(json
, "routerMac",
955 zl3vni_rmac2str(zl3vni
, buf
,
957 json_object_string_add(json
, "vniFilter",
958 CHECK_FLAG(zl3vni
->filter
,
959 PREFIX_ROUTES_ONLY
) ?
960 "prefix-routes-only" : "none");
961 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
962 json_object_array_add(json_vni_list
,
963 json_object_new_int(zvni
->vni
));
965 json_object_object_add(json
, "l2Vnis", json_vni_list
);
970 * Print a specific VNI entry.
972 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
978 json_object
*json
= NULL
;
979 json_object
*json_vtep_list
= NULL
;
980 json_object
*json_ip_str
= NULL
;
986 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
987 vty_out(vty
, " Type: %s\n", "L2");
988 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
990 json_object_int_add(json
, "vni", zvni
->vni
);
991 json_object_string_add(json
, "type", "L2");
992 json_object_string_add(json
, "vrf",
993 vrf_id_to_name(zvni
->vrf_id
));
996 if (!zvni
->vxlan_if
) { // unexpected
998 vty_out(vty
, " VxLAN interface: unknown\n");
1001 num_macs
= num_valid_macs(zvni
);
1002 num_neigh
= hashcount(zvni
->neigh_table
);
1004 vty_out(vty
, " VxLAN interface: %s\n",
1005 zvni
->vxlan_if
->name
);
1006 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1007 vty_out(vty
," Local VTEP IP: %s\n",
1008 inet_ntoa(zvni
->local_vtep_ip
));
1010 json_object_string_add(json
, "vxlanInterface",
1011 zvni
->vxlan_if
->name
);
1012 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1013 json_object_string_add(json
, "vtepIp",
1014 inet_ntoa(zvni
->local_vtep_ip
));
1015 json_object_string_add(json
, "advertiseGatewayMacip",
1016 zvni
->advertise_gw_macip
? "Yes" : "No");
1017 json_object_int_add(json
, "numMacs", num_macs
);
1018 json_object_int_add(json
, "numArpNd", num_neigh
);
1022 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1025 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1027 json_vtep_list
= json_object_new_array();
1028 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1030 vty_out(vty
, " %s\n",
1031 inet_ntoa(zvtep
->vtep_ip
));
1033 json_ip_str
= json_object_new_string(
1034 inet_ntoa(zvtep
->vtep_ip
));
1035 json_object_array_add(json_vtep_list
,
1040 json_object_object_add(json
, "numRemoteVteps",
1045 " Number of MACs (local and remote) known for this VNI: %u\n",
1048 " Number of ARPs (IPv4 and IPv6, local and remote) "
1049 "known for this VNI: %u\n",
1051 vty_out(vty
, " Advertise-gw-macip: %s\n",
1052 zvni
->advertise_gw_macip
? "Yes" : "No");
1056 /* print a L3 VNI hash entry */
1057 static void zl3vni_print_hash(struct hash_backet
*backet
,
1060 struct vty
*vty
= NULL
;
1061 json_object
*json
= NULL
;
1062 json_object
*json_vni
= NULL
;
1063 zebra_l3vni_t
*zl3vni
= NULL
;
1065 vty
= (struct vty
*)ctx
[0];
1066 json
= (json_object
*)ctx
[1];
1068 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1074 "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1076 zl3vni_vxlan_if_name(zl3vni
),
1077 hashcount(zl3vni
->rmac_table
),
1078 hashcount(zl3vni
->nh_table
),
1080 zl3vni_vrf_name(zl3vni
));
1082 char vni_str
[VNI_STR_LEN
];
1084 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1085 json_vni
= json_object_new_object();
1086 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1087 json_object_string_add(json_vni
, "vxlanIf",
1088 zl3vni_vxlan_if_name(zl3vni
));
1089 json_object_int_add(json_vni
, "numMacs",
1090 hashcount(zl3vni
->rmac_table
));
1091 json_object_int_add(json_vni
, "numArpNd",
1092 hashcount(zl3vni
->nh_table
));
1093 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1094 json_object_string_add(json_vni
, "type", "L3");
1095 json_object_string_add(json_vni
, "tenantVrf",
1096 zl3vni_vrf_name(zl3vni
));
1097 json_object_object_add(json
, vni_str
, json_vni
);
1103 * Print a VNI hash entry - called for display of all VNIs.
1105 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1109 zebra_vtep_t
*zvtep
;
1110 u_int32_t num_vteps
= 0;
1111 u_int32_t num_macs
= 0;
1112 u_int32_t num_neigh
= 0;
1113 json_object
*json
= NULL
;
1114 json_object
*json_vni
= NULL
;
1115 json_object
*json_ip_str
= NULL
;
1116 json_object
*json_vtep_list
= NULL
;
1121 zvni
= (zebra_vni_t
*)backet
->data
;
1125 zvtep
= zvni
->vteps
;
1128 zvtep
= zvtep
->next
;
1131 num_macs
= num_valid_macs(zvni
);
1132 num_neigh
= hashcount(zvni
->neigh_table
);
1135 "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1137 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1138 num_macs
, num_neigh
,
1140 vrf_id_to_name(zvni
->vrf_id
));
1142 char vni_str
[VNI_STR_LEN
];
1143 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1144 json_vni
= json_object_new_object();
1145 json_object_int_add(json_vni
, "vni", zvni
->vni
);
1146 json_object_string_add(json_vni
, "type", "L2");
1147 json_object_string_add(json_vni
, "vxlanIf",
1148 zvni
->vxlan_if
? zvni
->vxlan_if
->name
1150 json_object_int_add(json_vni
, "numMacs", num_macs
);
1151 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1152 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
1153 json_object_string_add(json_vni
, "tenantVrf",
1154 vrf_id_to_name(zvni
->vrf_id
));
1156 json_vtep_list
= json_object_new_array();
1157 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1158 json_ip_str
= json_object_new_string(
1159 inet_ntoa(zvtep
->vtep_ip
));
1160 json_object_array_add(json_vtep_list
,
1163 json_object_object_add(json_vni
, "remoteVteps",
1166 json_object_object_add(json
, vni_str
, json_vni
);
1171 * Inform BGP about local MACIP.
1173 static int zvni_macip_send_msg_to_client(vni_t vni
,
1174 struct ethaddr
*macaddr
,
1175 struct ipaddr
*ip
, u_char flags
,
1178 char buf
[ETHER_ADDR_STRLEN
];
1179 char buf2
[INET6_ADDRSTRLEN
];
1181 struct zserv
*client
= NULL
;
1182 struct stream
*s
= NULL
;
1184 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
1185 /* BGP may not be running. */
1192 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
1193 stream_putl(s
, vni
);
1194 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
1197 if (IS_IPADDR_V4(ip
))
1198 ipa_len
= IPV4_MAX_BYTELEN
;
1199 else if (IS_IPADDR_V6(ip
))
1200 ipa_len
= IPV6_MAX_BYTELEN
;
1202 stream_putl(s
, ipa_len
); /* IP address length */
1204 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
1206 stream_putl(s
, 0); /* Just MAC. */
1208 stream_putc(s
, flags
); /* sticky mac/gateway mac */
1211 /* Write packet size. */
1212 stream_putw_at(s
, 0, stream_get_endp(s
));
1214 if (IS_ZEBRA_DEBUG_VXLAN
)
1216 "Send MACIP %s flags 0x%x MAC %s IP %s L2-VNI %u to %s",
1217 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del",
1218 flags
, prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1219 ipaddr2str(ip
, buf2
, sizeof(buf2
)), vni
,
1220 zebra_route_string(client
->proto
));
1222 if (cmd
== ZEBRA_MACIP_ADD
)
1223 client
->macipadd_cnt
++;
1225 client
->macipdel_cnt
++;
1227 return zebra_server_send_message(client
);
1231 * Make hash key for neighbors.
1233 static unsigned int neigh_hash_keymake(void *p
)
1235 zebra_neigh_t
*n
= p
;
1236 struct ipaddr
*ip
= &n
->ip
;
1238 if (IS_IPADDR_V4(ip
))
1239 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
1241 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
1242 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
1246 * Compare two neighbor hash structures.
1248 static int neigh_cmp(const void *p1
, const void *p2
)
1250 const zebra_neigh_t
*n1
= p1
;
1251 const zebra_neigh_t
*n2
= p2
;
1253 if (n1
== NULL
&& n2
== NULL
)
1256 if (n1
== NULL
|| n2
== NULL
)
1259 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
1263 * Callback to allocate neighbor hash entry.
1265 static void *zvni_neigh_alloc(void *p
)
1267 const zebra_neigh_t
*tmp_n
= p
;
1270 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
1277 * Add neighbor entry.
1279 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
1280 struct ethaddr
*mac
)
1282 zebra_neigh_t tmp_n
;
1283 zebra_neigh_t
*n
= NULL
;
1284 zebra_mac_t
*zmac
= NULL
;
1286 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
1287 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1288 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
1291 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1292 n
->state
= ZEBRA_NEIGH_INACTIVE
;
1294 /* Associate the neigh to mac */
1295 zmac
= zvni_mac_lookup(zvni
, mac
);
1297 listnode_add_sort(zmac
->neigh_list
, n
);
1303 * Delete neighbor entry.
1305 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1307 zebra_neigh_t
*tmp_n
;
1308 zebra_mac_t
*zmac
= NULL
;
1310 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
1312 listnode_delete(zmac
->neigh_list
, n
);
1314 /* Free the VNI hash entry and allocated memory. */
1315 tmp_n
= hash_release(zvni
->neigh_table
, n
);
1317 XFREE(MTYPE_NEIGH
, tmp_n
);
1323 * Free neighbor hash entry (callback)
1325 static int zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
1327 struct neigh_walk_ctx
*wctx
= arg
;
1328 zebra_neigh_t
*n
= backet
->data
;
1330 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1331 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
1332 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
1333 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
1334 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
1335 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
1336 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1337 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
1340 if (wctx
->uninstall
)
1341 zvni_neigh_uninstall(wctx
->zvni
, n
);
1343 return zvni_neigh_del(wctx
->zvni
, n
);
1350 * Delete all neighbor entries from specific VTEP for a particular VNI.
1352 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
1353 struct in_addr
*r_vtep_ip
)
1355 struct neigh_walk_ctx wctx
;
1357 if (!zvni
->neigh_table
)
1360 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1362 wctx
.uninstall
= uninstall
;
1363 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
1364 wctx
.r_vtep_ip
= *r_vtep_ip
;
1366 hash_iterate(zvni
->neigh_table
,
1367 (void (*)(struct hash_backet
*,
1368 void *))zvni_neigh_del_hash_entry
,
1373 * Delete all neighbor entries for this VNI.
1375 static void zvni_neigh_del_all(zebra_vni_t
*zvni
,
1376 int uninstall
, int upd_client
, u_int32_t flags
)
1378 struct neigh_walk_ctx wctx
;
1380 if (!zvni
->neigh_table
)
1383 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1385 wctx
.uninstall
= uninstall
;
1386 wctx
.upd_client
= upd_client
;
1389 hash_iterate(zvni
->neigh_table
,
1390 (void (*)(struct hash_backet
*,
1391 void *))zvni_neigh_del_hash_entry
,
1396 * Look up neighbor hash entry.
1398 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
1403 memset(&tmp
, 0, sizeof(tmp
));
1404 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
1405 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
1410 /* Process all neigh associated to a mac upon local mac add event */
1411 static void zvni_process_neigh_on_local_mac_add(zebra_vni_t
*zvni
,
1414 zebra_neigh_t
*n
= NULL
;
1415 struct listnode
*node
= NULL
;
1416 char buf
[ETHER_ADDR_STRLEN
];
1417 char buf2
[INET6_ADDRSTRLEN
];
1419 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1420 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1421 /* MAC is learnt locally, program all inactive neigh
1422 * pointing to this mac */
1423 if (IS_ZEBRA_NEIGH_INACTIVE(n
)) {
1424 if (IS_ZEBRA_DEBUG_VXLAN
)
1426 "neigh %s (MAC %s) on L2-VNI %u is now ACTIVE",
1427 ipaddr2str(&n
->ip
, buf2
,
1429 prefix_mac2str(&n
->emac
, buf
,
1433 ZEBRA_NEIGH_SET_ACTIVE(n
);
1434 zvni_neigh_send_add_to_client(
1435 zvni
->vni
, &n
->ip
, &n
->emac
, n
->flags
);
1437 if (IS_ZEBRA_DEBUG_VXLAN
)
1439 "neigh %s (MAC %s) on VNI %u should NOT be ACTIVE",
1440 ipaddr2str(&n
->ip
, buf2
,
1442 prefix_mac2str(&n
->emac
, buf
,
1446 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1447 /* TODO: assume the neigh has moved too ?? */
1452 /* Process all neigh associated to a mac upon local mac del event */
1453 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
1456 zebra_neigh_t
*n
= NULL
;
1457 struct listnode
*node
= NULL
;
1458 char buf
[ETHER_ADDR_STRLEN
];
1459 char buf2
[INET6_ADDRSTRLEN
];
1461 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1462 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1463 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1464 if (IS_ZEBRA_DEBUG_VXLAN
)
1466 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1467 ipaddr2str(&n
->ip
, buf2
,
1469 prefix_mac2str(&n
->emac
, buf
,
1473 ZEBRA_NEIGH_SET_INACTIVE(n
);
1474 zvni_neigh_send_del_to_client(
1475 zvni
->vni
, &n
->ip
, &n
->emac
, 0);
1477 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1478 if (IS_ZEBRA_DEBUG_VXLAN
)
1480 "local MAC %s getting deleted on VNI %u has remote neigh %s",
1481 prefix_mac2str(&n
->emac
, buf
,
1484 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1489 /* process all neigh associated to a mac entry upon remote mac add */
1490 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
1493 zebra_neigh_t
*n
= NULL
;
1494 struct listnode
*node
= NULL
;
1495 char buf
[ETHER_ADDR_STRLEN
];
1496 char buf2
[INET6_ADDRSTRLEN
];
1498 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1499 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1500 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1501 if (IS_ZEBRA_DEBUG_VXLAN
)
1503 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1504 ipaddr2str(&n
->ip
, buf2
,
1506 prefix_mac2str(&n
->emac
, buf
,
1510 ZEBRA_NEIGH_SET_INACTIVE(n
);
1511 zvni_neigh_send_del_to_client(
1512 zvni
->vni
, &n
->ip
, &n
->emac
, 0);
1518 /* process all neigh associated to mac entry upon remote mac del */
1519 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
1522 zebra_neigh_t
*n
= NULL
;
1523 struct listnode
*node
= NULL
;
1524 char buf
[ETHER_ADDR_STRLEN
];
1525 char buf2
[INET6_ADDRSTRLEN
];
1527 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1528 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1529 if (IS_ZEBRA_DEBUG_VXLAN
)
1531 "remote MAC %s getting deleted on VNI %u has local neigh %s",
1532 prefix_mac2str(&n
->emac
, buf
,
1535 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1541 * Inform BGP about local neighbor addition.
1543 static int zvni_neigh_send_add_to_client(vni_t vni
,
1545 struct ethaddr
*macaddr
,
1550 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
1551 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
1553 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1558 * Inform BGP about local neighbor deletion.
1560 static int zvni_neigh_send_del_to_client(vni_t vni
,
1562 struct ethaddr
*macaddr
, u_char flags
)
1564 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1569 * Install remote neighbor into the kernel.
1571 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1573 struct zebra_if
*zif
;
1574 struct zebra_l2info_vxlan
*vxl
;
1575 struct interface
*vlan_if
;
1577 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1580 zif
= zvni
->vxlan_if
->info
;
1583 vxl
= &zif
->l2info
.vxl
;
1585 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1589 return kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
);
1593 * Uninstall remote neighbor from the kernel.
1595 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1597 struct zebra_if
*zif
;
1598 struct zebra_l2info_vxlan
*vxl
;
1599 struct interface
*vlan_if
;
1601 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1604 if (!zvni
->vxlan_if
) {
1605 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
1610 zif
= zvni
->vxlan_if
->info
;
1613 vxl
= &zif
->l2info
.vxl
;
1614 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1618 return kernel_del_neigh(vlan_if
, &n
->ip
);
1622 * Install neighbor hash entry - called upon access VLAN change.
1624 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
1627 struct neigh_walk_ctx
*wctx
= ctxt
;
1629 n
= (zebra_neigh_t
*)backet
->data
;
1633 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
1634 zvni_neigh_install(wctx
->zvni
, n
);
1637 /* Get the VRR interface for SVI if any */
1638 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
1640 struct zebra_vrf
*zvrf
= NULL
;
1641 struct interface
*tmp_if
= NULL
;
1642 struct zebra_if
*zif
= NULL
;
1644 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1647 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
1652 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
1655 if (zif
->link
== ifp
)
1662 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1664 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1665 struct connected
*c
= NULL
;
1666 struct ethaddr macaddr
;
1668 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1670 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1673 memset(&ip
, 0, sizeof(struct ipaddr
));
1674 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1677 if (c
->address
->family
== AF_INET
) {
1678 ip
.ipa_type
= IPADDR_V4
;
1679 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1680 sizeof(struct in_addr
));
1681 } else if (c
->address
->family
== AF_INET6
) {
1682 ip
.ipa_type
= IPADDR_V6
;
1683 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1684 sizeof(struct in6_addr
));
1689 zvni_gw_macip_del(ifp
, zvni
, &ip
);
1695 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1697 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1698 struct connected
*c
= NULL
;
1699 struct ethaddr macaddr
;
1701 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1703 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1706 memset(&ip
, 0, sizeof(struct ipaddr
));
1707 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1710 if (c
->address
->family
== AF_INET
) {
1711 ip
.ipa_type
= IPADDR_V4
;
1712 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1713 sizeof(struct in_addr
));
1714 } else if (c
->address
->family
== AF_INET6
) {
1715 ip
.ipa_type
= IPADDR_V6
;
1716 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1717 sizeof(struct in6_addr
));
1722 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
1728 static int zvni_advertise_subnet(zebra_vni_t
*zvni
,
1729 struct interface
*ifp
,
1732 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1733 struct connected
*c
= NULL
;
1734 struct ethaddr macaddr
;
1736 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1738 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1741 memcpy(&p
, c
->address
, sizeof(struct prefix
));
1743 /* skip link local address */
1744 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
1749 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1750 ZEBRA_IP_PREFIX_ROUTE_ADD
);
1752 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1753 ZEBRA_IP_PREFIX_ROUTE_DEL
);
1759 * zvni_gw_macip_add_to_client
1761 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
1762 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
1764 char buf
[ETHER_ADDR_STRLEN
];
1765 char buf2
[INET6_ADDRSTRLEN
];
1766 zebra_neigh_t
*n
= NULL
;
1767 zebra_mac_t
*mac
= NULL
;
1768 struct zebra_if
*zif
= NULL
;
1769 struct zebra_l2info_vxlan
*vxl
= NULL
;
1771 zif
= zvni
->vxlan_if
->info
;
1775 vxl
= &zif
->l2info
.vxl
;
1777 mac
= zvni_mac_lookup(zvni
, macaddr
);
1779 mac
= zvni_mac_add(zvni
, macaddr
);
1781 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
1782 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1783 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
1788 /* Set "local" forwarding info. */
1789 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
1790 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
1791 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
1792 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
1793 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
1794 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
1796 n
= zvni_neigh_lookup(zvni
, ip
);
1798 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
1801 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1802 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
1803 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1804 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
1809 /* Set "local" forwarding info. */
1810 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
1811 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
1812 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
1813 n
->ifindex
= ifp
->ifindex
;
1815 /* Only advertise in BGP if the knob is enabled */
1816 if (!advertise_gw_macip_enabled(zvni
))
1819 if (IS_ZEBRA_DEBUG_VXLAN
)
1821 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP",
1822 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1823 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1824 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1826 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
1833 * zvni_gw_macip_del_from_client
1835 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
1838 char buf1
[ETHER_ADDR_STRLEN
];
1839 char buf2
[INET6_ADDRSTRLEN
];
1840 zebra_neigh_t
*n
= NULL
;
1841 zebra_mac_t
*mac
= NULL
;
1843 /* If the neigh entry is not present nothing to do*/
1844 n
= zvni_neigh_lookup(zvni
, ip
);
1848 /* mac entry should be present */
1849 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
1851 zlog_err("MAC %s doesnt exists for neigh %s on VNI %u",
1852 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
1853 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1857 /* If the entry is not local nothing to do*/
1858 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
1861 /* only need to delete the entry from bgp if we sent it before */
1862 if (IS_ZEBRA_DEBUG_VXLAN
)
1863 zlog_debug("%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
1864 ifp
->vrf_id
, ifp
->name
,
1865 ifp
->ifindex
, zvni
->vni
,
1866 prefix_mac2str(&(n
->emac
),
1869 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1871 /* Remove neighbor from BGP. */
1872 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
1873 ZEBRA_MACIP_TYPE_GW
);
1875 /* Delete this neighbor entry. */
1876 zvni_neigh_del(zvni
, n
);
1878 /* see if the mac needs to be deleted as well*/
1880 zvni_deref_ip2mac(zvni
, mac
, 0);
1885 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
1888 zebra_vni_t
*zvni
= NULL
;
1889 struct zebra_if
*zif
= NULL
;
1890 struct zebra_l2info_vxlan zl2_info
;
1891 struct interface
*vlan_if
= NULL
;
1892 struct interface
*vrr_if
= NULL
;
1893 struct interface
*ifp
;
1895 /* Add primary SVI MAC*/
1896 zvni
= (zebra_vni_t
*)backet
->data
;
1900 ifp
= zvni
->vxlan_if
;
1905 /* If down or not mapped to a bridge, we're done. */
1906 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1909 zl2_info
= zif
->l2info
.vxl
;
1911 vlan_if
= 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
;
1950 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
1951 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
);
1967 * Make hash key for MAC.
1969 static unsigned int mac_hash_keymake(void *p
)
1971 zebra_mac_t
*pmac
= p
;
1972 const void *pnt
= (void *)pmac
->macaddr
.octet
;
1974 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
1978 * Compare two MAC addresses.
1980 static int mac_cmp(const void *p1
, const void *p2
)
1982 const zebra_mac_t
*pmac1
= p1
;
1983 const zebra_mac_t
*pmac2
= p2
;
1985 if (pmac1
== NULL
&& pmac2
== NULL
)
1988 if (pmac1
== NULL
|| pmac2
== NULL
)
1991 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
,
1997 * Callback to allocate MAC hash entry.
1999 static void *zvni_mac_alloc(void *p
)
2001 const zebra_mac_t
*tmp_mac
= p
;
2004 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2007 return ((void *)mac
);
2013 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
2015 zebra_mac_t tmp_mac
;
2016 zebra_mac_t
*mac
= NULL
;
2018 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
2019 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
2020 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
2023 mac
->neigh_list
= list_new();
2024 mac
->neigh_list
->cmp
= (int (*)(void *, void *))neigh_cmp
;
2032 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2034 zebra_mac_t
*tmp_mac
;
2036 list_delete_and_null(&mac
->neigh_list
);
2038 /* Free the VNI hash entry and allocated memory. */
2039 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
2041 XFREE(MTYPE_MAC
, tmp_mac
);
2047 * Free MAC hash entry (callback)
2049 static int zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2051 struct mac_walk_ctx
*wctx
= arg
;
2052 zebra_mac_t
*mac
= backet
->data
;
2054 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
2055 || ((wctx
->flags
& DEL_REMOTE_MAC
)
2056 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
2057 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
2058 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
2059 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
2060 &wctx
->r_vtep_ip
))) {
2061 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
2062 zvni_mac_send_del_to_client(
2063 wctx
->zvni
->vni
, &mac
->macaddr
,
2067 if (wctx
->uninstall
)
2068 zvni_mac_uninstall(wctx
->zvni
, mac
, 0);
2070 return zvni_mac_del(wctx
->zvni
, mac
);
2077 * Delete all MAC entries from specific VTEP for a particular VNI.
2079 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2080 struct in_addr
*r_vtep_ip
)
2082 struct mac_walk_ctx wctx
;
2084 if (!zvni
->mac_table
)
2087 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2089 wctx
.uninstall
= uninstall
;
2090 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
2091 wctx
.r_vtep_ip
= *r_vtep_ip
;
2093 hash_iterate(zvni
->mac_table
, (void (*)(struct hash_backet
*,
2094 void *))zvni_mac_del_hash_entry
,
2099 * Delete all MAC entries for this VNI.
2101 static void zvni_mac_del_all(zebra_vni_t
*zvni
,
2102 int uninstall
, int upd_client
, u_int32_t flags
)
2104 struct mac_walk_ctx wctx
;
2106 if (!zvni
->mac_table
)
2109 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2111 wctx
.uninstall
= uninstall
;
2112 wctx
.upd_client
= upd_client
;
2115 hash_iterate(zvni
->mac_table
, (void (*)(struct hash_backet
*,
2116 void *))zvni_mac_del_hash_entry
,
2121 * Look up MAC hash entry.
2123 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
2128 memset(&tmp
, 0, sizeof(tmp
));
2129 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
2130 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
2136 * Inform BGP about local MAC addition.
2138 static int zvni_mac_send_add_to_client(vni_t vni
,
2139 struct ethaddr
*macaddr
,
2144 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2145 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2146 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2147 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2149 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2154 * Inform BGP about local MAC deletion.
2156 static int zvni_mac_send_del_to_client(vni_t vni
,
2157 struct ethaddr
*macaddr
,
2162 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2163 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2164 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2165 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2167 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2172 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2173 * notifications, to see if they are of interest.
2175 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
2176 struct interface
*br_if
, vlanid_t vid
)
2178 struct zebra_ns
*zns
;
2179 struct route_node
*rn
;
2180 struct interface
*tmp_if
= NULL
;
2181 struct zebra_if
*zif
;
2182 struct zebra_l2info_bridge
*br
;
2183 struct zebra_l2info_vxlan
*vxl
= NULL
;
2184 u_char bridge_vlan_aware
;
2188 /* Determine if bridge is VLAN-aware or not */
2191 br
= &zif
->l2info
.br
;
2192 bridge_vlan_aware
= br
->vlan_aware
;
2194 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2195 /* TODO: Optimize with a hash. */
2196 zns
= zebra_ns_lookup(NS_DEFAULT
);
2197 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2198 tmp_if
= (struct interface
*)rn
->info
;
2202 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2204 if (!if_is_operative(tmp_if
))
2206 vxl
= &zif
->l2info
.vxl
;
2208 if (zif
->brslave_info
.br_if
!= br_if
)
2211 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2220 zvni
= zvni_lookup(vxl
->vni
);
2225 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2226 * neighbor notifications, to see if they are of interest.
2228 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
2229 struct interface
*br_if
)
2231 struct zebra_ns
*zns
;
2232 struct route_node
*rn
;
2233 struct interface
*tmp_if
= NULL
;
2234 struct zebra_if
*zif
;
2235 struct zebra_l2info_bridge
*br
;
2236 struct zebra_l2info_vxlan
*vxl
= NULL
;
2237 u_char bridge_vlan_aware
;
2245 /* Make sure the linked interface is a bridge. */
2246 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
2249 /* Determine if bridge is VLAN-aware or not */
2252 br
= &zif
->l2info
.br
;
2253 bridge_vlan_aware
= br
->vlan_aware
;
2254 if (bridge_vlan_aware
) {
2255 struct zebra_l2info_vlan
*vl
;
2257 if (!IS_ZEBRA_IF_VLAN(ifp
))
2262 vl
= &zif
->l2info
.vl
;
2266 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2267 /* TODO: Optimize with a hash. */
2268 zns
= zebra_ns_lookup(NS_DEFAULT
);
2269 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2270 tmp_if
= (struct interface
*)rn
->info
;
2274 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2276 if (!if_is_operative(tmp_if
))
2278 vxl
= &zif
->l2info
.vxl
;
2280 if (zif
->brslave_info
.br_if
!= br_if
)
2283 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2292 zvni
= zvni_lookup(vxl
->vni
);
2296 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
2298 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
2299 * linked to the bridge
2300 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
2303 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
2305 struct zebra_ns
*zns
;
2306 struct route_node
*rn
;
2307 struct interface
*tmp_if
= NULL
;
2308 struct zebra_if
*zif
;
2309 struct zebra_l2info_bridge
*br
;
2310 struct zebra_l2info_vlan
*vl
;
2311 u_char bridge_vlan_aware
;
2314 /* Defensive check, caller expected to invoke only with valid bridge. */
2318 /* Determine if bridge is VLAN-aware or not */
2321 br
= &zif
->l2info
.br
;
2322 bridge_vlan_aware
= br
->vlan_aware
;
2324 /* Check oper status of the SVI. */
2325 if (!bridge_vlan_aware
)
2326 return if_is_operative(br_if
) ? br_if
: NULL
;
2328 /* Identify corresponding VLAN interface. */
2329 /* TODO: Optimize with a hash. */
2330 zns
= zebra_ns_lookup(NS_DEFAULT
);
2331 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2332 tmp_if
= (struct interface
*)rn
->info
;
2333 /* Check oper status of the SVI. */
2334 if (!tmp_if
|| !if_is_operative(tmp_if
))
2337 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
2338 || zif
->link
!= br_if
)
2340 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
2342 if (vl
->vid
== vid
) {
2348 return found
? tmp_if
: NULL
;
2352 * Install remote MAC into the kernel.
2354 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2356 struct zebra_if
*zif
;
2357 struct zebra_l2info_vxlan
*vxl
;
2360 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2363 zif
= zvni
->vxlan_if
->info
;
2366 vxl
= &zif
->l2info
.vxl
;
2368 sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0;
2370 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
2371 mac
->fwd_info
.r_vtep_ip
, sticky
);
2375 * Uninstall remote MAC from the kernel. In the scenario where the MAC
2376 * moves to remote, we have to uninstall any existing local entry first.
2378 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
)
2380 struct zebra_if
*zif
;
2381 struct zebra_l2info_vxlan
*vxl
;
2382 struct in_addr vtep_ip
= {.s_addr
= 0};
2383 struct zebra_ns
*zns
;
2384 struct interface
*ifp
;
2386 if (!local
&& !(mac
->flags
& ZEBRA_MAC_REMOTE
))
2389 if (!zvni
->vxlan_if
) {
2390 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2395 zif
= zvni
->vxlan_if
->info
;
2398 vxl
= &zif
->l2info
.vxl
;
2401 zns
= zebra_ns_lookup(NS_DEFAULT
);
2402 ifp
= if_lookup_by_index_per_ns(zns
,
2403 mac
->fwd_info
.local
.ifindex
);
2404 if (!ifp
) // unexpected
2407 ifp
= zvni
->vxlan_if
;
2408 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
2411 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
,
2416 * Install MAC hash entry - called upon access VLAN change.
2418 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
2421 struct mac_walk_ctx
*wctx
= ctxt
;
2423 mac
= (zebra_mac_t
*)backet
->data
;
2427 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
2428 zvni_mac_install(wctx
->zvni
, mac
);
2432 * Decrement neighbor refcount of MAC; uninstall and free it if
2435 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
2438 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)
2439 || !list_isempty(mac
->neigh_list
))
2443 zvni_mac_uninstall(zvni
, mac
, 0);
2445 zvni_mac_del(zvni
, mac
);
2449 * Read and populate local MACs and neighbors corresponding to this VNI.
2451 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
,
2452 struct interface
*ifp
)
2454 struct zebra_ns
*zns
;
2455 struct zebra_if
*zif
;
2456 struct interface
*vlan_if
;
2457 struct zebra_l2info_vxlan
*vxl
;
2458 struct interface
*vrr_if
;
2461 vxl
= &zif
->l2info
.vxl
;
2462 zns
= zebra_ns_lookup(NS_DEFAULT
);
2464 if (IS_ZEBRA_DEBUG_VXLAN
)
2466 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2467 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2468 zif
->brslave_info
.bridge_ifindex
);
2470 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
2471 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2474 /* Add SVI MAC-IP */
2475 zvni_add_macip_for_intf(vlan_if
, zvni
);
2477 /* Add VRR MAC-IP - if any*/
2478 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2480 zvni_add_macip_for_intf(vrr_if
, zvni
);
2482 neigh_read_for_vlan(zns
, vlan_if
);
2487 * Hash function for VNI.
2489 static unsigned int vni_hash_keymake(void *p
)
2491 const zebra_vni_t
*zvni
= p
;
2493 return (jhash_1word(zvni
->vni
, 0));
2497 * Compare 2 VNI hash entries.
2499 static int vni_hash_cmp(const void *p1
, const void *p2
)
2501 const zebra_vni_t
*zvni1
= p1
;
2502 const zebra_vni_t
*zvni2
= p2
;
2504 return (zvni1
->vni
== zvni2
->vni
);
2508 * Callback to allocate VNI hash entry.
2510 static void *zvni_alloc(void *p
)
2512 const zebra_vni_t
*tmp_vni
= p
;
2515 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
2516 zvni
->vni
= tmp_vni
->vni
;
2517 return ((void *)zvni
);
2521 * Look up VNI hash entry.
2523 static zebra_vni_t
*zvni_lookup(vni_t vni
)
2525 struct zebra_vrf
*zvrf
;
2526 zebra_vni_t tmp_vni
;
2527 zebra_vni_t
*zvni
= NULL
;
2529 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2531 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
2533 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
2539 * Add VNI hash entry.
2541 static zebra_vni_t
*zvni_add(vni_t vni
)
2543 struct zebra_vrf
*zvrf
;
2544 zebra_vni_t tmp_zvni
;
2545 zebra_vni_t
*zvni
= NULL
;
2547 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2549 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
2551 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
2554 /* Create hash table for MAC */
2556 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
2558 /* Create hash table for neighbors */
2559 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
2560 "Zebra VNI Neighbor Table");
2566 * Delete VNI hash entry.
2568 static int zvni_del(zebra_vni_t
*zvni
)
2570 struct zebra_vrf
*zvrf
;
2571 zebra_vni_t
*tmp_zvni
;
2573 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2576 zvni
->vxlan_if
= NULL
;
2578 /* Free the neighbor hash table. */
2579 hash_free(zvni
->neigh_table
);
2580 zvni
->neigh_table
= NULL
;
2582 /* Free the MAC hash table. */
2583 hash_free(zvni
->mac_table
);
2584 zvni
->mac_table
= NULL
;
2586 /* Free the VNI hash entry and allocated memory. */
2587 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
2589 XFREE(MTYPE_ZVNI
, tmp_zvni
);
2595 * Inform BGP about local VNI addition.
2597 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
2599 struct zserv
*client
;
2602 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
2603 /* BGP may not be running. */
2610 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
2611 stream_putl(s
, zvni
->vni
);
2612 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
2613 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
2615 /* Write packet size. */
2616 stream_putw_at(s
, 0, stream_get_endp(s
));
2618 if (IS_ZEBRA_DEBUG_VXLAN
)
2619 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s",
2620 zvni
->vni
, inet_ntoa(zvni
->local_vtep_ip
),
2621 vrf_id_to_name(zvni
->vrf_id
),
2622 zebra_route_string(client
->proto
));
2624 client
->vniadd_cnt
++;
2625 return zebra_server_send_message(client
);
2629 * Inform BGP about local VNI deletion.
2631 static int zvni_send_del_to_client(vni_t vni
)
2633 struct zserv
*client
;
2636 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
2637 /* BGP may not be running. */
2644 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
2645 stream_putl(s
, vni
);
2647 /* Write packet size. */
2648 stream_putw_at(s
, 0, stream_get_endp(s
));
2650 if (IS_ZEBRA_DEBUG_VXLAN
)
2651 zlog_debug("Send VNI_DEL %u to %s", vni
,
2652 zebra_route_string(client
->proto
));
2654 client
->vnidel_cnt
++;
2655 return zebra_server_send_message(client
);
2659 * Build the VNI hash table by going over the VxLAN interfaces. This
2660 * is called when EVPN (advertise-all-vni) is enabled.
2662 static void zvni_build_hash_table()
2664 struct zebra_ns
*zns
;
2665 struct route_node
*rn
;
2666 struct interface
*ifp
;
2668 /* Walk VxLAN interfaces and create VNI hash. */
2669 zns
= zebra_ns_lookup(NS_DEFAULT
);
2670 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2672 zebra_vni_t
*zvni
= NULL
;
2673 zebra_l3vni_t
*zl3vni
= NULL
;
2674 struct zebra_if
*zif
;
2675 struct zebra_l2info_vxlan
*vxl
;
2677 ifp
= (struct interface
*)rn
->info
;
2681 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2684 vxl
= &zif
->l2info
.vxl
;
2687 /* L3-VNI and L2-VNI are handled seperately */
2688 zl3vni
= zl3vni_lookup(vni
);
2691 if (IS_ZEBRA_DEBUG_VXLAN
)
2692 zlog_debug("create L3-VNI hash for Intf %s(%u) L3-VNI %u",
2693 ifp
->name
, ifp
->ifindex
, vni
);
2695 /* associate with vxlan_if */
2696 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
2697 zl3vni
->vxlan_if
= ifp
;
2700 * we need to associate with SVI.
2701 * we can associate with svi-if only after association
2702 * with vxlan-intf is complete
2704 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
2706 if (is_l3vni_oper_up(zl3vni
))
2707 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
2710 struct interface
*vlan_if
= NULL
;
2712 if (IS_ZEBRA_DEBUG_VXLAN
)
2714 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
2715 ifp
->name
, ifp
->ifindex
, vni
,
2716 inet_ntoa(vxl
->vtep_ip
));
2718 /* VNI hash entry is not expected to exist. */
2719 zvni
= zvni_lookup(vni
);
2722 "VNI hash already present for IF %s(%u) L2-VNI %u",
2723 ifp
->name
, ifp
->ifindex
, vni
);
2727 zvni
= zvni_add(vni
);
2730 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
2731 ifp
->name
, ifp
->ifindex
, vni
);
2735 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
2736 zvni
->vxlan_if
= ifp
;
2737 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
2738 zif
->brslave_info
.br_if
);
2740 zvni
->vrf_id
= vlan_if
->vrf_id
;
2741 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
2743 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
2747 /* Inform BGP if intf is up and mapped to bridge. */
2748 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
2749 zvni_send_add_to_client(zvni
);
2755 * See if remote VTEP matches with prefix.
2757 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
2759 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
2763 * Locate remote VTEP in VNI hash table.
2765 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2767 zebra_vtep_t
*zvtep
;
2772 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2773 if (zvni_vtep_match(vtep_ip
, zvtep
))
2781 * Add remote VTEP to VNI hash table.
2783 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2785 zebra_vtep_t
*zvtep
;
2787 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
2789 zlog_err("Failed to alloc VTEP entry, VNI %u", zvni
->vni
);
2793 zvtep
->vtep_ip
= *vtep_ip
;
2796 zvni
->vteps
->prev
= zvtep
;
2797 zvtep
->next
= zvni
->vteps
;
2798 zvni
->vteps
= zvtep
;
2804 * Remove remote VTEP from VNI hash table.
2806 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
2809 zvtep
->next
->prev
= zvtep
->prev
;
2811 zvtep
->prev
->next
= zvtep
->next
;
2813 zvni
->vteps
= zvtep
->next
;
2815 zvtep
->prev
= zvtep
->next
= NULL
;
2816 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
2822 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
2823 * uninstall from kernel if asked to.
2825 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
2827 zebra_vtep_t
*zvtep
, *zvtep_next
;
2832 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
2833 zvtep_next
= zvtep
->next
;
2835 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
2836 zvni_vtep_del(zvni
, zvtep
);
2843 * Install remote VTEP into the kernel.
2845 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2847 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
2851 * Uninstall remote VTEP from the kernel.
2853 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2855 if (!zvni
->vxlan_if
) {
2856 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2861 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
2865 * Cleanup VNI/VTEP and update kernel
2867 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
2869 zebra_vni_t
*zvni
= NULL
;
2870 zebra_l3vni_t
*zl3vni
= NULL
;
2871 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
2873 zvni
= (zebra_vni_t
*)backet
->data
;
2877 /* remove from l3-vni list */
2879 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
2881 listnode_delete(zl3vni
->l2vnis
, zvni
);
2883 /* Free up all neighbors and MACs, if any. */
2884 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
2885 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
2887 /* Free up all remote VTEPs, if any. */
2888 zvni_vtep_del_all(zvni
, 1);
2890 /* Delete the hash entry. */
2895 static void zl3vni_cleanup_all(struct hash_backet
*backet
,
2898 zebra_l3vni_t
*zl3vni
= NULL
;
2900 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
2904 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
2907 static int is_host_present_in_host_list(struct list
*list
,
2908 struct prefix
*host
)
2910 struct listnode
*node
= NULL
;
2911 struct prefix
*p
= NULL
;
2913 for (ALL_LIST_ELEMENTS_RO(list
, node
, p
)) {
2914 if (prefix_same(p
, host
))
2920 static void host_list_add_host(struct list
*list
,
2921 struct prefix
*host
)
2923 struct prefix
*p
= NULL
;
2925 p
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct prefix
));
2926 memcpy(p
, host
, sizeof(struct prefix
));
2928 listnode_add_sort(list
, p
);
2931 static void host_list_delete_host(struct list
*list
,
2932 struct prefix
*host
)
2934 struct listnode
*node
= NULL
, *nnode
= NULL
, *node_to_del
= NULL
;
2935 struct prefix
*p
= NULL
;
2937 for (ALL_LIST_ELEMENTS(list
, node
, nnode
, p
)) {
2938 if (prefix_same(p
, host
)) {
2939 XFREE(MTYPE_HOST_PREFIX
, p
);
2945 list_delete_node(list
, node_to_del
);
2949 * Look up MAC hash entry.
2951 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
2952 struct ethaddr
*rmac
)
2957 memset(&tmp
, 0, sizeof(tmp
));
2958 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
2959 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
2965 * Callback to allocate RMAC hash entry.
2967 static void *zl3vni_rmac_alloc(void *p
)
2969 const zebra_mac_t
*tmp_rmac
= p
;
2972 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2975 return ((void *)zrmac
);
2979 * Add RMAC entry to l3-vni
2981 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
2982 struct ethaddr
*rmac
)
2984 zebra_mac_t tmp_rmac
;
2985 zebra_mac_t
*zrmac
= NULL
;
2987 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
2988 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
2989 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
2992 zrmac
->host_list
= list_new();
2993 zrmac
->host_list
->cmp
= (int (*)(void *, void *))prefix_cmp
;
2995 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
2996 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
3004 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
,
3007 zebra_mac_t
*tmp_rmac
;
3009 if (zrmac
->host_list
)
3010 list_delete_and_null(&zrmac
->host_list
);
3011 zrmac
->host_list
= NULL
;
3013 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
3015 XFREE(MTYPE_MAC
, tmp_rmac
);
3021 * Install remote RMAC into the kernel.
3023 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
,
3026 struct zebra_if
*zif
= NULL
;
3027 struct zebra_l2info_vxlan
*vxl
= NULL
;
3029 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
)) ||
3030 !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3033 zif
= zl3vni
->vxlan_if
->info
;
3037 vxl
= &zif
->l2info
.vxl
;
3039 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3041 zrmac
->fwd_info
.r_vtep_ip
, 0);
3045 * Uninstall remote RMAC from the kernel.
3047 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
,
3050 char buf
[ETHER_ADDR_STRLEN
];
3051 struct zebra_if
*zif
= NULL
;
3052 struct zebra_l2info_vxlan
*vxl
= NULL
;
3054 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
)) ||
3055 !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3058 if (!zl3vni
->vxlan_if
) {
3060 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
3061 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
3062 zl3vni
->vni
, zl3vni
);
3066 zif
= zl3vni
->vxlan_if
->info
;
3070 vxl
= &zif
->l2info
.vxl
;
3072 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3073 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3076 /* handle rmac add */
3077 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
,
3078 struct ethaddr
*rmac
,
3079 struct ipaddr
*vtep_ip
,
3080 struct prefix
*host_prefix
)
3082 char buf
[ETHER_ADDR_STRLEN
];
3083 char buf1
[INET6_ADDRSTRLEN
];
3084 zebra_mac_t
*zrmac
= NULL
;
3086 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3089 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
3092 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
3093 prefix_mac2str(rmac
, buf
,
3095 zl3vni
->vni
, ipaddr2str(vtep_ip
, buf1
,
3099 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
3100 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
3102 /* install rmac in kernel */
3103 zl3vni_rmac_install(zl3vni
, zrmac
);
3106 if (!is_host_present_in_host_list(zrmac
->host_list
, host_prefix
))
3107 host_list_add_host(zrmac
->host_list
, host_prefix
);
3112 /* handle rmac delete */
3113 static int zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
,
3114 struct ethaddr
*rmac
,
3115 struct prefix
*host_prefix
)
3117 zebra_mac_t
*zrmac
= NULL
;
3119 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3123 host_list_delete_host(zrmac
->host_list
, host_prefix
);
3124 if (list_isempty(zrmac
->host_list
)) {
3126 /* uninstall from kernel */
3127 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3129 /* del the rmac entry */
3130 zl3vni_rmac_del(zl3vni
, zrmac
);
3136 * Look up nh hash entry on a l3-vni.
3138 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
3144 memset(&tmp
, 0, sizeof(tmp
));
3145 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
3146 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
3153 * Callback to allocate NH hash entry on L3-VNI.
3155 static void *zl3vni_nh_alloc(void *p
)
3157 const zebra_neigh_t
*tmp_n
= p
;
3160 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
3167 * Add neighbor entry.
3169 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
3171 struct ethaddr
*mac
)
3173 zebra_neigh_t tmp_n
;
3174 zebra_neigh_t
*n
= NULL
;
3176 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
3177 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
3178 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
3181 n
->host_list
= list_new();
3182 n
->host_list
->cmp
= (int (*)(void *, void *))prefix_cmp
;
3184 memcpy(&n
->emac
, mac
, ETH_ALEN
);
3185 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3186 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
3192 * Delete neighbor entry.
3194 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
,
3197 zebra_neigh_t
*tmp_n
;
3200 list_delete_and_null(&n
->host_list
);
3201 n
->host_list
= NULL
;
3203 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
3205 XFREE(MTYPE_NEIGH
, tmp_n
);
3211 * Install remote nh as neigh into the kernel.
3213 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
,
3216 if (!is_l3vni_oper_up(zl3vni
))
3219 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
) ||
3220 !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3223 return kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
);
3227 * Uninstall remote nh from the kernel.
3229 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
,
3232 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
) ||
3233 !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3236 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
3239 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
3242 /* add remote vtep as a neigh entry */
3243 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
,
3244 struct ipaddr
*vtep_ip
,
3245 struct ethaddr
*rmac
,
3246 struct prefix
*host_prefix
)
3248 char buf
[ETHER_ADDR_STRLEN
];
3249 char buf1
[INET6_ADDRSTRLEN
];
3250 zebra_neigh_t
*nh
= NULL
;
3252 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3254 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
3258 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
3259 ipaddr2str(vtep_ip
, buf1
,
3261 prefix_mac2str(rmac
, buf
,
3267 /* install the nh neigh in kernel */
3268 zl3vni_nh_install(zl3vni
, nh
);
3271 if (!is_host_present_in_host_list(nh
->host_list
, host_prefix
))
3272 host_list_add_host(nh
->host_list
, host_prefix
);
3277 /* handle nh neigh delete */
3278 static int zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
,
3279 struct ipaddr
*vtep_ip
,
3280 struct prefix
*host_prefix
)
3282 zebra_neigh_t
*nh
= NULL
;
3284 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3288 host_list_delete_host(nh
->host_list
, host_prefix
);
3289 if (list_isempty(nh
->host_list
)) {
3291 /* uninstall from kernel */
3292 zl3vni_nh_uninstall(zl3vni
, nh
);
3294 /* delete the nh entry */
3295 zl3vni_nh_del(zl3vni
, nh
);
3301 /* handle neigh update from kernel - the only thing of interest is to
3302 * readd stale entries.
3304 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
,
3305 struct ipaddr
*ip
, u_int16_t state
)
3308 zebra_neigh_t
*n
= NULL
;
3310 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3314 /* all next hop neigh are remote and installed by frr.
3315 * If the kernel has aged this entry, re-install.
3317 if (state
& NUD_STALE
)
3318 zl3vni_nh_install(zl3vni
, n
);
3323 /* handle neigh delete from kernel */
3324 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
,
3327 zebra_neigh_t
*n
= NULL
;
3329 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3333 /* all next hop neigh are remote and installed by frr.
3334 * If we get an age out notification for these neigh entries, we have to
3337 zl3vni_nh_install(zl3vni
, n
);
3343 * Hash function for L3 VNI.
3345 static unsigned int l3vni_hash_keymake(void *p
)
3347 const zebra_l3vni_t
*zl3vni
= p
;
3349 return jhash_1word(zl3vni
->vni
, 0);
3353 * Compare 2 L3 VNI hash entries.
3355 static int l3vni_hash_cmp(const void *p1
, const void *p2
)
3357 const zebra_l3vni_t
*zl3vni1
= p1
;
3358 const zebra_l3vni_t
*zl3vni2
= p2
;
3360 return (zl3vni1
->vni
== zl3vni2
->vni
);
3364 * Callback to allocate L3 VNI hash entry.
3366 static void *zl3vni_alloc(void *p
)
3368 zebra_l3vni_t
*zl3vni
= NULL
;
3369 const zebra_l3vni_t
*tmp_l3vni
= p
;
3371 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
3372 zl3vni
->vni
= tmp_l3vni
->vni
;
3373 return ((void *)zl3vni
);
3377 * Look up L3 VNI hash entry.
3379 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
3381 struct zebra_ns
*zns
;
3382 zebra_l3vni_t tmp_l3vni
;
3383 zebra_l3vni_t
*zl3vni
= NULL
;
3385 zns
= zebra_ns_lookup(NS_DEFAULT
);
3387 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
3388 tmp_l3vni
.vni
= vni
;
3389 zl3vni
= hash_lookup(zns
->l3vni_table
, &tmp_l3vni
);
3395 * Add L3 VNI hash entry.
3397 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
3399 zebra_l3vni_t tmp_zl3vni
;
3400 struct zebra_ns
*zns
= NULL
;
3401 zebra_l3vni_t
*zl3vni
= NULL
;
3403 zns
= zebra_ns_lookup(NS_DEFAULT
);
3406 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
3407 tmp_zl3vni
.vni
= vni
;
3409 zl3vni
= hash_get(zns
->l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
3412 zl3vni
->vrf_id
= vrf_id
;
3413 zl3vni
->svi_if
= NULL
;
3414 zl3vni
->vxlan_if
= NULL
;
3415 zl3vni
->l2vnis
= list_new();
3416 zl3vni
->l2vnis
->cmp
= (int (*)(void *, void *))vni_hash_cmp
;
3418 /* Create hash table for remote RMAC */
3419 zl3vni
->rmac_table
=
3420 hash_create(mac_hash_keymake
, mac_cmp
,
3421 "Zebra L3-VNI RMAC-Table");
3423 /* Create hash table for neighbors */
3424 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3425 "Zebra L3-VNI next-hop table");
3431 * Delete L3 VNI hash entry.
3433 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
3435 struct zebra_ns
*zns
;
3436 zebra_l3vni_t
*tmp_zl3vni
;
3438 zns
= zebra_ns_lookup(NS_DEFAULT
);
3441 /* free the list of l2vnis */
3442 list_delete_and_null(&zl3vni
->l2vnis
);
3443 zl3vni
->l2vnis
= NULL
;
3445 /* Free the rmac table */
3446 hash_free(zl3vni
->rmac_table
);
3447 zl3vni
->rmac_table
= NULL
;
3449 /* Free the nh table */
3450 hash_free(zl3vni
->nh_table
);
3451 zl3vni
->nh_table
= NULL
;
3453 /* Free the VNI hash entry and allocated memory. */
3454 tmp_zl3vni
= hash_release(zns
->l3vni_table
, zl3vni
);
3456 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
3461 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
3463 struct zebra_ns
*zns
= NULL
;
3464 struct route_node
*rn
= NULL
;
3465 struct interface
*ifp
= NULL
;
3467 /* loop through all vxlan-interface */
3468 zns
= zebra_ns_lookup(NS_DEFAULT
);
3469 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3471 struct zebra_if
*zif
= NULL
;
3472 struct zebra_l2info_vxlan
*vxl
= NULL
;
3474 ifp
= (struct interface
*)rn
->info
;
3479 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3482 vxl
= &zif
->l2info
.vxl
;
3483 if (vxl
->vni
== zl3vni
->vni
) {
3484 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3492 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
3494 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
3495 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
3500 if (!zl3vni
->vxlan_if
)
3503 zif
= zl3vni
->vxlan_if
->info
;
3507 vxl
= &zif
->l2info
.vxl
;
3509 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3512 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
3514 struct zebra_vrf
*zvrf
= NULL
;
3516 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
3520 return zl3vni_lookup(zvrf
->l3vni
);
3524 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3525 * neighbor notifications, to see if they are of interest.
3527 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
3528 struct interface
*br_if
)
3532 u_char bridge_vlan_aware
= 0;
3533 zebra_l3vni_t
*zl3vni
= NULL
;
3534 struct zebra_ns
*zns
= NULL
;
3535 struct route_node
*rn
= NULL
;
3536 struct zebra_if
*zif
= NULL
;
3537 struct interface
*tmp_if
= NULL
;
3538 struct zebra_l2info_bridge
*br
= NULL
;
3539 struct zebra_l2info_vxlan
*vxl
= NULL
;
3544 /* Make sure the linked interface is a bridge. */
3545 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3548 /* Determine if bridge is VLAN-aware or not */
3551 br
= &zif
->l2info
.br
;
3552 bridge_vlan_aware
= br
->vlan_aware
;
3553 if (bridge_vlan_aware
) {
3554 struct zebra_l2info_vlan
*vl
;
3556 if (!IS_ZEBRA_IF_VLAN(ifp
))
3561 vl
= &zif
->l2info
.vl
;
3565 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3566 /* TODO: Optimize with a hash. */
3567 zns
= zebra_ns_lookup(NS_DEFAULT
);
3568 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3569 tmp_if
= (struct interface
*)rn
->info
;
3573 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3575 if (!if_is_operative(tmp_if
))
3577 vxl
= &zif
->l2info
.vxl
;
3579 if (zif
->brslave_info
.br_if
!= br_if
)
3582 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3591 zl3vni
= zl3vni_lookup(vxl
->vni
);
3596 * Inform BGP about l3-vni.
3598 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
3600 struct stream
*s
= NULL
;
3601 struct zserv
*client
= NULL
;
3602 struct ethaddr rmac
;
3603 char buf
[ETHER_ADDR_STRLEN
];
3605 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
3606 /* BGP may not be running. */
3611 memset(&rmac
, 0, sizeof(struct ethaddr
));
3612 zl3vni_get_rmac(zl3vni
, &rmac
);
3617 zclient_create_header(s
, ZEBRA_L3VNI_ADD
,
3618 zl3vni_vrf_id(zl3vni
));
3619 stream_putl(s
, zl3vni
->vni
);
3620 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
3621 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
3622 stream_put(s
, &zl3vni
->filter
, sizeof(int));
3624 /* Write packet size. */
3625 stream_putw_at(s
, 0, stream_get_endp(s
));
3627 if (IS_ZEBRA_DEBUG_VXLAN
)
3629 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
3630 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3631 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
3632 inet_ntoa(zl3vni
->local_vtep_ip
),
3633 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ?
3634 "prefix-routes-only" : "none",
3635 zebra_route_string(client
->proto
));
3637 client
->l3vniadd_cnt
++;
3638 return zebra_server_send_message(client
);
3642 * Inform BGP about local l3-VNI deletion.
3644 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
3646 struct stream
*s
= NULL
;
3647 struct zserv
*client
= NULL
;
3649 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
3650 /* BGP may not be running. */
3657 zclient_create_header(s
, ZEBRA_L3VNI_DEL
,
3658 zl3vni_vrf_id(zl3vni
));
3659 stream_putl(s
, zl3vni
->vni
);
3661 /* Write packet size. */
3662 stream_putw_at(s
, 0, stream_get_endp(s
));
3664 if (IS_ZEBRA_DEBUG_VXLAN
)
3665 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s",
3667 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3668 zebra_route_string(client
->proto
));
3670 client
->l3vnidel_cnt
++;
3671 return zebra_server_send_message(client
);
3674 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
3679 /* send l3vni add to BGP */
3680 zl3vni_send_add_to_client(zl3vni
);
3683 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
3688 /* send l3-vni del to BGP*/
3689 zl3vni_send_del_to_client(zl3vni
);
3692 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
,
3695 zebra_vni_t
*zvni
= (zebra_vni_t
*) backet
->data
;
3696 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*) ctxt
;
3698 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
3699 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3703 * handle transition of vni from l2 to l3 and vice versa
3705 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
,
3708 zebra_vni_t
*zvni
= NULL
;
3710 /* There is a possibility that VNI notification was already received
3711 * from kernel and we programmed it as L2-VNI
3712 * In such a case we need to delete this L2-VNI first, so
3713 * that it can be reprogrammed as L3-VNI in the system. It is also
3714 * possible that the vrf-vni mapping is removed from FRR while the vxlan
3715 * interface is still present in kernel. In this case to keep it
3716 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
3719 /* Locate hash entry */
3720 zvni
= zvni_lookup(vni
);
3724 if (IS_ZEBRA_DEBUG_VXLAN
)
3725 zlog_debug("Del L2-VNI %u - transition to L3-VNI",
3728 /* Delete VNI from BGP. */
3729 zvni_send_del_to_client(zvni
->vni
);
3731 /* Free up all neighbors and MAC, if any. */
3732 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
3733 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
3735 /* Free up all remote VTEPs, if any. */
3736 zvni_vtep_del_all(zvni
, 0);
3738 /* Delete the hash entry. */
3739 if (zvni_del(zvni
)) {
3740 zlog_err("Failed to del VNI hash %p, VNI %u",
3745 /* TODO_MITESH: This needs to be thought through. We don't have
3746 * enough information at this point to reprogram the vni as
3747 * l2-vni. One way is to store the required info in l3-vni and
3748 * used it solely for this purpose
3755 /* delete and uninstall rmac hash entry */
3756 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
,
3759 zebra_mac_t
*zrmac
= NULL
;
3760 zebra_l3vni_t
*zl3vni
= NULL
;
3762 zrmac
= (zebra_mac_t
*)backet
->data
;
3763 zl3vni
= (zebra_l3vni_t
*)ctx
;
3764 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3765 zl3vni_rmac_del(zl3vni
, zrmac
);
3768 /* delete and uninstall nh hash entry */
3769 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
,
3772 zebra_neigh_t
*n
= NULL
;
3773 zebra_l3vni_t
*zl3vni
= NULL
;
3775 n
= (zebra_neigh_t
*)backet
->data
;
3776 zl3vni
= (zebra_l3vni_t
*)ctx
;
3777 zl3vni_nh_uninstall(zl3vni
, n
);
3778 zl3vni_nh_del(zl3vni
, n
);
3781 static int ip_prefix_send_to_client(vrf_id_t vrf_id
,
3785 struct zserv
*client
= NULL
;
3786 struct stream
*s
= NULL
;
3787 char buf
[PREFIX_STRLEN
];
3789 client
= zebra_find_client(ZEBRA_ROUTE_BGP
, 0);
3790 /* BGP may not be running. */
3797 zclient_create_header(s
, cmd
, vrf_id
);
3798 stream_put(s
, p
, sizeof(struct prefix
));
3800 /* Write packet size. */
3801 stream_putw_at(s
, 0, stream_get_endp(s
));
3803 if (IS_ZEBRA_DEBUG_VXLAN
)
3805 "Send ip prefix %s %s on vrf %s",
3806 prefix2str(p
, buf
, sizeof(buf
)),
3807 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
3808 vrf_id_to_name(vrf_id
));
3810 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
3811 client
->prefixadd_cnt
++;
3813 client
->prefixdel_cnt
++;
3815 return zebra_server_send_message(client
);
3818 /* re-add remote rmac if needed */
3819 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
3820 struct ethaddr
*rmac
)
3822 char buf
[ETHER_ADDR_STRLEN
];
3823 zebra_mac_t
*zrmac
= NULL
;
3825 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3829 if (IS_ZEBRA_DEBUG_VXLAN
)
3830 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
3831 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3834 zl3vni_rmac_install(zl3vni
, zrmac
);
3838 /* Public functions */
3840 int is_l3vni_for_prefix_routes_only(vni_t vni
)
3842 zebra_l3vni_t
*zl3vni
= NULL
;
3844 zl3vni
= zl3vni_lookup(vni
);
3848 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
3851 /* handle evpn route in vrf table */
3852 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
,
3853 struct ethaddr
*rmac
,
3854 struct ipaddr
*vtep_ip
,
3855 struct prefix
*host_prefix
)
3857 zebra_l3vni_t
*zl3vni
= NULL
;
3859 zl3vni
= zl3vni_from_vrf(vrf_id
);
3860 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
3863 /* add the next hop neighbor */
3864 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
3867 zl3vni_remote_rmac_add(zl3vni
, rmac
, vtep_ip
, host_prefix
);
3870 /* handle evpn vrf route delete */
3871 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
3872 struct ethaddr
*rmac
,
3873 struct ipaddr
*vtep_ip
,
3874 struct prefix
*host_prefix
)
3876 zebra_l3vni_t
*zl3vni
= NULL
;
3878 zl3vni
= zl3vni_from_vrf(vrf_id
);
3882 /* delete the next hop entry */
3883 zl3vni_remote_nh_del(zl3vni
, vtep_ip
, host_prefix
);
3885 /* delete the rmac entry */
3886 zl3vni_remote_rmac_del(zl3vni
, rmac
, host_prefix
);
3889 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
,
3891 struct ethaddr
*rmac
,
3894 zebra_l3vni_t
*zl3vni
= NULL
;
3895 zebra_mac_t
*zrmac
= NULL
;
3896 json_object
*json
= NULL
;
3898 if (!is_evpn_enabled()) {
3900 vty_out(vty
, "{}\n");
3905 json
= json_object_new_object();
3907 zl3vni
= zl3vni_lookup(l3vni
);
3910 vty_out(vty
, "{}\n");
3912 vty_out(vty
, "%% L3-VNI %u doesnt exist\n",
3917 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3920 vty_out(vty
, "{}\n");
3923 "%% Requested RMAC doesnt exist in L3-VNI %u",
3928 zl3vni_print_rmac(zrmac
, vty
, json
);
3931 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3932 json
, JSON_C_TO_STRING_PRETTY
));
3933 json_object_free(json
);
3937 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
,
3941 zebra_l3vni_t
*zl3vni
;
3942 u_int32_t num_rmacs
;
3943 struct rmac_walk_ctx wctx
;
3944 json_object
*json
= NULL
;
3946 if (!is_evpn_enabled())
3949 zl3vni
= zl3vni_lookup(l3vni
);
3952 vty_out(vty
, "{}\n");
3954 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
3957 num_rmacs
= hashcount(zl3vni
->rmac_table
);
3962 json
= json_object_new_object();
3964 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
3969 "Number of Remote RMACs known for this VNI: %u\n",
3971 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
3973 json_object_int_add(json
, "numRmacs", num_rmacs
);
3975 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
3978 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3979 json
, JSON_C_TO_STRING_PRETTY
));
3980 json_object_free(json
);
3984 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
,
3987 struct zebra_ns
*zns
= NULL
;
3988 json_object
*json
= NULL
;
3991 if (!is_evpn_enabled()) {
3993 vty_out(vty
, "{}\n");
3997 zns
= zebra_ns_lookup(NS_DEFAULT
);
4000 vty_out(vty
, "{}\n");
4005 json
= json_object_new_object();
4009 hash_iterate(zns
->l3vni_table
,
4010 (void (*)(struct hash_backet
*,
4011 void *))zl3vni_print_rmac_hash_all_vni
,
4015 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4016 json
, JSON_C_TO_STRING_PRETTY
));
4017 json_object_free(json
);
4021 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
,
4026 zebra_l3vni_t
*zl3vni
= NULL
;
4027 zebra_neigh_t
*n
= NULL
;
4028 json_object
*json
= NULL
;
4030 if (!is_evpn_enabled()) {
4032 vty_out(vty
, "{}\n");
4037 json
= json_object_new_object();
4039 zl3vni
= zl3vni_lookup(l3vni
);
4042 vty_out(vty
, "{}\n");
4044 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4048 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4051 vty_out(vty
, "{}\n");
4054 "%% Requested next-hop not present for L3-VNI %u",
4059 zl3vni_print_nh(n
, vty
, json
);
4062 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4063 json
, JSON_C_TO_STRING_PRETTY
));
4064 json_object_free(json
);
4068 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
,
4073 struct nh_walk_ctx wctx
;
4074 json_object
*json
= NULL
;
4075 zebra_l3vni_t
*zl3vni
= NULL
;
4077 if (!is_evpn_enabled())
4080 zl3vni
= zl3vni_lookup(l3vni
);
4083 vty_out(vty
, "{}\n");
4085 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4089 num_nh
= hashcount(zl3vni
->nh_table
);
4094 json
= json_object_new_object();
4100 "Number of NH Neighbors known for this VNI: %u\n",
4102 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
4104 json_object_int_add(json
, "numNextHops", num_nh
);
4106 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
4109 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4110 json
, JSON_C_TO_STRING_PRETTY
));
4111 json_object_free(json
);
4115 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
,
4118 struct zebra_ns
*zns
= NULL
;
4119 json_object
*json
= NULL
;
4122 if (!is_evpn_enabled()) {
4124 vty_out(vty
, "{}\n");
4128 zns
= zebra_ns_lookup(NS_DEFAULT
);
4133 json
= json_object_new_object();
4137 hash_iterate(zns
->l3vni_table
,
4138 (void (*)(struct hash_backet
*,
4139 void *))zl3vni_print_nh_hash_all_vni
,
4143 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4144 json
, JSON_C_TO_STRING_PRETTY
));
4145 json_object_free(json
);
4151 * Display L3 VNI information (VTY command handler).
4153 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, u_char use_json
)
4156 json_object
*json
= NULL
;
4157 zebra_l3vni_t
*zl3vni
= NULL
;
4159 if (!is_evpn_enabled()) {
4161 vty_out(vty
, "{}\n");
4165 zl3vni
= zl3vni_lookup(vni
);
4168 vty_out(vty
, "{}\n");
4170 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4175 json
= json_object_new_object();
4179 zl3vni_print(zl3vni
, (void *)args
);
4182 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4183 json
, JSON_C_TO_STRING_PRETTY
));
4184 json_object_free(json
);
4188 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4189 json_object
*json_vrfs
)
4191 char buf
[ETHER_ADDR_STRLEN
];
4192 zebra_l3vni_t
*zl3vni
= NULL
;
4194 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4199 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
4202 zl3vni_vxlan_if_name(zl3vni
),
4203 zl3vni_svi_if_name(zl3vni
),
4204 zl3vni_state2str(zl3vni
),
4205 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4207 json_object
*json_vrf
= NULL
;
4208 json_vrf
= json_object_new_object();
4209 json_object_string_add(json_vrf
, "vrf",
4211 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
4212 json_object_string_add(json_vrf
, "vxlanIntf",
4213 zl3vni_vxlan_if_name(zl3vni
));
4214 json_object_string_add(json_vrf
, "sviIntf",
4215 zl3vni_svi_if_name(zl3vni
));
4216 json_object_string_add(json_vrf
, "state",
4217 zl3vni_state2str(zl3vni
));
4218 json_object_string_add(json_vrf
, "routerMac",
4219 zl3vni_rmac2str(zl3vni
, buf
,
4221 json_object_array_add(json_vrfs
, json_vrf
);
4226 * Display Neighbors for a VNI (VTY command handler).
4228 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4229 vni_t vni
, u_char use_json
)
4232 u_int32_t num_neigh
;
4233 struct neigh_walk_ctx wctx
;
4234 json_object
*json
= NULL
;
4236 if (!is_evpn_enabled())
4238 zvni
= zvni_lookup(vni
);
4241 vty_out(vty
, "{}\n");
4243 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4246 num_neigh
= hashcount(zvni
->neigh_table
);
4251 json
= json_object_new_object();
4253 /* Since we have IPv6 addresses to deal with which can vary widely in
4254 * size, we try to be a bit more elegant in display by first computing
4255 * the maximum width.
4257 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4260 wctx
.addr_width
= 15;
4262 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4266 "Number of ARPs (local and remote) known for this VNI: %u\n",
4268 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
4269 "Type", "MAC", "Remote VTEP");
4271 json_object_int_add(json
, "numArpNd", num_neigh
);
4273 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4275 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4276 json
, JSON_C_TO_STRING_PRETTY
));
4277 json_object_free(json
);
4282 * Display neighbors across all VNIs (VTY command handler).
4284 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4287 json_object
*json
= NULL
;
4290 if (!is_evpn_enabled())
4294 json
= json_object_new_object();
4298 hash_iterate(zvrf
->vni_table
,
4299 (void (*)(struct hash_backet
*,
4300 void *))zvni_print_neigh_hash_all_vni
,
4303 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4304 json
, JSON_C_TO_STRING_PRETTY
));
4305 json_object_free(json
);
4310 * Display specific neighbor for a VNI, if present (VTY command handler).
4312 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
4313 struct zebra_vrf
*zvrf
, vni_t vni
,
4314 struct ipaddr
*ip
, u_char use_json
)
4318 json_object
*json
= NULL
;
4320 if (!is_evpn_enabled())
4322 zvni
= zvni_lookup(vni
);
4325 vty_out(vty
, "{}\n");
4327 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4330 n
= zvni_neigh_lookup(zvni
, ip
);
4334 "%% Requested neighbor does not exist in VNI %u\n",
4339 json
= json_object_new_object();
4341 zvni_print_neigh(n
, vty
, json
);
4344 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4345 json
, JSON_C_TO_STRING_PRETTY
));
4346 json_object_free(json
);
4351 * Display neighbors for a VNI from specific VTEP (VTY command handler).
4352 * By definition, these are remote neighbors.
4354 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4355 vni_t vni
, struct in_addr vtep_ip
,
4359 u_int32_t num_neigh
;
4360 struct neigh_walk_ctx wctx
;
4361 json_object
*json
= NULL
;
4363 if (!is_evpn_enabled())
4365 zvni
= zvni_lookup(vni
);
4368 vty_out(vty
, "{}\n");
4370 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4373 num_neigh
= hashcount(zvni
->neigh_table
);
4377 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4380 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
4381 wctx
.r_vtep_ip
= vtep_ip
;
4383 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4386 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4387 json
, JSON_C_TO_STRING_PRETTY
));
4388 json_object_free(json
);
4393 * Display MACs for a VNI (VTY command handler).
4395 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4396 vni_t vni
, u_char use_json
)
4400 struct mac_walk_ctx wctx
;
4401 json_object
*json
= NULL
;
4402 json_object
*json_mac
= NULL
;
4404 if (!is_evpn_enabled())
4406 zvni
= zvni_lookup(vni
);
4409 vty_out(vty
, "{}\n");
4411 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4414 num_macs
= num_valid_macs(zvni
);
4419 json
= json_object_new_object();
4420 json_mac
= json_object_new_object();
4423 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4426 wctx
.json
= json_mac
;
4430 "Number of MACs (local and remote) known for this VNI: %u\n",
4432 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
4433 "Intf/Remote VTEP", "VLAN");
4435 json_object_int_add(json
, "numMacs", num_macs
);
4437 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4440 json_object_object_add(json
, "macs", json_mac
);
4441 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4442 json
, JSON_C_TO_STRING_PRETTY
));
4443 json_object_free(json
);
4448 * Display MACs for all VNIs (VTY command handler).
4450 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4453 struct mac_walk_ctx wctx
;
4454 json_object
*json
= NULL
;
4456 if (!is_evpn_enabled()) {
4458 vty_out(vty
, "{}\n");
4462 json
= json_object_new_object();
4464 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4467 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4470 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4471 json
, JSON_C_TO_STRING_PRETTY
));
4472 json_object_free(json
);
4477 * Display MACs for all VNIs (VTY command handler).
4479 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
4480 struct zebra_vrf
*zvrf
,
4481 struct in_addr vtep_ip
,
4484 struct mac_walk_ctx wctx
;
4485 json_object
*json
= NULL
;
4487 if (!is_evpn_enabled())
4491 json
= json_object_new_object();
4493 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4495 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4496 wctx
.r_vtep_ip
= vtep_ip
;
4498 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4501 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4502 json
, JSON_C_TO_STRING_PRETTY
));
4503 json_object_free(json
);
4508 * Display specific MAC for a VNI, if present (VTY command handler).
4510 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4511 vni_t vni
, struct ethaddr
*macaddr
)
4516 if (!is_evpn_enabled())
4518 zvni
= zvni_lookup(vni
);
4520 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4523 mac
= zvni_mac_lookup(zvni
, macaddr
);
4525 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
4530 zvni_print_mac(mac
, vty
);
4534 * Display MACs for a VNI from specific VTEP (VTY command handler).
4536 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4537 vni_t vni
, struct in_addr vtep_ip
,
4542 struct mac_walk_ctx wctx
;
4543 json_object
*json
= NULL
;
4544 json_object
*json_mac
= NULL
;
4546 if (!is_evpn_enabled())
4548 zvni
= zvni_lookup(vni
);
4551 vty_out(vty
, "{}\n");
4553 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4556 num_macs
= num_valid_macs(zvni
);
4561 json
= json_object_new_object();
4562 json_mac
= json_object_new_object();
4565 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4568 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4569 wctx
.r_vtep_ip
= vtep_ip
;
4570 wctx
.json
= json_mac
;
4571 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4574 json_object_int_add(json
, "numMacs", wctx
.count
);
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
);
4585 * Display VNI information (VTY command handler).
4587 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
4590 json_object
*json
= NULL
;
4592 zebra_l3vni_t
*zl3vni
= NULL
;
4593 zebra_vni_t
*zvni
= NULL
;
4595 if (!is_evpn_enabled())
4599 json
= json_object_new_object();
4603 zl3vni
= zl3vni_lookup(vni
);
4605 zl3vni_print(zl3vni
, (void *)args
);
4607 zvni
= zvni_lookup(vni
);
4610 vty_out(vty
, "{}\n");
4612 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4616 zvni_print(zvni
, (void *)args
);
4620 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4621 json
, JSON_C_TO_STRING_PRETTY
));
4622 json_object_free(json
);
4626 /* Display all global details for EVPN */
4627 void zebra_vxlan_print_evpn(struct vty
*vty
, u_char uj
)
4632 json_object
*json
= NULL
;
4633 struct zebra_ns
*zns
= NULL
;
4634 struct zebra_vrf
*zvrf
= NULL
;
4636 if (!is_evpn_enabled())
4639 zns
= zebra_ns_lookup(NS_DEFAULT
);
4643 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
4647 num_l3vnis
= hashcount(zns
->l3vni_table
);
4648 num_l2vnis
= hashcount(zvrf
->vni_table
);
4649 num_vnis
= num_l2vnis
+ num_l3vnis
;
4652 json
= json_object_new_object();
4653 json_object_string_add(json
, "advertiseGatewayMacip",
4654 zvrf
->advertise_gw_macip
? "Yes" : "No");
4655 json_object_int_add(json
, "numVnis", num_vnis
);
4656 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4657 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4659 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
4660 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
4661 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
4662 zvrf
->advertise_gw_macip
? "Yes" : "No");
4666 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4667 json
, JSON_C_TO_STRING_PRETTY
));
4668 json_object_free(json
);
4673 * Display VNI hash table (VTY command handler).
4675 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4678 json_object
*json
= NULL
;
4679 struct zebra_ns
*zns
= NULL
;
4682 if (!is_evpn_enabled())
4685 zns
= zebra_ns_lookup(NS_DEFAULT
);
4691 json
= json_object_new_object();
4694 "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n",
4695 "VNI", "Type", "VxLAN IF", "# MACs",
4696 "# ARPs", "# Remote VTEPs", "Tenant VRF");
4701 /* Display all L2-VNIs */
4702 hash_iterate(zvrf
->vni_table
,
4703 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
4706 /* Display all L3-VNIs */
4707 hash_iterate(zns
->l3vni_table
,
4708 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
4712 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4713 json
, JSON_C_TO_STRING_PRETTY
));
4714 json_object_free(json
);
4719 * Handle neighbor delete (on a VLAN device / L3 interface) from the
4720 * kernel. This may result in either the neighbor getting deleted from
4721 * our database or being re-added to the kernel (if it is a valid
4724 int zebra_vxlan_local_neigh_del(struct interface
*ifp
,
4725 struct interface
*link_if
, struct ipaddr
*ip
)
4727 char buf
[INET6_ADDRSTRLEN
];
4728 char buf2
[ETHER_ADDR_STRLEN
];
4729 zebra_neigh_t
*n
= NULL
;
4730 zebra_vni_t
*zvni
= NULL
;
4731 zebra_mac_t
*zmac
= NULL
;
4732 zebra_l3vni_t
*zl3vni
= NULL
;
4734 /* check if this is a remote neigh entry corresponding to remote
4737 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4739 return zl3vni_local_nh_del(zl3vni
, ip
);
4741 /* We are only interested in neighbors on an SVI that resides on top
4742 * of a VxLAN bridge.
4744 zvni
= zvni_from_svi(ifp
, link_if
);
4748 if (!zvni
->vxlan_if
) {
4750 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
4755 if (IS_ZEBRA_DEBUG_VXLAN
)
4756 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
4757 ipaddr2str(ip
, buf
, sizeof(buf
)),
4758 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
4760 /* If entry doesn't exist, nothing to do. */
4761 n
= zvni_neigh_lookup(zvni
, ip
);
4765 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
4767 if (IS_ZEBRA_DEBUG_VXLAN
)
4769 "Trying to del a neigh %s without a mac %s on VNI %u",
4770 ipaddr2str(ip
, buf
, sizeof(buf
)),
4771 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
4777 /* If it is a remote entry, the kernel has aged this out or someone has
4778 * deleted it, it needs to be re-installed as Quagga is the owner.
4780 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
4781 zvni_neigh_install(zvni
, n
);
4785 /* Remove neighbor from BGP. */
4786 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
4787 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
4790 /* Delete this neighbor entry. */
4791 zvni_neigh_del(zvni
, n
);
4793 /* see if the AUTO mac needs to be deleted */
4794 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
4795 && !listcount(zmac
->neigh_list
))
4796 zvni_mac_del(zvni
, zmac
);
4802 * Handle neighbor add or update (on a VLAN device / L3 interface)
4805 int zebra_vxlan_local_neigh_add_update(struct interface
*ifp
,
4806 struct interface
*link_if
,
4808 struct ethaddr
*macaddr
, u_int16_t state
,
4811 char buf
[ETHER_ADDR_STRLEN
];
4812 char buf2
[INET6_ADDRSTRLEN
];
4813 zebra_vni_t
*zvni
= NULL
;
4814 zebra_neigh_t
*n
= NULL
;
4815 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
4816 zebra_l3vni_t
*zl3vni
= NULL
;
4818 /* check if this is a remote neigh entry corresponding to remote
4821 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4823 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
4825 /* We are only interested in neighbors on an SVI that resides on top
4826 * of a VxLAN bridge.
4828 zvni
= zvni_from_svi(ifp
, link_if
);
4832 if (IS_ZEBRA_DEBUG_VXLAN
)
4834 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u",
4835 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
4836 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
4837 ifp
->ifindex
, state
, ext_learned
? "ext-learned " : "",
4840 /* create a dummy MAC if the MAC is not already present */
4841 zmac
= zvni_mac_lookup(zvni
, macaddr
);
4843 if (IS_ZEBRA_DEBUG_VXLAN
)
4845 "AUTO MAC %s created for neigh %s on VNI %u",
4846 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4847 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
4849 zmac
= zvni_mac_add(zvni
, macaddr
);
4851 zlog_warn("Failed to add MAC %s VNI %u",
4852 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4857 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
4858 memset(&zmac
->flags
, 0, sizeof(u_int32_t
));
4859 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
4862 /* If same entry already exists, it might be a change or it might be a
4863 * move from remote to local.
4865 n
= zvni_neigh_lookup(zvni
, ip
);
4867 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
4868 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
4871 /* Update any params and return - client doesn't
4872 * care about a purely local change.
4874 n
->ifindex
= ifp
->ifindex
;
4878 /* If the MAC has changed,
4879 * need to issue a delete first
4880 * as this means a different MACIP route.
4881 * Also, need to do some unlinking/relinking.
4883 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
4885 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
4887 listnode_delete(old_zmac
->neigh_list
, n
);
4888 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
4891 /* Set "local" forwarding info. */
4892 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
4893 n
->ifindex
= ifp
->ifindex
;
4894 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
4896 /* Link to new MAC */
4897 listnode_add_sort(zmac
->neigh_list
, n
);
4898 } else if (ext_learned
)
4899 /* The neighbor is remote and that is the notification we got.
4902 /* TODO: Evaluate if we need to do anything here. */
4905 /* Neighbor has moved from remote to local. */
4907 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4908 n
->r_vtep_ip
.s_addr
= 0;
4909 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
4910 n
->ifindex
= ifp
->ifindex
;
4913 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
4916 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
4917 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
4918 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4919 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
4922 /* Set "local" forwarding info. */
4923 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
4924 n
->ifindex
= ifp
->ifindex
;
4927 /* Before we program this in BGP, we need to check if MAC is locally
4929 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
4930 if (IS_ZEBRA_DEBUG_VXLAN
)
4932 "Skipping neigh %s add to client as MAC %s is not local on VNI %u",
4933 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
4934 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4941 if (IS_ZEBRA_DEBUG_VXLAN
)
4942 zlog_debug("neigh %s (MAC %s) is now ACTIVE on L2-VNI %u",
4943 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
4944 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4946 ZEBRA_NEIGH_SET_ACTIVE(n
);
4948 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, n
->flags
);
4953 * Handle message from client to delete a remote MACIP for a VNI.
4955 int zebra_vxlan_remote_macip_del(struct zserv
*client
, u_short length
,
4956 struct zebra_vrf
*zvrf
)
4960 struct ethaddr macaddr
;
4962 struct in_addr vtep_ip
;
4966 u_short l
= 0, ipa_len
;
4967 char buf
[ETHER_ADDR_STRLEN
];
4968 char buf1
[INET6_ADDRSTRLEN
];
4969 struct interface
*ifp
= NULL
;
4970 struct zebra_if
*zif
= NULL
;
4972 memset(&macaddr
, 0, sizeof(struct ethaddr
));
4973 memset(&ip
, 0, sizeof(struct ipaddr
));
4974 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
4978 while (l
< length
) {
4979 /* Obtain each remote MACIP and process. */
4980 /* Message contains VNI, followed by MAC followed by IP (if any)
4981 * followed by remote VTEP IP.
4985 memset(&ip
, 0, sizeof(ip
));
4986 STREAM_GETL(s
, vni
);
4987 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
4988 STREAM_GETL(s
, ipa_len
);
4990 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
4992 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
4994 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
4995 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
4996 l
+= IPV4_MAX_BYTELEN
;
4998 if (IS_ZEBRA_DEBUG_VXLAN
)
5000 "Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
5001 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5002 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5004 zebra_route_string(client
->proto
));
5006 /* Locate VNI hash entry - expected to exist. */
5007 zvni
= zvni_lookup(vni
);
5009 if (IS_ZEBRA_DEBUG_VXLAN
)
5011 "Failed to locate VNI hash upon remote MACIP DEL, "
5016 ifp
= zvni
->vxlan_if
;
5019 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
5025 /* If down or not mapped to a bridge, we're done. */
5026 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5029 /* The remote VTEP specified is normally expected to exist, but
5031 * possible that the peer may delete the VTEP before deleting
5033 * referring to the VTEP, in which case the handler (see
5035 * would have already deleted the MACs.
5037 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5040 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5042 n
= zvni_neigh_lookup(zvni
, &ip
);
5046 "Failed to locate MAC %s for neigh %s VNI %u",
5047 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5048 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5052 /* If the remote mac or neighbor doesn't exist there is nothing
5054 * to do. Otherwise, uninstall the entry and then remove it.
5059 /* Ignore the delete if this mac is a gateway mac-ip */
5060 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
) &&
5061 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5062 zlog_err("%u: Ignore Del for MAC %s neigh %s on VNI %u as it is configured as a default gateway",
5064 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5065 ipaddr2str(&ip
, buf1
, sizeof(buf1
)),
5070 /* Uninstall remote neighbor or MAC. */
5072 /* When the MAC changes for an IP, it is possible the
5074 * update the new MAC before trying to delete the "old"
5076 * (as these are two different MACIP routes). Do the
5078 * if the MAC matches.
5080 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5081 && (memcmp(n
->emac
.octet
, macaddr
.octet
,
5084 zvni_neigh_uninstall(zvni
, n
);
5085 zvni_neigh_del(zvni
, n
);
5086 zvni_deref_ip2mac(zvni
, mac
, 1);
5089 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5090 zvni_process_neigh_on_remote_mac_del(zvni
,
5093 if (list_isempty(mac
->neigh_list
)) {
5094 zvni_mac_uninstall(zvni
, mac
, 0);
5095 zvni_mac_del(zvni
, mac
);
5097 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5107 * Handle message from client to add a remote MACIP for a VNI. This
5108 * could be just the add of a MAC address or the add of a neighbor
5111 int zebra_vxlan_remote_macip_add(struct zserv
*client
, u_short length
,
5112 struct zebra_vrf
*zvrf
)
5116 struct ethaddr macaddr
;
5118 struct in_addr vtep_ip
;
5120 zebra_vtep_t
*zvtep
;
5121 zebra_mac_t
*mac
, *old_mac
;
5123 u_short l
= 0, ipa_len
;
5124 int update_mac
= 0, update_neigh
= 0;
5125 char buf
[ETHER_ADDR_STRLEN
];
5126 char buf1
[INET6_ADDRSTRLEN
];
5129 struct interface
*ifp
= NULL
;
5130 struct zebra_if
*zif
= NULL
;
5132 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5133 memset(&ip
, 0, sizeof(struct ipaddr
));
5134 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5136 if (!EVPN_ENABLED(zvrf
)) {
5137 zlog_warn("%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
5138 __PRETTY_FUNCTION__
);
5144 while (l
< length
) {
5145 /* Obtain each remote MACIP and process. */
5146 /* Message contains VNI, followed by MAC followed by IP (if any)
5147 * followed by remote VTEP IP.
5149 update_mac
= update_neigh
= 0;
5152 memset(&ip
, 0, sizeof(ip
));
5153 STREAM_GETL(s
, vni
);
5154 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5155 STREAM_GETL(s
, ipa_len
);
5157 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5159 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5161 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5162 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5163 l
+= IPV4_MAX_BYTELEN
;
5165 /* Get flags - sticky mac and/or gateway mac */
5166 flags
= stream_getc(s
);
5167 sticky
= CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5170 if (IS_ZEBRA_DEBUG_VXLAN
)
5172 "Recv MACIP Add MAC %s IP %s VNI %u Remote VTEP %s with flags 0x%x from %s",
5173 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5174 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5175 inet_ntoa(vtep_ip
), flags
,
5176 zebra_route_string(client
->proto
));
5178 /* Locate VNI hash entry - expected to exist. */
5179 zvni
= zvni_lookup(vni
);
5182 "Failed to locate VNI hash upon remote MACIP ADD, VNI %u",
5186 ifp
= zvni
->vxlan_if
;
5189 "VNI %u hash %p doesn't have intf upon remote MACIP add",
5195 /* If down or not mapped to a bridge, we're done. */
5196 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5199 /* The remote VTEP specified should normally exist, but it is
5201 * that when peering comes up, peer may advertise MACIP routes
5203 * advertising type-3 routes.
5205 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5207 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5209 "Failed to add remote VTEP, VNI %u zvni %p",
5214 zvni_vtep_install(zvni
, &vtep_ip
);
5217 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5219 /* Ignore the update if the mac is already present
5221 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5222 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5223 if (IS_ZEBRA_DEBUG_VXLAN
)
5224 zlog_debug("%u:Ignore MAC %s IP %s on VNI %u as MAC is already configured as gateway mac",
5226 prefix_mac2str(&macaddr
,
5228 ipaddr2str(&ip
, buf1
,
5229 sizeof(buf1
)), vni
);
5233 /* check if the remote MAC is unknown or has a change.
5234 * If so, that needs to be updated first. Note that client could
5235 * install MAC and MACIP separately or just install the latter.
5237 if (!mac
|| !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5238 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0)
5240 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
))
5245 mac
= zvni_mac_add(zvni
, &macaddr
);
5248 "Failed to add MAC %s VNI %u Remote VTEP %s",
5249 prefix_mac2str(&macaddr
, buf
,
5251 vni
, inet_ntoa(vtep_ip
));
5255 /* Is this MAC created for a MACIP? */
5257 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5260 /* Set "auto" and "remote" forwarding info. */
5261 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5262 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5263 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5264 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5267 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5269 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5271 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5273 /* Install the entry. */
5274 zvni_mac_install(zvni
, mac
);
5277 /* If there is no IP, continue - after clearing AUTO flag of
5280 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5284 /* Check if the remote neighbor itself is unknown or has a
5286 * If so, create or update and then install the entry.
5288 n
= zvni_neigh_lookup(zvni
, &ip
);
5289 if (!n
|| !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5290 || (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
)) != 0)
5291 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
))
5296 n
= zvni_neigh_add(zvni
, &ip
, &macaddr
);
5299 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5300 ipaddr2str(&ip
, buf1
,
5302 prefix_mac2str(&macaddr
, buf
,
5304 vni
, inet_ntoa(vtep_ip
));
5308 } else if (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
))
5310 /* MAC change, update neigh list for old and new
5312 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5314 listnode_delete(old_mac
->neigh_list
, n
);
5315 zvni_deref_ip2mac(zvni
, old_mac
, 1);
5317 listnode_add_sort(mac
->neigh_list
, n
);
5318 memcpy(&n
->emac
, &macaddr
, ETH_ALEN
);
5321 /* Set "remote" forwarding info. */
5322 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5323 /* TODO: Handle MAC change. */
5324 n
->r_vtep_ip
= vtep_ip
;
5325 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5327 /* Install the entry. */
5328 zvni_neigh_install(zvni
, n
);
5337 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5338 * us, this must involve a multihoming scenario. Treat this as implicit delete
5339 * of any prior local MAC.
5341 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
5342 struct interface
*br_if
,
5343 struct ethaddr
*macaddr
, vlanid_t vid
)
5345 struct zebra_if
*zif
;
5346 struct zebra_l2info_vxlan
*vxl
;
5350 char buf
[ETHER_ADDR_STRLEN
];
5354 vxl
= &zif
->l2info
.vxl
;
5357 /* Check if EVPN is enabled. */
5358 if (!is_evpn_enabled())
5361 /* Locate hash entry; it is expected to exist. */
5362 zvni
= zvni_lookup(vni
);
5366 /* If entry doesn't exist, nothing to do. */
5367 mac
= zvni_mac_lookup(zvni
, macaddr
);
5371 /* Is it a local entry? */
5372 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5375 if (IS_ZEBRA_DEBUG_VXLAN
)
5377 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5378 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5379 ifp
->name
, ifp
->ifindex
, vni
);
5381 /* Remove MAC from BGP. */
5382 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5385 * If there are no neigh associated with the mac delete the mac
5386 * else mark it as AUTO for forward reference
5388 if (!listcount(mac
->neigh_list
)) {
5389 zvni_mac_del(zvni
, mac
);
5391 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5392 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5399 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5400 * This can happen because the remote MAC entries are also added as "dynamic",
5401 * so the kernel can ageout the entry.
5403 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
5404 struct interface
*br_if
,
5405 struct ethaddr
*macaddr
, vlanid_t vid
)
5407 struct zebra_if
*zif
= NULL
;
5408 struct zebra_l2info_vxlan
*vxl
= NULL
;
5410 zebra_vni_t
*zvni
= NULL
;
5411 zebra_l3vni_t
*zl3vni
= NULL
;
5412 zebra_mac_t
*mac
= NULL
;
5413 char buf
[ETHER_ADDR_STRLEN
];
5417 vxl
= &zif
->l2info
.vxl
;
5420 /* Check if EVPN is enabled. */
5421 if (!is_evpn_enabled())
5424 /* check if this is a remote RMAC and readd simillar to remote macs */
5425 zl3vni
= zl3vni_lookup(vni
);
5427 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
5429 /* Locate hash entry; it is expected to exist. */
5430 zvni
= zvni_lookup(vni
);
5434 /* If entry doesn't exist, nothing to do. */
5435 mac
= zvni_mac_lookup(zvni
, macaddr
);
5439 /* Is it a remote entry? */
5440 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
5443 if (IS_ZEBRA_DEBUG_VXLAN
)
5444 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
5445 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5448 zvni_mac_install(zvni
, mac
);
5453 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
5455 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
5456 struct ethaddr
*macaddr
, vlanid_t vid
)
5460 char buf
[ETHER_ADDR_STRLEN
];
5462 /* We are interested in MACs only on ports or (port, VLAN) that
5465 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5468 if (!zvni
->vxlan_if
) {
5469 zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL",
5474 if (IS_ZEBRA_DEBUG_VXLAN
)
5475 zlog_debug("Del MAC %s intf %s(%u) VID %u -> VNI %u",
5476 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5477 ifp
->ifindex
, vid
, zvni
->vni
);
5479 /* If entry doesn't exist, nothing to do. */
5480 mac
= zvni_mac_lookup(zvni
, macaddr
);
5484 /* Is it a local entry? */
5485 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5488 /* Remove MAC from BGP. */
5489 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5491 /* Update all the neigh entries associated with this mac */
5492 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
5495 * If there are no neigh associated with the mac delete the mac
5496 * else mark it as AUTO for forward reference
5498 if (!listcount(mac
->neigh_list
)) {
5499 zvni_mac_del(zvni
, mac
);
5501 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5502 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5509 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
5511 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
5512 struct interface
*br_if
,
5513 struct ethaddr
*macaddr
, vlanid_t vid
,
5518 char buf
[ETHER_ADDR_STRLEN
];
5522 /* We are interested in MACs only on ports or (port, VLAN) that
5525 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5527 if (IS_ZEBRA_DEBUG_VXLAN
)
5529 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5530 sticky
? "sticky " : "",
5531 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5532 ifp
->name
, ifp
->ifindex
, vid
);
5536 if (!zvni
->vxlan_if
) {
5537 zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD",
5542 if (IS_ZEBRA_DEBUG_VXLAN
)
5544 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
5545 sticky
? "sticky " : "",
5546 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5547 ifp
->ifindex
, vid
, zvni
->vni
);
5549 /* If same entry already exists, nothing to do. */
5550 mac
= zvni_mac_lookup(zvni
, macaddr
);
5552 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5553 mac_sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5559 * return if nothing has changed.
5560 * inform bgp if sticky flag has changed
5561 * update locally and do not inform bgp if local
5562 * parameters like interface has changed
5564 if (mac_sticky
== sticky
5565 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
5566 && mac
->fwd_info
.local
.vid
== vid
) {
5567 if (IS_ZEBRA_DEBUG_VXLAN
)
5569 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
5570 "entry exists and has not changed ",
5571 sticky
? "sticky " : "",
5572 prefix_mac2str(macaddr
, buf
,
5574 ifp
->name
, ifp
->ifindex
, vid
,
5577 } else if (mac_sticky
!= sticky
) {
5580 add
= 0; /* This is an update of local
5583 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5585 * If we have already learned the MAC as a remote sticky
5587 * this is a operator error and we must log a warning
5589 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
5591 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
5592 prefix_mac2str(macaddr
, buf
,
5594 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
5602 mac
= zvni_mac_add(zvni
, macaddr
);
5604 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
5605 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5606 ifp
->name
, ifp
->ifindex
, vid
);
5611 /* Set "local" forwarding info. */
5612 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5613 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5614 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5615 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5616 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
5617 mac
->fwd_info
.local
.vid
= vid
;
5620 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5622 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5624 /* Inform BGP if required. */
5626 zvni_process_neigh_on_local_mac_add(zvni
, mac
);
5627 return zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
5635 * Handle message from client to delete a remote VTEP for a VNI.
5637 int zebra_vxlan_remote_vtep_del(struct zserv
*client
, u_short length
,
5638 struct zebra_vrf
*zvrf
)
5643 struct in_addr vtep_ip
;
5645 zebra_vtep_t
*zvtep
;
5646 struct interface
*ifp
;
5647 struct zebra_if
*zif
;
5649 if (!is_evpn_enabled()) {
5650 zlog_warn("%s: EVPN is not enabled yet we have received a vtep del command",
5651 __PRETTY_FUNCTION__
);
5655 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5656 zlog_err("Recv MACIP DEL for non-default VRF %u",
5663 while (l
< length
) {
5664 /* Obtain each remote VTEP and process. */
5665 STREAM_GETL(s
, vni
);
5667 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5668 l
+= IPV4_MAX_BYTELEN
;
5670 if (IS_ZEBRA_DEBUG_VXLAN
)
5671 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
5672 inet_ntoa(vtep_ip
), vni
,
5673 zebra_route_string(client
->proto
));
5675 /* Locate VNI hash entry - expected to exist. */
5676 zvni
= zvni_lookup(vni
);
5678 if (IS_ZEBRA_DEBUG_VXLAN
)
5680 "Failed to locate VNI hash upon remote VTEP DEL, "
5686 ifp
= zvni
->vxlan_if
;
5689 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
5695 /* If down or not mapped to a bridge, we're done. */
5696 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5699 /* If the remote VTEP does not exist, there's nothing more to
5701 * Otherwise, uninstall any remote MACs pointing to this VTEP
5703 * then, the VTEP entry itself and remove it.
5705 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5709 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
5710 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
5711 zvni_vtep_uninstall(zvni
, &vtep_ip
);
5712 zvni_vtep_del(zvni
, zvtep
);
5720 * Handle message from client to add a remote VTEP for a VNI.
5722 int zebra_vxlan_remote_vtep_add(struct zserv
*client
, u_short length
,
5723 struct zebra_vrf
*zvrf
)
5728 struct in_addr vtep_ip
;
5730 struct interface
*ifp
;
5731 struct zebra_if
*zif
;
5733 if (!is_evpn_enabled()) {
5734 zlog_warn("%s: EVPN not enabled yet we received a vtep_add zapi call",
5735 __PRETTY_FUNCTION__
);
5739 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5740 zlog_err("Recv MACIP ADD for non-default VRF %u",
5747 while (l
< length
) {
5748 /* Obtain each remote VTEP and process. */
5749 STREAM_GETL(s
, vni
);
5751 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5752 l
+= IPV4_MAX_BYTELEN
;
5754 if (IS_ZEBRA_DEBUG_VXLAN
)
5755 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
5756 inet_ntoa(vtep_ip
), vni
,
5757 zebra_route_string(client
->proto
));
5759 /* Locate VNI hash entry - expected to exist. */
5760 zvni
= zvni_lookup(vni
);
5763 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
5768 ifp
= zvni
->vxlan_if
;
5771 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
5778 /* If down or not mapped to a bridge, we're done. */
5779 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5782 /* If the remote VTEP already exists,
5783 there's nothing more to do. */
5784 if (zvni_vtep_find(zvni
, &vtep_ip
))
5787 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5789 "Failed to add remote VTEP, VNI %u zvni %p",
5794 zvni_vtep_install(zvni
, &vtep_ip
);
5802 * Add/Del gateway macip to evpn
5804 * 1. SVI interface on a vlan aware bridge
5805 * 2. SVI interface on a vlan unaware bridge
5806 * 3. vrr interface (MACVLAN) associated to a SVI
5807 * We advertise macip routes for an interface if it is associated to VxLan vlan
5809 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
5813 struct ethaddr macaddr
;
5814 zebra_vni_t
*zvni
= NULL
;
5816 memset(&ip
, 0, sizeof(struct ipaddr
));
5817 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5819 /* Check if EVPN is enabled. */
5820 if (!is_evpn_enabled())
5823 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
5824 struct interface
*svi_if
=
5825 NULL
; /* SVI corresponding to the MACVLAN */
5826 struct zebra_if
*ifp_zif
=
5827 NULL
; /* Zebra daemon specific info for MACVLAN */
5828 struct zebra_if
*svi_if_zif
=
5829 NULL
; /* Zebra daemon specific info for SVI*/
5831 ifp_zif
= ifp
->info
;
5836 * for a MACVLAN interface the link represents the svi_if
5838 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
5839 ifp_zif
->link_ifindex
);
5841 zlog_err("MACVLAN %s(%u) without link information",
5842 ifp
->name
, ifp
->ifindex
);
5846 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
5848 * If it is a vlan aware bridge then the link gives the
5849 * bridge information
5851 struct interface
*svi_if_link
= NULL
;
5853 svi_if_zif
= svi_if
->info
;
5855 svi_if_link
= if_lookup_by_index_per_ns(
5856 zebra_ns_lookup(NS_DEFAULT
),
5857 svi_if_zif
->link_ifindex
);
5858 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
5860 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
5862 * If it is a vlan unaware bridge then svi is the bridge
5865 zvni
= zvni_from_svi(svi_if
, svi_if
);
5867 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
5868 struct zebra_if
*svi_if_zif
=
5869 NULL
; /* Zebra daemon specific info for SVI */
5870 struct interface
*svi_if_link
=
5871 NULL
; /* link info for the SVI = bridge info */
5873 svi_if_zif
= ifp
->info
;
5874 svi_if_link
= if_lookup_by_index_per_ns(
5875 zebra_ns_lookup(NS_DEFAULT
), svi_if_zif
->link_ifindex
);
5876 if (svi_if_zif
&& svi_if_link
)
5877 zvni
= zvni_from_svi(ifp
, svi_if_link
);
5878 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
5879 zvni
= zvni_from_svi(ifp
, ifp
);
5885 if (!zvni
->vxlan_if
) {
5886 zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
5892 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
5894 if (p
->family
== AF_INET
) {
5895 ip
.ipa_type
= IPADDR_V4
;
5896 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
5897 sizeof(struct in_addr
));
5898 } else if (p
->family
== AF_INET6
) {
5899 ip
.ipa_type
= IPADDR_V6
;
5900 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
5901 sizeof(struct in6_addr
));
5906 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
5908 zvni_gw_macip_del(ifp
, zvni
, &ip
);
5914 * Handle SVI interface going down.
5915 * SVI can be associated to either L3-VNI or L2-VNI.
5916 * For L2-VNI: At this point, this is a NOP since
5917 * the kernel deletes the neighbor entries on this SVI (if any).
5918 * We only need to update the vrf corresponding to zvni.
5919 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
5922 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
5924 zebra_l3vni_t
*zl3vni
= NULL
;
5926 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5929 /* process l3-vni down */
5930 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
5932 /* remove association with svi-if */
5933 zl3vni
->svi_if
= NULL
;
5935 zebra_vni_t
*zvni
= NULL
;
5937 /* since we dont have svi corresponding to zvni, we associate it
5938 * to default vrf. Note: the corresponding neigh entries on the
5939 * SVI would have already been deleted */
5940 zvni
= zvni_from_svi(ifp
, link_if
);
5942 zvni
->vrf_id
= VRF_DEFAULT
;
5944 /* update the tenant vrf in BGP */
5945 zvni_send_add_to_client(zvni
);
5952 * Handle SVI interface coming up.
5953 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
5955 * For L2-VNI: we need to install any remote neighbors entried (used for
5957 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
5959 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
5961 zebra_vni_t
*zvni
= NULL
;
5962 zebra_l3vni_t
*zl3vni
= NULL
;
5964 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5967 /* associate with svi */
5968 zl3vni
->svi_if
= ifp
;
5970 /* process oper-up */
5971 if (is_l3vni_oper_up(zl3vni
))
5972 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
5975 /* process SVI up for l2-vni */
5976 struct neigh_walk_ctx n_wctx
;
5978 zvni
= zvni_from_svi(ifp
, link_if
);
5982 if (!zvni
->vxlan_if
) {
5983 zlog_err("VNI %u hash %p doesn't have intf upon SVI up",
5988 if (IS_ZEBRA_DEBUG_VXLAN
)
5989 zlog_debug("SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
5990 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
5991 vrf_id_to_name(ifp
->vrf_id
));
5993 /* update the vrf information for l2-vni and inform bgp */
5994 zvni
->vrf_id
= ifp
->vrf_id
;
5995 zvni_send_add_to_client(zvni
);
5997 /* Install any remote neighbors for this VNI. */
5998 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6000 hash_iterate(zvni
->neigh_table
,
6001 zvni_install_neigh_hash
,
6009 * Handle VxLAN interface down
6011 int zebra_vxlan_if_down(struct interface
*ifp
)
6014 struct zebra_if
*zif
= NULL
;
6015 struct zebra_l2info_vxlan
*vxl
= NULL
;
6016 zebra_l3vni_t
*zl3vni
= NULL
;
6019 /* Check if EVPN is enabled. */
6020 if (!is_evpn_enabled())
6025 vxl
= &zif
->l2info
.vxl
;
6028 zl3vni
= zl3vni_lookup(vni
);
6030 /* process-if-down for l3-vni */
6031 if (IS_ZEBRA_DEBUG_VXLAN
)
6032 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN",
6033 ifp
->name
, ifp
->ifindex
, vni
);
6035 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6037 /* process if-down for l2-vni */
6038 if (IS_ZEBRA_DEBUG_VXLAN
)
6039 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN",
6040 ifp
->name
, ifp
->ifindex
, vni
);
6042 /* Locate hash entry; it is expected to exist. */
6043 zvni
= zvni_lookup(vni
);
6046 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
6047 ifp
->name
, ifp
->ifindex
, vni
);
6051 assert(zvni
->vxlan_if
== ifp
);
6053 /* Delete this VNI from BGP. */
6054 zvni_send_del_to_client(zvni
->vni
);
6056 /* Free up all neighbors and MACs, if any. */
6057 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6058 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6060 /* Free up all remote VTEPs, if any. */
6061 zvni_vtep_del_all(zvni
, 1);
6067 * Handle VxLAN interface up - update BGP if required.
6069 int zebra_vxlan_if_up(struct interface
*ifp
)
6072 struct zebra_if
*zif
= NULL
;
6073 struct zebra_l2info_vxlan
*vxl
= NULL
;
6074 zebra_vni_t
*zvni
= NULL
;
6075 zebra_l3vni_t
*zl3vni
= NULL
;
6077 /* Check if EVPN is enabled. */
6078 if (!is_evpn_enabled())
6083 vxl
= &zif
->l2info
.vxl
;
6086 zl3vni
= zl3vni_lookup(vni
);
6089 if (IS_ZEBRA_DEBUG_VXLAN
)
6090 zlog_debug("Intf %s(%u) L3-VNI %u is UP",
6091 ifp
->name
, ifp
->ifindex
, vni
);
6093 /* we need to associate with SVI, if any, we can associate with
6094 * svi-if only after association with vxlan-intf is complete
6096 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6098 if (is_l3vni_oper_up(zl3vni
))
6099 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6101 /* Handle L2-VNI add */
6102 struct interface
*vlan_if
= NULL
;
6104 if (IS_ZEBRA_DEBUG_VXLAN
)
6105 zlog_debug("Intf %s(%u) L2-VNI %u is UP",
6106 ifp
->name
, ifp
->ifindex
, vni
);
6108 /* Locate hash entry; it is expected to exist. */
6109 zvni
= zvni_lookup(vni
);
6112 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
6113 ifp
->name
, ifp
->ifindex
, vni
);
6117 assert(zvni
->vxlan_if
== ifp
);
6118 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6119 zif
->brslave_info
.br_if
);
6121 zvni
->vrf_id
= vlan_if
->vrf_id
;
6122 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6124 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6127 /* If part of a bridge, inform BGP about this VNI. */
6128 /* Also, read and populate local MACs and neighbors. */
6129 if (zif
->brslave_info
.br_if
) {
6130 zvni_send_add_to_client(zvni
);
6131 zvni_read_mac_neigh(zvni
, ifp
);
6139 * Handle VxLAN interface delete. Locate and remove entry in hash table
6140 * and update BGP, if required.
6142 int zebra_vxlan_if_del(struct interface
*ifp
)
6145 struct zebra_if
*zif
= NULL
;
6146 struct zebra_l2info_vxlan
*vxl
= NULL
;
6147 zebra_vni_t
*zvni
= NULL
;
6148 zebra_l3vni_t
*zl3vni
= NULL
;
6150 /* Check if EVPN is enabled. */
6151 if (!is_evpn_enabled())
6156 vxl
= &zif
->l2info
.vxl
;
6159 zl3vni
= zl3vni_lookup(vni
);
6162 if (IS_ZEBRA_DEBUG_VXLAN
)
6163 zlog_debug("Del L3-VNI %u intf %s(%u)",
6164 vni
, ifp
->name
, ifp
->ifindex
);
6166 /* process oper-down for l3-vni */
6167 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6169 /* remove the association with vxlan_if */
6170 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
6171 zl3vni
->vxlan_if
= NULL
;
6174 /* process if-del for l2-vni*/
6175 if (IS_ZEBRA_DEBUG_VXLAN
)
6176 zlog_debug("Del L2-VNI %u intf %s(%u)",
6177 vni
, ifp
->name
, ifp
->ifindex
);
6179 /* Locate hash entry; it is expected to exist. */
6180 zvni
= zvni_lookup(vni
);
6183 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6184 ifp
->name
, ifp
->ifindex
, vni
);
6188 /* remove from l3-vni list */
6189 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
6191 listnode_delete(zl3vni
->l2vnis
, zvni
);
6193 /* Delete VNI from BGP. */
6194 zvni_send_del_to_client(zvni
->vni
);
6196 /* Free up all neighbors and MAC, if any. */
6197 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
6198 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
6200 /* Free up all remote VTEPs, if any. */
6201 zvni_vtep_del_all(zvni
, 0);
6203 /* Delete the hash entry. */
6204 if (zvni_del(zvni
)) {
6205 zlog_err("Failed to del VNI hash %p, IF %s(%u) VNI %u",
6206 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
6214 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6216 int zebra_vxlan_if_update(struct interface
*ifp
, u_int16_t chgflags
)
6219 struct zebra_if
*zif
= NULL
;
6220 struct zebra_l2info_vxlan
*vxl
= NULL
;
6221 zebra_vni_t
*zvni
= NULL
;
6222 zebra_l3vni_t
*zl3vni
= NULL
;
6224 /* Check if EVPN is enabled. */
6225 if (!is_evpn_enabled())
6230 vxl
= &zif
->l2info
.vxl
;
6233 zl3vni
= zl3vni_lookup(vni
);
6236 if (IS_ZEBRA_DEBUG_VXLAN
)
6238 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6239 vni
, ifp
->name
, ifp
->ifindex
,
6240 vxl
->access_vlan
, inet_ntoa(vxl
->vtep_ip
),
6241 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6243 /* Removed from bridge? Cleanup and return */
6244 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6245 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6246 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6250 /* access-vlan change - process oper down, associate with new
6251 * svi_if and then process oper up again
6253 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6254 if (if_is_operative(ifp
)) {
6255 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6256 zl3vni
->svi_if
= NULL
;
6257 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6258 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6259 if (is_l3vni_oper_up(zl3vni
))
6260 zebra_vxlan_process_l3vni_oper_up(
6266 * local-ip change - process oper down, associate with new
6267 * local-ip and then process oper up again
6269 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
6270 if (if_is_operative(ifp
)) {
6271 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6272 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6273 if (is_l3vni_oper_up(zl3vni
))
6274 zebra_vxlan_process_l3vni_oper_up(
6279 /* Update local tunnel IP. */
6280 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6282 /* if we have a valid new master, process l3-vni oper up */
6283 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
6284 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
6285 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6289 /* Update VNI hash. */
6290 zvni
= zvni_lookup(vni
);
6293 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6294 ifp
->name
, ifp
->ifindex
, vni
);
6298 if (IS_ZEBRA_DEBUG_VXLAN
)
6300 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6301 vni
, ifp
->name
, ifp
->ifindex
,
6302 vxl
->access_vlan
, inet_ntoa(vxl
->vtep_ip
),
6303 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6305 /* Removed from bridge? Cleanup and return */
6306 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6307 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6308 /* Delete from client, remove all remote VTEPs */
6309 /* Also, free up all MACs and neighbors. */
6310 zvni_send_del_to_client(zvni
->vni
);
6311 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6312 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6313 zvni_vtep_del_all(zvni
, 1);
6317 /* Handle other changes. */
6318 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6319 /* Remove all existing local neigh and MACs for this VNI
6320 * (including from BGP)
6322 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6323 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6326 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6327 zvni
->vxlan_if
= ifp
;
6329 /* Take further actions needed.
6330 * Note that if we are here, there is a change of interest.
6332 /* If down or not mapped to a bridge, we're done. */
6333 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6336 /* Inform BGP, if there is a change of interest. */
6338 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
6339 zvni_send_add_to_client(zvni
);
6341 /* If there is a valid new master or a VLAN mapping change,
6342 * read and populate local MACs and neighbors.
6343 * Also, reinstall any remote MACs and neighbors
6344 * for this VNI (based on new VLAN).
6346 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6347 zvni_read_mac_neigh(zvni
, ifp
);
6348 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6349 struct mac_walk_ctx m_wctx
;
6350 struct neigh_walk_ctx n_wctx
;
6352 zvni_read_mac_neigh(zvni
, ifp
);
6354 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6356 hash_iterate(zvni
->mac_table
,
6357 zvni_install_mac_hash
,
6360 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6362 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6371 * Handle VxLAN interface add.
6373 int zebra_vxlan_if_add(struct interface
*ifp
)
6376 struct zebra_if
*zif
= NULL
;
6377 struct zebra_l2info_vxlan
*vxl
= NULL
;
6378 zebra_vni_t
*zvni
= NULL
;
6379 zebra_l3vni_t
*zl3vni
= NULL
;
6381 /* Check if EVPN is enabled. */
6382 if (!is_evpn_enabled())
6387 vxl
= &zif
->l2info
.vxl
;
6390 zl3vni
= zl3vni_lookup(vni
);
6393 /* process if-add for l3-vni*/
6394 if (IS_ZEBRA_DEBUG_VXLAN
)
6396 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6397 vni
, ifp
->name
, ifp
->ifindex
,
6398 vxl
->access_vlan
, inet_ntoa(vxl
->vtep_ip
),
6399 zif
->brslave_info
.bridge_ifindex
);
6401 /* associate with vxlan_if */
6402 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6403 zl3vni
->vxlan_if
= ifp
;
6405 /* Associate with SVI, if any. We can associate with svi-if only
6406 * after association with vxlan_if is complete */
6407 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6409 if (is_l3vni_oper_up(zl3vni
))
6410 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6413 /* process if-add for l2-vni */
6414 struct interface
*vlan_if
= NULL
;
6416 /* Create or update VNI hash. */
6417 zvni
= zvni_lookup(vni
);
6419 zvni
= zvni_add(vni
);
6422 "Failed to add VNI hash, IF %s(%u) VNI %u",
6423 ifp
->name
, ifp
->ifindex
, vni
);
6428 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6429 zvni
->vxlan_if
= ifp
;
6430 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6431 zif
->brslave_info
.br_if
);
6433 zvni
->vrf_id
= vlan_if
->vrf_id
;
6434 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6436 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6439 if (IS_ZEBRA_DEBUG_VXLAN
)
6441 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6443 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
) :
6445 ifp
->name
, ifp
->ifindex
,
6446 vxl
->access_vlan
, inet_ntoa(vxl
->vtep_ip
),
6447 zif
->brslave_info
.bridge_ifindex
);
6449 /* If down or not mapped to a bridge, we're done. */
6450 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6454 zvni_send_add_to_client(zvni
);
6456 /* Read and populate local MACs and neighbors */
6457 zvni_read_mac_neigh(zvni
, ifp
);
6463 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
,
6465 char *err
, int err_str_sz
,
6466 int filter
, int add
)
6468 zebra_l3vni_t
*zl3vni
= NULL
;
6469 struct zebra_vrf
*zvrf_default
= NULL
;
6471 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
6475 if (IS_ZEBRA_DEBUG_VXLAN
)
6476 zlog_debug("vrf %s vni %u %s",
6479 add
? "ADD" : "DEL");
6483 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6485 /* check if the vni is already present under zvrf */
6487 snprintf(err
, err_str_sz
,
6488 "VNI is already configured under the vrf");
6492 /* check if this VNI is already present in the system */
6493 zl3vni
= zl3vni_lookup(vni
);
6495 snprintf(err
, err_str_sz
,
6496 "VNI is already configured as L3-VNI");
6500 /* add the L3-VNI to the global table */
6501 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
6503 snprintf(err
, err_str_sz
,
6504 "Could not add L3-VNI");
6508 /* associate the vrf with vni */
6511 /* set the filter in l3vni to denote if we are using l3vni only
6515 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
6517 /* associate with vxlan-intf;
6518 * we need to associate with the vxlan-intf first
6520 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
6522 /* associate with corresponding SVI interface, we can associate
6523 * with svi-if only after vxlan interface association is
6526 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6528 /* formulate l2vni list */
6529 hash_iterate(zvrf_default
->vni_table
,
6530 zvni_add_to_l3vni_list
, zl3vni
);
6532 if (is_l3vni_oper_up(zl3vni
))
6533 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6536 zl3vni
= zl3vni_lookup(vni
);
6538 snprintf(err
, err_str_sz
, "VNI doesn't exist");
6542 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6544 /* delete and uninstall all rmacs */
6545 hash_iterate(zl3vni
->rmac_table
,
6546 zl3vni_del_rmac_hash_entry
,
6549 /* delete and uninstall all next-hops */
6550 hash_iterate(zl3vni
->nh_table
,
6551 zl3vni_del_nh_hash_entry
,
6557 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6562 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
6564 zebra_l3vni_t
*zl3vni
= NULL
;
6567 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6571 zl3vni
->vrf_id
= zvrf_id(zvrf
);
6572 if (is_l3vni_oper_up(zl3vni
))
6573 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6577 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
6579 zebra_l3vni_t
*zl3vni
= NULL
;
6582 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6586 zl3vni
->vrf_id
= VRF_UNKNOWN
;
6587 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6591 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
6593 zebra_l3vni_t
*zl3vni
= NULL
;
6597 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6603 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
6609 * Handle message from client to enable/disable advertisement of g/w macip
6612 int zebra_vxlan_advertise_subnet(struct zserv
*client
, u_short length
,
6613 struct zebra_vrf
*zvrf
)
6618 zebra_vni_t
*zvni
= NULL
;
6619 struct interface
*ifp
= NULL
;
6620 struct zebra_if
*zif
= NULL
;
6621 struct zebra_l2info_vxlan zl2_info
;
6622 struct interface
*vlan_if
= NULL
;
6624 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6625 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6631 advertise
= stream_getc(s
);
6632 vni
= stream_get3(s
);
6634 zvni
= zvni_lookup(vni
);
6638 if (zvni
->advertise_subnet
== advertise
)
6641 if (IS_ZEBRA_DEBUG_VXLAN
)
6643 "EVPN subnet Adv %s on VNI %d , currently %s",
6644 advertise
? "enabled" : "disabled", vni
,
6645 zvni
->advertise_subnet
? "enabled" : "disabled");
6648 zvni
->advertise_subnet
= advertise
;
6650 ifp
= zvni
->vxlan_if
;
6656 /* If down or not mapped to a bridge, we're done. */
6657 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6660 zl2_info
= zif
->l2info
.vxl
;
6662 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
6663 zif
->brslave_info
.br_if
);
6667 if (zvni
->advertise_subnet
)
6668 zvni_advertise_subnet(zvni
, vlan_if
, 1);
6670 zvni_advertise_subnet(zvni
, vlan_if
, 0);
6676 * Handle message from client to enable/disable advertisement of g/w macip
6679 int zebra_vxlan_advertise_gw_macip(struct zserv
*client
, u_short length
,
6680 struct zebra_vrf
*zvrf
)
6685 zebra_vni_t
*zvni
= NULL
;
6686 struct interface
*ifp
= NULL
;
6688 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6689 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6695 STREAM_GETC(s
, advertise
);
6696 STREAM_GET(&vni
, s
, 3);
6699 if (IS_ZEBRA_DEBUG_VXLAN
)
6700 zlog_debug("EVPN gateway macip Adv %s, currently %s",
6701 advertise
? "enabled" : "disabled",
6702 advertise_gw_macip_enabled(NULL
)
6706 if (zvrf
->advertise_gw_macip
== advertise
)
6709 zvrf
->advertise_gw_macip
= advertise
;
6711 if (advertise_gw_macip_enabled(zvni
))
6712 hash_iterate(zvrf
->vni_table
,
6713 zvni_gw_macip_add_for_vni_hash
, NULL
);
6715 hash_iterate(zvrf
->vni_table
,
6716 zvni_gw_macip_del_for_vni_hash
, NULL
);
6719 struct zebra_if
*zif
= NULL
;
6720 struct zebra_l2info_vxlan zl2_info
;
6721 struct interface
*vlan_if
= NULL
;
6722 struct interface
*vrr_if
= NULL
;
6724 zvni
= zvni_lookup(vni
);
6728 if (IS_ZEBRA_DEBUG_VXLAN
)
6730 "EVPN gateway macip Adv %s on VNI %d , currently %s",
6731 advertise
? "enabled" : "disabled", vni
,
6732 advertise_gw_macip_enabled(zvni
)
6736 if (zvni
->advertise_gw_macip
== advertise
)
6739 zvni
->advertise_gw_macip
= advertise
;
6741 ifp
= zvni
->vxlan_if
;
6747 /* If down or not mapped to a bridge, we're done. */
6748 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6751 zl2_info
= zif
->l2info
.vxl
;
6753 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
6754 zif
->brslave_info
.br_if
);
6758 if (advertise_gw_macip_enabled(zvni
)) {
6759 /* Add primary SVI MAC-IP */
6760 zvni_add_macip_for_intf(vlan_if
, zvni
);
6762 /* Add VRR MAC-IP - if any*/
6763 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6765 zvni_add_macip_for_intf(vrr_if
, zvni
);
6767 /* Del primary MAC-IP */
6768 zvni_del_macip_for_intf(vlan_if
, zvni
);
6770 /* Del VRR MAC-IP - if any*/
6771 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6773 zvni_del_macip_for_intf(vrr_if
, zvni
);
6783 * Handle message from client to learn (or stop learning) about VNIs and MACs.
6784 * When enabled, the VNI hash table will be built and MAC FDB table read;
6785 * when disabled, the entries should be deleted and remote VTEPs and MACs
6786 * uninstalled from the kernel.
6788 int zebra_vxlan_advertise_all_vni(struct zserv
*client
,
6789 u_short length
, struct zebra_vrf
*zvrf
)
6791 struct stream
*s
= NULL
;
6793 struct zebra_ns
*zns
= NULL
;
6795 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6796 zlog_err("EVPN VNI Adv for non-default VRF %u",
6802 STREAM_GETC(s
, advertise
);
6804 if (IS_ZEBRA_DEBUG_VXLAN
)
6805 zlog_debug("EVPN VNI Adv %s, currently %s",
6806 advertise
? "enabled" : "disabled",
6807 is_evpn_enabled() ? "enabled" : "disabled");
6809 if (zvrf
->advertise_all_vni
== advertise
)
6812 zvrf
->advertise_all_vni
= advertise
;
6813 if (is_evpn_enabled()) {
6814 /* Build VNI hash table and inform BGP. */
6815 zvni_build_hash_table();
6817 /* Add all SVI (L3 GW) MACs to BGP*/
6818 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
6821 /* Read the MAC FDB */
6822 macfdb_read(zvrf
->zns
);
6824 /* Read neighbors */
6825 neigh_read(zvrf
->zns
);
6827 /* Cleanup VTEPs for all VNIs - uninstall from
6828 * kernel and free entries.
6830 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6832 /* cleanup all l3vnis */
6833 zns
= zebra_ns_lookup(NS_DEFAULT
);
6837 hash_iterate(zns
->l3vni_table
, zl3vni_cleanup_all
, NULL
);
6845 * Allocate VNI hash table for this VRF and do other initialization.
6846 * NOTE: Currently supported only for default VRF.
6848 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
6852 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
6853 "Zebra VRF VNI Table");
6856 /* Cleanup VNI info, but don't free the table. */
6857 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
6861 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6864 /* Close all VNI handling */
6865 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
6869 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6870 hash_free(zvrf
->vni_table
);
6873 /* init the l3vni table */
6874 void zebra_vxlan_ns_init(struct zebra_ns
*zns
)
6876 zns
->l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
6877 "Zebra VRF L3 VNI table");
6880 /* free l3vni table */
6881 void zebra_vxlan_ns_disable(struct zebra_ns
*zns
)
6883 hash_free(zns
->l3vni_table
);
6886 /* get the l3vni svi ifindex */
6887 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
6889 zebra_l3vni_t
*zl3vni
= NULL
;
6891 zl3vni
= zl3vni_from_vrf(vrf_id
);
6892 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
6895 return zl3vni
->svi_if
->ifindex
;