2 * Zebra EVPN for VxLAN code
3 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
5 * This file is part of FRR.
7 * FRR is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * FRR is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with FRR; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
37 #include "zebra/rib.h"
39 #include "zebra/zebra_ns.h"
40 #include "zebra/zserv.h"
41 #include "zebra/debug.h"
42 #include "zebra/interface.h"
43 #include "zebra/zebra_vrf.h"
44 #include "zebra/rt_netlink.h"
45 #include "zebra/zebra_vxlan_private.h"
46 #include "zebra/zebra_vxlan.h"
47 #include "zebra/zebra_memory.h"
48 #include "zebra/zebra_l2.h"
50 DEFINE_MTYPE_STATIC(ZEBRA
, HOST_PREFIX
, "host prefix");
51 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI
, "VNI hash");
52 DEFINE_MTYPE_STATIC(ZEBRA
, ZL3VNI
, "L3 VNI hash");
53 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI_VTEP
, "VNI remote VTEP");
54 DEFINE_MTYPE_STATIC(ZEBRA
, MAC
, "VNI MAC");
55 DEFINE_MTYPE_STATIC(ZEBRA
, NEIGH
, "VNI Neighbor");
59 /* static function declarations */
60 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
62 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
63 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
);
64 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
66 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
68 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
70 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
);
71 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
);
72 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
);
73 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
74 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[]);
76 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
77 struct ipaddr
*ip
, uint8_t flags
,
79 static unsigned int neigh_hash_keymake(void *p
);
80 static int neigh_cmp(const void *p1
, const void *p2
);
81 static void *zvni_neigh_alloc(void *p
);
82 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
84 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
85 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
86 struct in_addr
*r_vtep_ip
);
87 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
89 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
);
90 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
91 struct ethaddr
*macaddr
,
93 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
94 struct ethaddr
*macaddr
,
96 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
97 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
98 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
99 struct interface
*br_if
);
100 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
);
102 /* l3-vni next-hop neigh related APIs */
103 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
105 static void *zl3vni_nh_alloc(void *p
);
106 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
107 struct ipaddr
*vtep_ip
,
108 struct ethaddr
*rmac
);
109 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
110 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
111 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
113 /* l3-vni rmac related APIs */
114 static void zl3vni_print_rmac_hash(struct hash_backet
*, void *);
115 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
116 struct ethaddr
*rmac
);
117 static void *zl3vni_rmac_alloc(void *p
);
118 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
119 struct ethaddr
*rmac
);
120 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
121 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
122 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
124 /* l3-vni related APIs*/
125 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
);
126 static void *zl3vni_alloc(void *p
);
127 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
128 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
129 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t
);
130 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
);
131 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
);
132 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
133 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
135 static unsigned int mac_hash_keymake(void *p
);
136 static int mac_cmp(const void *p1
, const void *p2
);
137 static void *zvni_mac_alloc(void *p
);
138 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
139 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
140 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
141 struct in_addr
*r_vtep_ip
);
142 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
144 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
145 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
147 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
149 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
150 struct interface
*br_if
, vlanid_t vid
);
151 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
152 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
);
153 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
);
155 static unsigned int vni_hash_keymake(void *p
);
156 static int vni_hash_cmp(const void *p1
, const void *p2
);
157 static void *zvni_alloc(void *p
);
158 static zebra_vni_t
*zvni_lookup(vni_t vni
);
159 static zebra_vni_t
*zvni_add(vni_t vni
);
160 static int zvni_del(zebra_vni_t
*zvni
);
161 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
162 static int zvni_send_del_to_client(vni_t vni
);
163 static void zvni_build_hash_table();
164 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
165 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
166 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
167 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
168 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
169 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
170 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
171 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
172 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
173 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
174 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
175 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
177 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
178 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
179 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
182 /* Private functions */
183 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
184 const struct host_rb_entry
*hle2
)
186 if (hle1
->p
.family
< hle2
->p
.family
)
189 if (hle1
->p
.family
> hle2
->p
.family
)
192 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
195 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
198 if (hle1
->p
.family
== AF_INET
) {
199 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
202 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
207 zlog_warn("%s: Unexpected family type: %d", __PRETTY_FUNCTION__
,
212 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
214 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
216 struct host_rb_entry
*hle
;
219 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
226 * Return number of valid MACs in a VNI's MAC hash table - all
227 * remote MACs and non-internal (auto) local MACs count.
229 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
232 uint32_t num_macs
= 0;
234 struct hash_backet
*hb
;
237 hash
= zvni
->mac_table
;
240 for (i
= 0; i
< hash
->size
; i
++) {
241 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
242 mac
= (zebra_mac_t
*)hb
->data
;
243 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
244 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
252 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
254 struct zebra_vrf
*zvrf
;
256 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
257 if (zvrf
&& zvrf
->advertise_gw_macip
)
260 if (zvni
&& zvni
->advertise_gw_macip
)
267 * Helper function to determine maximum width of neighbor IP address for
268 * display - just because we're dealing with IPv6 addresses that can
271 static void zvni_find_neigh_addr_width(struct hash_backet
*backet
, void *ctxt
)
274 char buf
[INET6_ADDRSTRLEN
];
275 struct neigh_walk_ctx
*wctx
= ctxt
;
278 n
= (zebra_neigh_t
*)backet
->data
;
282 ipaddr2str(&n
->ip
, buf
, sizeof(buf
)), width
= strlen(buf
);
283 if (width
> wctx
->addr_width
)
284 wctx
->addr_width
= width
;
288 * Print a specific neighbor entry.
290 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
293 char buf1
[ETHER_ADDR_STRLEN
];
294 char buf2
[INET6_ADDRSTRLEN
];
296 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
297 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
298 vty
= (struct vty
*)ctxt
;
300 vty_out(vty
, "IP: %s\n",
301 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
302 vty_out(vty
, " MAC: %s",
303 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
305 json_object_string_add(json
, "ip", buf2
);
306 json_object_string_add(json
, "mac", buf1
);
308 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
310 vty_out(vty
, " Remote VTEP: %s",
311 inet_ntoa(n
->r_vtep_ip
));
313 json_object_string_add(json
, "remoteVtep",
314 inet_ntoa(n
->r_vtep_ip
));
316 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
319 vty_out(vty
, " State: %s",
320 IS_ZEBRA_NEIGH_ACTIVE(n
) ? "Active"
324 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
326 vty_out(vty
, " Default-gateway");
328 json_object_boolean_true_add(json
, "defaultGateway");
335 * Print neighbor hash entry - called for display of all neighbors.
337 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
340 json_object
*json_vni
= NULL
, *json_row
= NULL
;
342 char buf1
[ETHER_ADDR_STRLEN
];
343 char buf2
[INET6_ADDRSTRLEN
];
344 struct neigh_walk_ctx
*wctx
= ctxt
;
347 json_vni
= wctx
->json
;
348 n
= (zebra_neigh_t
*)backet
->data
;
353 json_row
= json_object_new_object();
355 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
356 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
357 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)
358 && !(wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)) {
359 if (json_vni
== NULL
) {
360 vty_out(vty
, "%*s %-6s %-17s\n", -wctx
->addr_width
,
361 buf2
, "local", buf1
);
363 json_object_string_add(json_row
, "type", "local");
364 json_object_string_add(json_row
, "mac", buf1
);
368 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) {
369 if (IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
)) {
370 if (json_vni
== NULL
) {
371 if (wctx
->count
== 0)
373 "%*s %-6s %-17s %-21s\n",
376 "MAC", "Remote VTEP");
377 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
378 -wctx
->addr_width
, buf2
,
380 inet_ntoa(n
->r_vtep_ip
));
382 json_object_string_add(json_row
, "type",
384 json_object_string_add(json_row
, "mac",
386 json_object_string_add(
387 json_row
, "remoteVtep",
388 inet_ntoa(n
->r_vtep_ip
));
393 if (json_vni
== NULL
) {
394 vty_out(vty
, "%*s %-6s %-17s %-21s\n",
395 -wctx
->addr_width
, buf2
, "remote", buf1
,
396 inet_ntoa(n
->r_vtep_ip
));
398 json_object_string_add(json_row
, "type",
400 json_object_string_add(json_row
, "mac", buf1
);
401 json_object_string_add(json_row
, "remoteVtep",
402 inet_ntoa(n
->r_vtep_ip
));
409 json_object_object_add(json_vni
, buf2
, json_row
);
413 * Print neighbors for all VNI.
415 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
419 json_object
*json
= NULL
, *json_vni
= NULL
;
422 struct neigh_walk_ctx wctx
;
423 char vni_str
[VNI_STR_LEN
];
425 vty
= (struct vty
*)args
[0];
426 json
= (json_object
*)args
[1];
428 zvni
= (zebra_vni_t
*)backet
->data
;
431 vty_out(vty
, "{}\n");
434 num_neigh
= hashcount(zvni
->neigh_table
);
437 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
438 zvni
->vni
, num_neigh
);
440 json_vni
= json_object_new_object();
441 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
442 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
446 json_object_object_add(json
, vni_str
, json_vni
);
450 /* Since we have IPv6 addresses to deal with which can vary widely in
451 * size, we try to be a bit more elegant in display by first computing
454 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
457 wctx
.addr_width
= 15;
458 wctx
.json
= json_vni
;
459 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
462 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
463 "Type", "MAC", "Remote VTEP");
464 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
467 json_object_object_add(json
, vni_str
, json_vni
);
470 /* print a specific next hop for an l3vni */
471 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
474 char buf1
[ETHER_ADDR_STRLEN
];
475 char buf2
[INET6_ADDRSTRLEN
];
476 json_object
*json_hosts
= NULL
;
477 struct host_rb_entry
*hle
;
480 vty_out(vty
, "Ip: %s\n",
481 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
482 vty_out(vty
, " RMAC: %s\n",
483 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
484 vty_out(vty
, " Refcount: %d\n",
485 rb_host_count(&n
->host_rb
));
486 vty_out(vty
, " Prefixes:\n");
487 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
488 vty_out(vty
, " %s\n",
489 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
491 json_hosts
= json_object_new_array();
492 json_object_string_add(
493 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
494 json_object_string_add(
496 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
497 json_object_int_add(json
, "refCount",
498 rb_host_count(&n
->host_rb
));
499 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
500 json_object_array_add(json_hosts
,
501 json_object_new_string(prefix2str(
502 &hle
->p
, buf2
, sizeof(buf2
))));
503 json_object_object_add(json
, "prefixList", json_hosts
);
507 /* Print a specific RMAC entry */
508 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
511 char buf1
[ETHER_ADDR_STRLEN
];
512 char buf2
[PREFIX_STRLEN
];
513 json_object
*json_hosts
= NULL
;
514 struct host_rb_entry
*hle
;
517 vty_out(vty
, "MAC: %s\n",
518 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
519 vty_out(vty
, " Remote VTEP: %s\n",
520 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
521 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
522 vty_out(vty
, " Prefixes:\n");
523 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
524 vty_out(vty
, " %s\n",
525 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
527 json_hosts
= json_object_new_array();
528 json_object_string_add(
530 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
531 json_object_string_add(json
, "vtepIp",
532 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
533 json_object_int_add(json
, "refCount",
534 rb_host_count(&zrmac
->host_rb
));
535 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
536 json_object_array_add(
538 json_object_new_string(prefix2str(
539 &hle
->p
, buf2
, sizeof(buf2
))));
540 json_object_object_add(json
, "prefixList", json_hosts
);
545 * Print a specific MAC entry.
547 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
)
550 zebra_neigh_t
*n
= NULL
;
551 struct listnode
*node
= NULL
;
553 char buf2
[INET6_ADDRSTRLEN
];
555 vty
= (struct vty
*)ctxt
;
556 vty_out(vty
, "MAC: %s",
557 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
)));
558 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
559 struct zebra_ns
*zns
;
560 struct interface
*ifp
;
563 ifindex
= mac
->fwd_info
.local
.ifindex
;
564 zns
= zebra_ns_lookup(NS_DEFAULT
);
565 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
566 if (!ifp
) // unexpected
568 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
569 if (mac
->fwd_info
.local
.vid
)
570 vty_out(vty
, " VLAN: %u", mac
->fwd_info
.local
.vid
);
571 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
572 vty_out(vty
, " Remote VTEP: %s",
573 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
574 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
575 vty_out(vty
, " Auto Mac ");
578 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
579 vty_out(vty
, " Sticky Mac ");
581 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
582 vty_out(vty
, " Default-gateway Mac ");
584 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
585 vty_out(vty
, " Remote-gateway Mac ");
588 /* print all the associated neigh */
589 vty_out(vty
, " Neighbors:\n");
590 if (!listcount(mac
->neigh_list
))
591 vty_out(vty
, " No Neighbors\n");
593 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
594 vty_out(vty
, " %s %s\n",
595 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
596 CHECK_FLAG(n
->flags
, ZEBRA_MAC_LOCAL
)
597 ? (IS_ZEBRA_NEIGH_ACTIVE(n
)
608 * Print MAC hash entry - called for display of all MACs.
610 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
613 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
616 struct mac_walk_ctx
*wctx
= ctxt
;
619 json_mac_hdr
= wctx
->json
;
620 mac
= (zebra_mac_t
*)backet
->data
;
624 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
627 json_mac
= json_object_new_object();
629 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
630 && !(wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)) {
631 struct zebra_ns
*zns
;
633 struct interface
*ifp
;
636 zns
= zebra_ns_lookup(NS_DEFAULT
);
637 ifindex
= mac
->fwd_info
.local
.ifindex
;
638 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
639 if (!ifp
) // unexpected
641 vid
= mac
->fwd_info
.local
.vid
;
642 if (json_mac_hdr
== NULL
)
643 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
646 json_object_string_add(json_mac
, "type", "local");
647 json_object_string_add(json_mac
, "intf", ifp
->name
);
650 if (json_mac_hdr
== NULL
)
651 vty_out(vty
, " %-5u", vid
);
653 json_object_int_add(json_mac
, "vlan", vid
);
655 if (json_mac_hdr
== NULL
)
658 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
660 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
661 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) {
662 if (IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
664 if (wctx
->count
== 0) {
665 if (json_mac_hdr
== NULL
) {
666 vty_out(vty
, "\nVNI %u\n\n",
669 "%-17s %-6s %-21s %-5s\n",
675 if (json_mac_hdr
== NULL
)
676 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
678 inet_ntoa(mac
->fwd_info
681 json_object_string_add(json_mac
, "type",
683 json_object_string_add(
684 json_mac
, "remoteVtep",
685 inet_ntoa(mac
->fwd_info
687 json_object_object_add(json_mac_hdr
,
693 if (json_mac_hdr
== NULL
)
694 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
,
696 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
698 json_object_string_add(json_mac
, "type",
700 json_object_string_add(
701 json_mac
, "remoteVtep",
702 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
703 json_object_object_add(json_mac_hdr
, buf1
,
712 * Print MACs for all VNI.
714 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
717 json_object
*json
= NULL
, *json_vni
= NULL
;
718 json_object
*json_mac
= NULL
;
721 struct mac_walk_ctx
*wctx
= ctxt
;
722 char vni_str
[VNI_STR_LEN
];
724 vty
= (struct vty
*)wctx
->vty
;
725 json
= (struct json_object
*)wctx
->json
;
727 zvni
= (zebra_vni_t
*)backet
->data
;
730 vty_out(vty
, "{}\n");
735 /*We are iterating over a new VNI, set the count to 0*/
738 num_macs
= num_valid_macs(zvni
);
743 json_vni
= json_object_new_object();
744 json_mac
= json_object_new_object();
745 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
748 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
750 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
751 zvni
->vni
, num_macs
);
752 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
753 "Intf/Remote VTEP", "VLAN");
755 json_object_int_add(json_vni
, "numMacs", num_macs
);
757 /* assign per-vni to wctx->json object to fill macs
758 * under the vni. Re-assign primary json object to fill
759 * next vni information.
761 wctx
->json
= json_mac
;
762 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
766 json_object_object_add(json_vni
, "macs", json_mac
);
767 json_object_object_add(json
, vni_str
, json_vni
);
771 static void zl3vni_print_nh_hash(struct hash_backet
*backet
, void *ctx
)
773 struct nh_walk_ctx
*wctx
= NULL
;
774 struct vty
*vty
= NULL
;
775 struct json_object
*json_vni
= NULL
;
776 struct json_object
*json_nh
= NULL
;
777 zebra_neigh_t
*n
= NULL
;
778 char buf1
[ETHER_ADDR_STRLEN
];
779 char buf2
[INET6_ADDRSTRLEN
];
781 wctx
= (struct nh_walk_ctx
*)ctx
;
783 json_vni
= wctx
->json
;
785 json_nh
= json_object_new_object();
786 n
= (zebra_neigh_t
*)backet
->data
;
791 vty_out(vty
, "%-15s %-17s\n",
792 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
793 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
795 json_object_string_add(json_nh
, "nexthopIp",
796 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
797 json_object_string_add(
798 json_nh
, "routerMac",
799 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
800 json_object_object_add(json_vni
,
801 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
806 static void zl3vni_print_nh_hash_all_vni(struct hash_backet
*backet
,
809 struct vty
*vty
= NULL
;
810 json_object
*json
= NULL
;
811 json_object
*json_vni
= NULL
;
812 zebra_l3vni_t
*zl3vni
= NULL
;
814 struct nh_walk_ctx wctx
;
815 char vni_str
[VNI_STR_LEN
];
817 vty
= (struct vty
*)args
[0];
818 json
= (struct json_object
*)args
[1];
820 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
823 vty_out(vty
, "{}\n");
827 num_nh
= hashcount(zl3vni
->nh_table
);
832 json_vni
= json_object_new_object();
833 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
837 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
838 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
840 json_object_int_add(json_vni
, "numNextHops", num_nh
);
842 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
844 wctx
.json
= json_vni
;
845 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
847 json_object_object_add(json
, vni_str
, json_vni
);
850 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet
*backet
,
853 struct vty
*vty
= NULL
;
854 json_object
*json
= NULL
;
855 json_object
*json_vni
= NULL
;
856 zebra_l3vni_t
*zl3vni
= NULL
;
858 struct rmac_walk_ctx wctx
;
859 char vni_str
[VNI_STR_LEN
];
861 vty
= (struct vty
*)args
[0];
862 json
= (struct json_object
*)args
[1];
864 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
867 vty_out(vty
, "{}\n");
871 num_rmacs
= hashcount(zl3vni
->rmac_table
);
876 json_vni
= json_object_new_object();
877 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
881 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
882 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
884 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
886 /* assign per-vni to wctx->json object to fill macs
887 * under the vni. Re-assign primary json object to fill
888 * next vni information.
890 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
892 wctx
.json
= json_vni
;
893 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
895 json_object_object_add(json
, vni_str
, json_vni
);
898 static void zl3vni_print_rmac_hash(struct hash_backet
*backet
, void *ctx
)
900 zebra_mac_t
*zrmac
= NULL
;
901 struct rmac_walk_ctx
*wctx
= NULL
;
902 struct vty
*vty
= NULL
;
903 struct json_object
*json
= NULL
;
904 struct json_object
*json_rmac
= NULL
;
905 char buf
[ETHER_ADDR_STRLEN
];
907 wctx
= (struct rmac_walk_ctx
*)ctx
;
911 json_rmac
= json_object_new_object();
912 zrmac
= (zebra_mac_t
*)backet
->data
;
917 vty_out(vty
, "%-17s %-21s\n",
918 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
919 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
921 json_object_string_add(
922 json_rmac
, "routerMac",
923 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
924 json_object_string_add(json_rmac
, "vtepIp",
925 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
926 json_object_object_add(
927 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
932 /* print a specific L3 VNI entry */
933 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
935 char buf
[ETHER_ADDR_STRLEN
];
936 struct vty
*vty
= NULL
;
937 json_object
*json
= NULL
;
938 zebra_vni_t
*zvni
= NULL
;
939 json_object
*json_vni_list
= NULL
;
940 struct listnode
*node
= NULL
, *nnode
= NULL
;
946 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
947 vty_out(vty
, " Type: %s\n", "L3");
948 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
949 vty_out(vty
, " Local Vtep Ip: %s\n",
950 inet_ntoa(zl3vni
->local_vtep_ip
));
951 vty_out(vty
, " Vxlan-Intf: %s\n",
952 zl3vni_vxlan_if_name(zl3vni
));
953 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
954 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
955 vty_out(vty
, " VNI Filter: %s\n",
956 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
957 ? "prefix-routes-only"
959 vty_out(vty
, " Router MAC: %s\n",
960 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
961 vty_out(vty
, " L2 VNIs: ");
962 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
963 vty_out(vty
, "%u ", zvni
->vni
);
966 json_vni_list
= json_object_new_array();
967 json_object_int_add(json
, "vni", zl3vni
->vni
);
968 json_object_string_add(json
, "type", "L3");
969 json_object_string_add(json
, "localVtepIp",
970 inet_ntoa(zl3vni
->local_vtep_ip
));
971 json_object_string_add(json
, "vxlanIntf",
972 zl3vni_vxlan_if_name(zl3vni
));
973 json_object_string_add(json
, "sviIntf",
974 zl3vni_svi_if_name(zl3vni
));
975 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
976 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
977 json_object_string_add(
979 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
980 json_object_string_add(
982 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
983 ? "prefix-routes-only"
985 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
986 json_object_array_add(json_vni_list
,
987 json_object_new_int(zvni
->vni
));
989 json_object_object_add(json
, "l2Vnis", json_vni_list
);
994 * Print a specific VNI entry.
996 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1002 json_object
*json
= NULL
;
1003 json_object
*json_vtep_list
= NULL
;
1004 json_object
*json_ip_str
= NULL
;
1010 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1011 vty_out(vty
, " Type: %s\n", "L2");
1012 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1014 json_object_int_add(json
, "vni", zvni
->vni
);
1015 json_object_string_add(json
, "type", "L2");
1016 json_object_string_add(json
, "vrf",
1017 vrf_id_to_name(zvni
->vrf_id
));
1020 if (!zvni
->vxlan_if
) { // unexpected
1022 vty_out(vty
, " VxLAN interface: unknown\n");
1025 num_macs
= num_valid_macs(zvni
);
1026 num_neigh
= hashcount(zvni
->neigh_table
);
1028 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1029 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1030 vty_out(vty
, " Local VTEP IP: %s\n",
1031 inet_ntoa(zvni
->local_vtep_ip
));
1033 json_object_string_add(json
, "vxlanInterface",
1034 zvni
->vxlan_if
->name
);
1035 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1036 json_object_string_add(json
, "vtepIp",
1037 inet_ntoa(zvni
->local_vtep_ip
));
1038 json_object_string_add(json
, "advertiseGatewayMacip",
1039 zvni
->advertise_gw_macip
? "Yes" : "No");
1040 json_object_int_add(json
, "numMacs", num_macs
);
1041 json_object_int_add(json
, "numArpNd", num_neigh
);
1045 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1048 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1050 json_vtep_list
= json_object_new_array();
1051 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1053 vty_out(vty
, " %s\n",
1054 inet_ntoa(zvtep
->vtep_ip
));
1056 json_ip_str
= json_object_new_string(
1057 inet_ntoa(zvtep
->vtep_ip
));
1058 json_object_array_add(json_vtep_list
,
1063 json_object_object_add(json
, "numRemoteVteps",
1068 " Number of MACs (local and remote) known for this VNI: %u\n",
1071 " Number of ARPs (IPv4 and IPv6, local and remote) "
1072 "known for this VNI: %u\n",
1074 vty_out(vty
, " Advertise-gw-macip: %s\n",
1075 zvni
->advertise_gw_macip
? "Yes" : "No");
1079 /* print a L3 VNI hash entry */
1080 static void zl3vni_print_hash(struct hash_backet
*backet
, void *ctx
[])
1082 struct vty
*vty
= NULL
;
1083 json_object
*json
= NULL
;
1084 json_object
*json_vni
= NULL
;
1085 zebra_l3vni_t
*zl3vni
= NULL
;
1087 vty
= (struct vty
*)ctx
[0];
1088 json
= (json_object
*)ctx
[1];
1090 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1095 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1096 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1097 hashcount(zl3vni
->rmac_table
),
1098 hashcount(zl3vni
->nh_table
), "n/a",
1099 zl3vni_vrf_name(zl3vni
));
1101 char vni_str
[VNI_STR_LEN
];
1103 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1104 json_vni
= json_object_new_object();
1105 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1106 json_object_string_add(json_vni
, "vxlanIf",
1107 zl3vni_vxlan_if_name(zl3vni
));
1108 json_object_int_add(json_vni
, "numMacs",
1109 hashcount(zl3vni
->rmac_table
));
1110 json_object_int_add(json_vni
, "numArpNd",
1111 hashcount(zl3vni
->nh_table
));
1112 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1113 json_object_string_add(json_vni
, "type", "L3");
1114 json_object_string_add(json_vni
, "tenantVrf",
1115 zl3vni_vrf_name(zl3vni
));
1116 json_object_object_add(json
, vni_str
, json_vni
);
1121 * Print a VNI hash entry - called for display of all VNIs.
1123 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1127 zebra_vtep_t
*zvtep
;
1128 uint32_t num_vteps
= 0;
1129 uint32_t num_macs
= 0;
1130 uint32_t num_neigh
= 0;
1131 json_object
*json
= NULL
;
1132 json_object
*json_vni
= NULL
;
1133 json_object
*json_ip_str
= NULL
;
1134 json_object
*json_vtep_list
= NULL
;
1139 zvni
= (zebra_vni_t
*)backet
->data
;
1143 zvtep
= zvni
->vteps
;
1146 zvtep
= zvtep
->next
;
1149 num_macs
= num_valid_macs(zvni
);
1150 num_neigh
= hashcount(zvni
->neigh_table
);
1152 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1154 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1155 num_macs
, num_neigh
, num_vteps
,
1156 vrf_id_to_name(zvni
->vrf_id
));
1158 char vni_str
[VNI_STR_LEN
];
1159 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1160 json_vni
= json_object_new_object();
1161 json_object_int_add(json_vni
, "vni", zvni
->vni
);
1162 json_object_string_add(json_vni
, "type", "L2");
1163 json_object_string_add(json_vni
, "vxlanIf",
1164 zvni
->vxlan_if
? zvni
->vxlan_if
->name
1166 json_object_int_add(json_vni
, "numMacs", num_macs
);
1167 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1168 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
1169 json_object_string_add(json_vni
, "tenantVrf",
1170 vrf_id_to_name(zvni
->vrf_id
));
1172 json_vtep_list
= json_object_new_array();
1173 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1174 json_ip_str
= json_object_new_string(
1175 inet_ntoa(zvtep
->vtep_ip
));
1176 json_object_array_add(json_vtep_list
,
1179 json_object_object_add(json_vni
, "remoteVteps",
1182 json_object_object_add(json
, vni_str
, json_vni
);
1187 * Inform BGP about local MACIP.
1189 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
1190 struct ipaddr
*ip
, uint8_t flags
,
1193 char buf
[ETHER_ADDR_STRLEN
];
1194 char buf2
[INET6_ADDRSTRLEN
];
1196 struct zserv
*client
= NULL
;
1197 struct stream
*s
= NULL
;
1199 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
1200 /* BGP may not be running. */
1204 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
1206 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
1207 stream_putl(s
, vni
);
1208 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
1211 if (IS_IPADDR_V4(ip
))
1212 ipa_len
= IPV4_MAX_BYTELEN
;
1213 else if (IS_IPADDR_V6(ip
))
1214 ipa_len
= IPV6_MAX_BYTELEN
;
1216 stream_putl(s
, ipa_len
); /* IP address length */
1218 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
1220 stream_putl(s
, 0); /* Just MAC. */
1222 stream_putc(s
, flags
); /* sticky mac/gateway mac */
1225 /* Write packet size. */
1226 stream_putw_at(s
, 0, stream_get_endp(s
));
1228 if (IS_ZEBRA_DEBUG_VXLAN
)
1230 "Send MACIP %s flags 0x%x MAC %s IP %s L2-VNI %u to %s",
1231 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
1232 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1233 ipaddr2str(ip
, buf2
, sizeof(buf2
)), vni
,
1234 zebra_route_string(client
->proto
));
1236 if (cmd
== ZEBRA_MACIP_ADD
)
1237 client
->macipadd_cnt
++;
1239 client
->macipdel_cnt
++;
1241 return zserv_send_message(client
, s
);
1245 * Make hash key for neighbors.
1247 static unsigned int neigh_hash_keymake(void *p
)
1249 zebra_neigh_t
*n
= p
;
1250 struct ipaddr
*ip
= &n
->ip
;
1252 if (IS_IPADDR_V4(ip
))
1253 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
1255 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
1256 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
1260 * Compare two neighbor hash structures.
1262 static int neigh_cmp(const void *p1
, const void *p2
)
1264 const zebra_neigh_t
*n1
= p1
;
1265 const zebra_neigh_t
*n2
= p2
;
1267 if (n1
== NULL
&& n2
== NULL
)
1270 if (n1
== NULL
|| n2
== NULL
)
1273 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
1277 * Callback to allocate neighbor hash entry.
1279 static void *zvni_neigh_alloc(void *p
)
1281 const zebra_neigh_t
*tmp_n
= p
;
1284 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
1291 * Add neighbor entry.
1293 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
1294 struct ethaddr
*mac
)
1296 zebra_neigh_t tmp_n
;
1297 zebra_neigh_t
*n
= NULL
;
1298 zebra_mac_t
*zmac
= NULL
;
1300 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
1301 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1302 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
1305 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1306 n
->state
= ZEBRA_NEIGH_INACTIVE
;
1308 /* Associate the neigh to mac */
1309 zmac
= zvni_mac_lookup(zvni
, mac
);
1311 listnode_add_sort(zmac
->neigh_list
, n
);
1317 * Delete neighbor entry.
1319 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1321 zebra_neigh_t
*tmp_n
;
1322 zebra_mac_t
*zmac
= NULL
;
1324 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
1326 listnode_delete(zmac
->neigh_list
, n
);
1328 /* Free the VNI hash entry and allocated memory. */
1329 tmp_n
= hash_release(zvni
->neigh_table
, n
);
1331 XFREE(MTYPE_NEIGH
, tmp_n
);
1337 * Free neighbor hash entry (callback)
1339 static void zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
1341 struct neigh_walk_ctx
*wctx
= arg
;
1342 zebra_neigh_t
*n
= backet
->data
;
1344 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1345 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
1346 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
1347 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
1348 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
1349 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
1350 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1351 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
1354 if (wctx
->uninstall
)
1355 zvni_neigh_uninstall(wctx
->zvni
, n
);
1357 zvni_neigh_del(wctx
->zvni
, n
);
1364 * Delete all neighbor entries from specific VTEP for a particular VNI.
1366 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
1367 struct in_addr
*r_vtep_ip
)
1369 struct neigh_walk_ctx wctx
;
1371 if (!zvni
->neigh_table
)
1374 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1376 wctx
.uninstall
= uninstall
;
1377 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
1378 wctx
.r_vtep_ip
= *r_vtep_ip
;
1380 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1384 * Delete all neighbor entries for this VNI.
1386 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
1389 struct neigh_walk_ctx wctx
;
1391 if (!zvni
->neigh_table
)
1394 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1396 wctx
.uninstall
= uninstall
;
1397 wctx
.upd_client
= upd_client
;
1400 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
1404 * Look up neighbor hash entry.
1406 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
1411 memset(&tmp
, 0, sizeof(tmp
));
1412 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
1413 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
1418 /* Process all neigh associated to a mac upon local mac add event */
1419 static void zvni_process_neigh_on_local_mac_add(zebra_vni_t
*zvni
,
1422 zebra_neigh_t
*n
= NULL
;
1423 struct listnode
*node
= NULL
;
1424 char buf
[ETHER_ADDR_STRLEN
];
1425 char buf2
[INET6_ADDRSTRLEN
];
1427 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1428 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1429 /* MAC is learnt locally, program all inactive neigh
1430 * pointing to this mac */
1431 if (IS_ZEBRA_NEIGH_INACTIVE(n
)) {
1432 if (IS_ZEBRA_DEBUG_VXLAN
)
1434 "neigh %s (MAC %s) on L2-VNI %u is now ACTIVE",
1435 ipaddr2str(&n
->ip
, buf2
,
1437 prefix_mac2str(&n
->emac
, buf
,
1441 ZEBRA_NEIGH_SET_ACTIVE(n
);
1442 zvni_neigh_send_add_to_client(
1443 zvni
->vni
, &n
->ip
, &n
->emac
, n
->flags
);
1445 if (IS_ZEBRA_DEBUG_VXLAN
)
1447 "neigh %s (MAC %s) on VNI %u should NOT be ACTIVE",
1448 ipaddr2str(&n
->ip
, buf2
,
1450 prefix_mac2str(&n
->emac
, buf
,
1454 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1455 /* TODO: assume the neigh has moved too ?? */
1460 /* Process all neigh associated to a mac upon local mac del event */
1461 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
1464 zebra_neigh_t
*n
= NULL
;
1465 struct listnode
*node
= NULL
;
1466 char buf
[ETHER_ADDR_STRLEN
];
1467 char buf2
[INET6_ADDRSTRLEN
];
1469 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1470 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1471 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1472 if (IS_ZEBRA_DEBUG_VXLAN
)
1474 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1475 ipaddr2str(&n
->ip
, buf2
,
1477 prefix_mac2str(&n
->emac
, buf
,
1481 ZEBRA_NEIGH_SET_INACTIVE(n
);
1482 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1485 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
1486 if (IS_ZEBRA_DEBUG_VXLAN
)
1488 "local MAC %s getting deleted on VNI %u has remote neigh %s",
1489 prefix_mac2str(&n
->emac
, buf
,
1492 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1497 /* process all neigh associated to a mac entry upon remote mac add */
1498 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
1501 zebra_neigh_t
*n
= NULL
;
1502 struct listnode
*node
= NULL
;
1503 char buf
[ETHER_ADDR_STRLEN
];
1504 char buf2
[INET6_ADDRSTRLEN
];
1506 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1507 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1508 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
1509 if (IS_ZEBRA_DEBUG_VXLAN
)
1511 "neigh %s (MAC %s) on L2-VNI %u is now INACTIVE",
1512 ipaddr2str(&n
->ip
, buf2
,
1514 prefix_mac2str(&n
->emac
, buf
,
1518 ZEBRA_NEIGH_SET_INACTIVE(n
);
1519 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
1526 /* process all neigh associated to mac entry upon remote mac del */
1527 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
1530 zebra_neigh_t
*n
= NULL
;
1531 struct listnode
*node
= NULL
;
1532 char buf
[ETHER_ADDR_STRLEN
];
1533 char buf2
[INET6_ADDRSTRLEN
];
1535 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
1536 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
1537 if (IS_ZEBRA_DEBUG_VXLAN
)
1539 "remote MAC %s getting deleted on VNI %u has local neigh %s",
1540 prefix_mac2str(&n
->emac
, buf
,
1543 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1549 * Inform BGP about local neighbor addition.
1551 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
1552 struct ethaddr
*macaddr
,
1553 uint8_t neigh_flags
)
1557 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
1558 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
1560 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1565 * Inform BGP about local neighbor deletion.
1567 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
1568 struct ethaddr
*macaddr
, uint8_t flags
)
1570 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
1575 * Install remote neighbor into the kernel.
1577 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1579 struct zebra_if
*zif
;
1580 struct zebra_l2info_vxlan
*vxl
;
1581 struct interface
*vlan_if
;
1583 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1586 zif
= zvni
->vxlan_if
->info
;
1589 vxl
= &zif
->l2info
.vxl
;
1591 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1595 return kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
);
1599 * Uninstall remote neighbor from the kernel.
1601 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1603 struct zebra_if
*zif
;
1604 struct zebra_l2info_vxlan
*vxl
;
1605 struct interface
*vlan_if
;
1607 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
1610 if (!zvni
->vxlan_if
) {
1611 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
1616 zif
= zvni
->vxlan_if
->info
;
1619 vxl
= &zif
->l2info
.vxl
;
1620 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1624 return kernel_del_neigh(vlan_if
, &n
->ip
);
1628 * Install neighbor hash entry - called upon access VLAN change.
1630 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
1633 struct neigh_walk_ctx
*wctx
= ctxt
;
1635 n
= (zebra_neigh_t
*)backet
->data
;
1639 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
1640 zvni_neigh_install(wctx
->zvni
, n
);
1643 /* Get the VRR interface for SVI if any */
1644 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
1646 struct zebra_vrf
*zvrf
= NULL
;
1647 struct interface
*tmp_if
= NULL
;
1648 struct zebra_if
*zif
= NULL
;
1650 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
1653 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
1658 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
1661 if (zif
->link
== ifp
)
1668 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1670 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1671 struct connected
*c
= NULL
;
1672 struct ethaddr macaddr
;
1674 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1676 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1679 memset(&ip
, 0, sizeof(struct ipaddr
));
1680 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1683 if (c
->address
->family
== AF_INET
) {
1684 ip
.ipa_type
= IPADDR_V4
;
1685 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1686 sizeof(struct in_addr
));
1687 } else if (c
->address
->family
== AF_INET6
) {
1688 ip
.ipa_type
= IPADDR_V6
;
1689 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1690 sizeof(struct in6_addr
));
1695 zvni_gw_macip_del(ifp
, zvni
, &ip
);
1701 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
1703 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1704 struct connected
*c
= NULL
;
1705 struct ethaddr macaddr
;
1707 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1709 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1712 memset(&ip
, 0, sizeof(struct ipaddr
));
1713 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
1716 if (c
->address
->family
== AF_INET
) {
1717 ip
.ipa_type
= IPADDR_V4
;
1718 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
1719 sizeof(struct in_addr
));
1720 } else if (c
->address
->family
== AF_INET6
) {
1721 ip
.ipa_type
= IPADDR_V6
;
1722 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
1723 sizeof(struct in6_addr
));
1728 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
1734 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
1737 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
1738 struct connected
*c
= NULL
;
1739 struct ethaddr macaddr
;
1741 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
1743 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
1746 memcpy(&p
, c
->address
, sizeof(struct prefix
));
1748 /* skip link local address */
1749 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
1754 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1755 ZEBRA_IP_PREFIX_ROUTE_ADD
);
1757 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
1758 ZEBRA_IP_PREFIX_ROUTE_DEL
);
1764 * zvni_gw_macip_add_to_client
1766 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
1767 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
1769 char buf
[ETHER_ADDR_STRLEN
];
1770 char buf2
[INET6_ADDRSTRLEN
];
1771 zebra_neigh_t
*n
= NULL
;
1772 zebra_mac_t
*mac
= NULL
;
1773 struct zebra_if
*zif
= NULL
;
1774 struct zebra_l2info_vxlan
*vxl
= NULL
;
1776 zif
= zvni
->vxlan_if
->info
;
1780 vxl
= &zif
->l2info
.vxl
;
1782 mac
= zvni_mac_lookup(zvni
, macaddr
);
1784 mac
= zvni_mac_add(zvni
, macaddr
);
1786 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
1787 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1788 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
1793 /* Set "local" forwarding info. */
1794 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
1795 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
1796 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
1797 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
1798 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
1799 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
1801 n
= zvni_neigh_lookup(zvni
, ip
);
1803 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
1806 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1807 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
1808 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1809 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
1814 /* Set "local" forwarding info. */
1815 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
1816 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
1817 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
1818 n
->ifindex
= ifp
->ifindex
;
1820 /* Only advertise in BGP if the knob is enabled */
1821 if (!advertise_gw_macip_enabled(zvni
))
1824 if (IS_ZEBRA_DEBUG_VXLAN
)
1826 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP",
1827 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1828 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1829 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1831 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, n
->flags
);
1837 * zvni_gw_macip_del_from_client
1839 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
1842 char buf1
[ETHER_ADDR_STRLEN
];
1843 char buf2
[INET6_ADDRSTRLEN
];
1844 zebra_neigh_t
*n
= NULL
;
1845 zebra_mac_t
*mac
= NULL
;
1847 /* If the neigh entry is not present nothing to do*/
1848 n
= zvni_neigh_lookup(zvni
, ip
);
1852 /* mac entry should be present */
1853 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
1855 zlog_err("MAC %s doesnt exists for neigh %s on VNI %u",
1856 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
1857 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1861 /* If the entry is not local nothing to do*/
1862 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
1865 /* only need to delete the entry from bgp if we sent it before */
1866 if (IS_ZEBRA_DEBUG_VXLAN
)
1868 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
1869 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
1870 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
1871 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
1873 /* Remove neighbor from BGP. */
1874 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
1875 ZEBRA_MACIP_TYPE_GW
);
1877 /* Delete this neighbor entry. */
1878 zvni_neigh_del(zvni
, n
);
1880 /* see if the mac needs to be deleted as well*/
1882 zvni_deref_ip2mac(zvni
, mac
, 0);
1887 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
1890 zebra_vni_t
*zvni
= NULL
;
1891 struct zebra_if
*zif
= NULL
;
1892 struct zebra_l2info_vxlan zl2_info
;
1893 struct interface
*vlan_if
= NULL
;
1894 struct interface
*vrr_if
= NULL
;
1895 struct interface
*ifp
;
1897 /* Add primary SVI MAC*/
1898 zvni
= (zebra_vni_t
*)backet
->data
;
1902 ifp
= zvni
->vxlan_if
;
1907 /* If down or not mapped to a bridge, we're done. */
1908 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1911 zl2_info
= zif
->l2info
.vxl
;
1914 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1918 /* Del primary MAC-IP */
1919 zvni_del_macip_for_intf(vlan_if
, zvni
);
1921 /* Del VRR MAC-IP - if any*/
1922 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1924 zvni_del_macip_for_intf(vrr_if
, zvni
);
1929 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
1932 zebra_vni_t
*zvni
= NULL
;
1933 struct zebra_if
*zif
= NULL
;
1934 struct zebra_l2info_vxlan zl2_info
;
1935 struct interface
*vlan_if
= NULL
;
1936 struct interface
*vrr_if
= NULL
;
1937 struct interface
*ifp
= NULL
;
1939 zvni
= (zebra_vni_t
*)backet
->data
;
1943 ifp
= zvni
->vxlan_if
;
1948 /* If down or not mapped to a bridge, we're done. */
1949 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
1951 zl2_info
= zif
->l2info
.vxl
;
1954 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
1958 /* Add primary SVI MAC-IP */
1959 zvni_add_macip_for_intf(vlan_if
, zvni
);
1961 /* Add VRR MAC-IP - if any*/
1962 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
1964 zvni_add_macip_for_intf(vrr_if
, zvni
);
1969 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
1970 struct interface
*ifp
,
1972 struct ethaddr
*macaddr
)
1974 char buf
[ETHER_ADDR_STRLEN
];
1975 char buf2
[INET6_ADDRSTRLEN
];
1976 zebra_neigh_t
*n
= NULL
;
1977 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
1979 /* create a dummy MAC if the MAC is not already present */
1980 zmac
= zvni_mac_lookup(zvni
, macaddr
);
1982 if (IS_ZEBRA_DEBUG_VXLAN
)
1984 "AUTO MAC %s created for neigh %s on VNI %u",
1985 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1986 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
1988 zmac
= zvni_mac_add(zvni
, macaddr
);
1990 zlog_warn("Failed to add MAC %s VNI %u",
1991 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1996 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
1997 memset(&zmac
->flags
, 0, sizeof(uint32_t));
1998 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2001 /* If same entry already exists, it might be a change or it might be a
2002 * move from remote to local.
2004 n
= zvni_neigh_lookup(zvni
, ip
);
2006 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2007 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2009 /* Update any params and return - client doesn't
2010 * care about a purely local change.
2012 n
->ifindex
= ifp
->ifindex
;
2016 /* If the MAC has changed,
2017 * need to issue a delete first
2018 * as this means a different MACIP route.
2019 * Also, need to do some unlinking/relinking.
2021 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2023 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2025 listnode_delete(old_zmac
->neigh_list
, n
);
2026 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
2029 /* Update the forwarding info. */
2030 n
->ifindex
= ifp
->ifindex
;
2031 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2033 /* Link to new MAC */
2034 listnode_add_sort(zmac
->neigh_list
, n
);
2037 /* Neighbor has moved from remote to local. */
2039 /* If MAC has changed, do the unlink/link */
2040 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2042 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2044 listnode_delete(old_zmac
->neigh_list
,
2046 zvni_deref_ip2mac(zvni
, old_zmac
, 0);
2049 /* Link to new MAC */
2050 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2051 listnode_add_sort(zmac
->neigh_list
, n
);
2054 /* Mark appropriately */
2055 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2056 n
->r_vtep_ip
.s_addr
= 0;
2057 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2058 n
->ifindex
= ifp
->ifindex
;
2061 /* New neighbor - create */
2062 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2065 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2066 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2067 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2068 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2071 /* Set "local" forwarding info. */
2072 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2073 n
->ifindex
= ifp
->ifindex
;
2076 /* Before we program this in BGP, we need to check if MAC is locally
2079 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
2080 if (IS_ZEBRA_DEBUG_VXLAN
)
2082 "Skipping neigh %s add to client as MAC %s is not local on VNI %u",
2083 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2084 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2091 if (IS_ZEBRA_DEBUG_VXLAN
)
2092 zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u",
2093 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2094 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2096 ZEBRA_NEIGH_SET_ACTIVE(n
);
2098 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
, 0);
2101 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
2102 struct interface
*ifp
,
2104 struct ethaddr
*macaddr
,
2107 char buf
[ETHER_ADDR_STRLEN
];
2108 char buf2
[INET6_ADDRSTRLEN
];
2109 zebra_neigh_t
*n
= NULL
;
2110 zebra_mac_t
*zmac
= NULL
;
2112 /* If the neighbor is unknown, there is no further action. */
2113 n
= zvni_neigh_lookup(zvni
, ip
);
2117 /* If a remote entry, see if it needs to be refreshed */
2118 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2120 if (state
& NUD_STALE
)
2121 zvni_neigh_install(zvni
, n
);
2124 /* We got a "remote" neighbor notification for an entry
2125 * we think is local. This can happen in a multihoming
2126 * scenario - but only if the MAC is already "remote".
2127 * Just mark our entry as "remote".
2129 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2130 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2131 zlog_err("Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
2132 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
2133 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2138 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2139 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2140 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
2147 * Make hash key for MAC.
2149 static unsigned int mac_hash_keymake(void *p
)
2151 zebra_mac_t
*pmac
= p
;
2152 const void *pnt
= (void *)pmac
->macaddr
.octet
;
2154 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
2158 * Compare two MAC addresses.
2160 static int mac_cmp(const void *p1
, const void *p2
)
2162 const zebra_mac_t
*pmac1
= p1
;
2163 const zebra_mac_t
*pmac2
= p2
;
2165 if (pmac1
== NULL
&& pmac2
== NULL
)
2168 if (pmac1
== NULL
|| pmac2
== NULL
)
2171 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
2176 * Callback to allocate MAC hash entry.
2178 static void *zvni_mac_alloc(void *p
)
2180 const zebra_mac_t
*tmp_mac
= p
;
2183 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2186 return ((void *)mac
);
2192 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
2194 zebra_mac_t tmp_mac
;
2195 zebra_mac_t
*mac
= NULL
;
2197 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
2198 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
2199 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
2202 mac
->neigh_list
= list_new();
2203 mac
->neigh_list
->cmp
= (int (*)(void *, void *))neigh_cmp
;
2211 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2213 zebra_mac_t
*tmp_mac
;
2215 list_delete_and_null(&mac
->neigh_list
);
2217 /* Free the VNI hash entry and allocated memory. */
2218 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
2220 XFREE(MTYPE_MAC
, tmp_mac
);
2226 * Free MAC hash entry (callback)
2228 static void zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2230 struct mac_walk_ctx
*wctx
= arg
;
2231 zebra_mac_t
*mac
= backet
->data
;
2233 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
2234 || ((wctx
->flags
& DEL_REMOTE_MAC
)
2235 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
2236 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
2237 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
2238 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
2239 &wctx
->r_vtep_ip
))) {
2240 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
2241 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
2242 &mac
->macaddr
, mac
->flags
);
2245 if (wctx
->uninstall
)
2246 zvni_mac_uninstall(wctx
->zvni
, mac
, 0);
2248 zvni_mac_del(wctx
->zvni
, mac
);
2255 * Delete all MAC entries from specific VTEP for a particular VNI.
2257 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2258 struct in_addr
*r_vtep_ip
)
2260 struct mac_walk_ctx wctx
;
2262 if (!zvni
->mac_table
)
2265 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2267 wctx
.uninstall
= uninstall
;
2268 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
2269 wctx
.r_vtep_ip
= *r_vtep_ip
;
2271 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2275 * Delete all MAC entries for this VNI.
2277 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2280 struct mac_walk_ctx wctx
;
2282 if (!zvni
->mac_table
)
2285 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2287 wctx
.uninstall
= uninstall
;
2288 wctx
.upd_client
= upd_client
;
2291 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
2295 * Look up MAC hash entry.
2297 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
2302 memset(&tmp
, 0, sizeof(tmp
));
2303 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
2304 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
2310 * Inform BGP about local MAC addition.
2312 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2317 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2318 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2319 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2320 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2322 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2327 * Inform BGP about local MAC deletion.
2329 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2334 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
2335 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
2336 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
2337 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2339 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
2344 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
2345 * notifications, to see if they are of interest.
2347 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
2348 struct interface
*br_if
, vlanid_t vid
)
2350 struct zebra_ns
*zns
;
2351 struct route_node
*rn
;
2352 struct interface
*tmp_if
= NULL
;
2353 struct zebra_if
*zif
;
2354 struct zebra_l2info_bridge
*br
;
2355 struct zebra_l2info_vxlan
*vxl
= NULL
;
2356 uint8_t bridge_vlan_aware
;
2360 /* Determine if bridge is VLAN-aware or not */
2363 br
= &zif
->l2info
.br
;
2364 bridge_vlan_aware
= br
->vlan_aware
;
2366 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2367 /* TODO: Optimize with a hash. */
2368 zns
= zebra_ns_lookup(NS_DEFAULT
);
2369 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2370 tmp_if
= (struct interface
*)rn
->info
;
2374 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2376 if (!if_is_operative(tmp_if
))
2378 vxl
= &zif
->l2info
.vxl
;
2380 if (zif
->brslave_info
.br_if
!= br_if
)
2383 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2392 zvni
= zvni_lookup(vxl
->vni
);
2397 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2398 * neighbor notifications, to see if they are of interest.
2400 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
2401 struct interface
*br_if
)
2403 struct zebra_ns
*zns
;
2404 struct route_node
*rn
;
2405 struct interface
*tmp_if
= NULL
;
2406 struct zebra_if
*zif
;
2407 struct zebra_l2info_bridge
*br
;
2408 struct zebra_l2info_vxlan
*vxl
= NULL
;
2409 uint8_t bridge_vlan_aware
;
2417 /* Make sure the linked interface is a bridge. */
2418 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
2421 /* Determine if bridge is VLAN-aware or not */
2424 br
= &zif
->l2info
.br
;
2425 bridge_vlan_aware
= br
->vlan_aware
;
2426 if (bridge_vlan_aware
) {
2427 struct zebra_l2info_vlan
*vl
;
2429 if (!IS_ZEBRA_IF_VLAN(ifp
))
2434 vl
= &zif
->l2info
.vl
;
2438 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2439 /* TODO: Optimize with a hash. */
2440 zns
= zebra_ns_lookup(NS_DEFAULT
);
2441 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2442 tmp_if
= (struct interface
*)rn
->info
;
2446 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2448 if (!if_is_operative(tmp_if
))
2450 vxl
= &zif
->l2info
.vxl
;
2452 if (zif
->brslave_info
.br_if
!= br_if
)
2455 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
2464 zvni
= zvni_lookup(vxl
->vni
);
2468 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
2470 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
2471 * linked to the bridge
2472 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
2475 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
2477 struct zebra_ns
*zns
;
2478 struct route_node
*rn
;
2479 struct interface
*tmp_if
= NULL
;
2480 struct zebra_if
*zif
;
2481 struct zebra_l2info_bridge
*br
;
2482 struct zebra_l2info_vlan
*vl
;
2483 uint8_t bridge_vlan_aware
;
2486 /* Defensive check, caller expected to invoke only with valid bridge. */
2490 /* Determine if bridge is VLAN-aware or not */
2493 br
= &zif
->l2info
.br
;
2494 bridge_vlan_aware
= br
->vlan_aware
;
2496 /* Check oper status of the SVI. */
2497 if (!bridge_vlan_aware
)
2498 return if_is_operative(br_if
) ? br_if
: NULL
;
2500 /* Identify corresponding VLAN interface. */
2501 /* TODO: Optimize with a hash. */
2502 zns
= zebra_ns_lookup(NS_DEFAULT
);
2503 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2504 tmp_if
= (struct interface
*)rn
->info
;
2505 /* Check oper status of the SVI. */
2506 if (!tmp_if
|| !if_is_operative(tmp_if
))
2509 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
2510 || zif
->link
!= br_if
)
2512 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
2514 if (vl
->vid
== vid
) {
2520 return found
? tmp_if
: NULL
;
2524 * Install remote MAC into the kernel.
2526 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2528 struct zebra_if
*zif
;
2529 struct zebra_l2info_vxlan
*vxl
;
2532 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
2535 zif
= zvni
->vxlan_if
->info
;
2538 vxl
= &zif
->l2info
.vxl
;
2540 sticky
= CHECK_FLAG(mac
->flags
,
2541 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
)) ? 1 : 0;
2543 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
2544 mac
->fwd_info
.r_vtep_ip
, sticky
);
2548 * Uninstall remote MAC from the kernel. In the scenario where the MAC
2549 * moves to remote, we have to uninstall any existing local entry first.
2551 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
, int local
)
2553 struct zebra_if
*zif
;
2554 struct zebra_l2info_vxlan
*vxl
;
2555 struct in_addr vtep_ip
= {.s_addr
= 0};
2556 struct zebra_ns
*zns
;
2557 struct interface
*ifp
;
2559 if (!local
&& !(mac
->flags
& ZEBRA_MAC_REMOTE
))
2562 if (!zvni
->vxlan_if
) {
2563 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
2568 zif
= zvni
->vxlan_if
->info
;
2571 vxl
= &zif
->l2info
.vxl
;
2574 zns
= zebra_ns_lookup(NS_DEFAULT
);
2575 ifp
= if_lookup_by_index_per_ns(zns
,
2576 mac
->fwd_info
.local
.ifindex
);
2577 if (!ifp
) // unexpected
2580 ifp
= zvni
->vxlan_if
;
2581 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
2584 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
,
2589 * Install MAC hash entry - called upon access VLAN change.
2591 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
2594 struct mac_walk_ctx
*wctx
= ctxt
;
2596 mac
= (zebra_mac_t
*)backet
->data
;
2600 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
2601 zvni_mac_install(wctx
->zvni
, mac
);
2605 * Decrement neighbor refcount of MAC; uninstall and free it if
2608 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
,
2611 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)
2612 || !list_isempty(mac
->neigh_list
))
2616 zvni_mac_uninstall(zvni
, mac
, 0);
2618 zvni_mac_del(zvni
, mac
);
2622 * Read and populate local MACs and neighbors corresponding to this VNI.
2624 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
2626 struct zebra_ns
*zns
;
2627 struct zebra_if
*zif
;
2628 struct interface
*vlan_if
;
2629 struct zebra_l2info_vxlan
*vxl
;
2630 struct interface
*vrr_if
;
2633 vxl
= &zif
->l2info
.vxl
;
2634 zns
= zebra_ns_lookup(NS_DEFAULT
);
2636 if (IS_ZEBRA_DEBUG_VXLAN
)
2638 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
2639 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2640 zif
->brslave_info
.bridge_ifindex
);
2642 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
2643 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2646 /* Add SVI MAC-IP */
2647 zvni_add_macip_for_intf(vlan_if
, zvni
);
2649 /* Add VRR MAC-IP - if any*/
2650 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2652 zvni_add_macip_for_intf(vrr_if
, zvni
);
2654 neigh_read_for_vlan(zns
, vlan_if
);
2659 * Hash function for VNI.
2661 static unsigned int vni_hash_keymake(void *p
)
2663 const zebra_vni_t
*zvni
= p
;
2665 return (jhash_1word(zvni
->vni
, 0));
2669 * Compare 2 VNI hash entries.
2671 static int vni_hash_cmp(const void *p1
, const void *p2
)
2673 const zebra_vni_t
*zvni1
= p1
;
2674 const zebra_vni_t
*zvni2
= p2
;
2676 return (zvni1
->vni
== zvni2
->vni
);
2680 * Callback to allocate VNI hash entry.
2682 static void *zvni_alloc(void *p
)
2684 const zebra_vni_t
*tmp_vni
= p
;
2687 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
2688 zvni
->vni
= tmp_vni
->vni
;
2689 return ((void *)zvni
);
2693 * Look up VNI hash entry.
2695 static zebra_vni_t
*zvni_lookup(vni_t vni
)
2697 struct zebra_vrf
*zvrf
;
2698 zebra_vni_t tmp_vni
;
2699 zebra_vni_t
*zvni
= NULL
;
2701 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2703 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
2705 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
2711 * Add VNI hash entry.
2713 static zebra_vni_t
*zvni_add(vni_t vni
)
2715 struct zebra_vrf
*zvrf
;
2716 zebra_vni_t tmp_zvni
;
2717 zebra_vni_t
*zvni
= NULL
;
2719 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2721 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
2723 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
2726 /* Create hash table for MAC */
2728 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
2730 /* Create hash table for neighbors */
2731 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
2732 "Zebra VNI Neighbor Table");
2738 * Delete VNI hash entry.
2740 static int zvni_del(zebra_vni_t
*zvni
)
2742 struct zebra_vrf
*zvrf
;
2743 zebra_vni_t
*tmp_zvni
;
2745 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2748 zvni
->vxlan_if
= NULL
;
2750 /* Free the neighbor hash table. */
2751 hash_free(zvni
->neigh_table
);
2752 zvni
->neigh_table
= NULL
;
2754 /* Free the MAC hash table. */
2755 hash_free(zvni
->mac_table
);
2756 zvni
->mac_table
= NULL
;
2758 /* Free the VNI hash entry and allocated memory. */
2759 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
2761 XFREE(MTYPE_ZVNI
, tmp_zvni
);
2767 * Inform BGP about local VNI addition.
2769 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
2771 struct zserv
*client
;
2774 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2775 /* BGP may not be running. */
2779 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2781 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
2782 stream_putl(s
, zvni
->vni
);
2783 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
2784 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
2786 /* Write packet size. */
2787 stream_putw_at(s
, 0, stream_get_endp(s
));
2789 if (IS_ZEBRA_DEBUG_VXLAN
)
2790 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
2791 inet_ntoa(zvni
->local_vtep_ip
),
2792 vrf_id_to_name(zvni
->vrf_id
),
2793 zebra_route_string(client
->proto
));
2795 client
->vniadd_cnt
++;
2796 return zserv_send_message(client
, s
);
2800 * Inform BGP about local VNI deletion.
2802 static int zvni_send_del_to_client(vni_t vni
)
2804 struct zserv
*client
;
2807 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2808 /* BGP may not be running. */
2812 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2815 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
2816 stream_putl(s
, vni
);
2818 /* Write packet size. */
2819 stream_putw_at(s
, 0, stream_get_endp(s
));
2821 if (IS_ZEBRA_DEBUG_VXLAN
)
2822 zlog_debug("Send VNI_DEL %u to %s", vni
,
2823 zebra_route_string(client
->proto
));
2825 client
->vnidel_cnt
++;
2826 return zserv_send_message(client
, s
);
2830 * Build the VNI hash table by going over the VxLAN interfaces. This
2831 * is called when EVPN (advertise-all-vni) is enabled.
2833 static void zvni_build_hash_table()
2835 struct zebra_ns
*zns
;
2836 struct route_node
*rn
;
2837 struct interface
*ifp
;
2839 /* Walk VxLAN interfaces and create VNI hash. */
2840 zns
= zebra_ns_lookup(NS_DEFAULT
);
2841 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2843 zebra_vni_t
*zvni
= NULL
;
2844 zebra_l3vni_t
*zl3vni
= NULL
;
2845 struct zebra_if
*zif
;
2846 struct zebra_l2info_vxlan
*vxl
;
2848 ifp
= (struct interface
*)rn
->info
;
2852 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2855 vxl
= &zif
->l2info
.vxl
;
2858 /* L3-VNI and L2-VNI are handled seperately */
2859 zl3vni
= zl3vni_lookup(vni
);
2862 if (IS_ZEBRA_DEBUG_VXLAN
)
2864 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
2865 ifp
->name
, ifp
->ifindex
, vni
);
2867 /* associate with vxlan_if */
2868 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
2869 zl3vni
->vxlan_if
= ifp
;
2872 * we need to associate with SVI.
2873 * we can associate with svi-if only after association
2874 * with vxlan-intf is complete
2876 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
2878 if (is_l3vni_oper_up(zl3vni
))
2879 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
2882 struct interface
*vlan_if
= NULL
;
2884 if (IS_ZEBRA_DEBUG_VXLAN
)
2886 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
2887 ifp
->name
, ifp
->ifindex
, vni
,
2888 inet_ntoa(vxl
->vtep_ip
));
2890 /* VNI hash entry is not expected to exist. */
2891 zvni
= zvni_lookup(vni
);
2894 "VNI hash already present for IF %s(%u) L2-VNI %u",
2895 ifp
->name
, ifp
->ifindex
, vni
);
2899 zvni
= zvni_add(vni
);
2902 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
2903 ifp
->name
, ifp
->ifindex
, vni
);
2907 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
2908 zvni
->vxlan_if
= ifp
;
2909 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
2910 zif
->brslave_info
.br_if
);
2912 zvni
->vrf_id
= vlan_if
->vrf_id
;
2913 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
2915 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
2919 /* Inform BGP if intf is up and mapped to bridge. */
2920 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
2921 zvni_send_add_to_client(zvni
);
2927 * See if remote VTEP matches with prefix.
2929 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
2931 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
2935 * Locate remote VTEP in VNI hash table.
2937 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2939 zebra_vtep_t
*zvtep
;
2944 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2945 if (zvni_vtep_match(vtep_ip
, zvtep
))
2953 * Add remote VTEP to VNI hash table.
2955 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
2957 zebra_vtep_t
*zvtep
;
2959 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
2961 zlog_err("Failed to alloc VTEP entry, VNI %u", zvni
->vni
);
2965 zvtep
->vtep_ip
= *vtep_ip
;
2968 zvni
->vteps
->prev
= zvtep
;
2969 zvtep
->next
= zvni
->vteps
;
2970 zvni
->vteps
= zvtep
;
2976 * Remove remote VTEP from VNI hash table.
2978 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
2981 zvtep
->next
->prev
= zvtep
->prev
;
2983 zvtep
->prev
->next
= zvtep
->next
;
2985 zvni
->vteps
= zvtep
->next
;
2987 zvtep
->prev
= zvtep
->next
= NULL
;
2988 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
2994 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
2995 * uninstall from kernel if asked to.
2997 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
2999 zebra_vtep_t
*zvtep
, *zvtep_next
;
3004 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
3005 zvtep_next
= zvtep
->next
;
3007 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
3008 zvni_vtep_del(zvni
, zvtep
);
3015 * Install remote VTEP into the kernel.
3017 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3019 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3023 * Uninstall remote VTEP from the kernel.
3025 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3027 if (!zvni
->vxlan_if
) {
3028 zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
3033 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3037 * Cleanup VNI/VTEP and update kernel
3039 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
3041 zebra_vni_t
*zvni
= NULL
;
3042 zebra_l3vni_t
*zl3vni
= NULL
;
3043 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
3045 zvni
= (zebra_vni_t
*)backet
->data
;
3049 /* remove from l3-vni list */
3051 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
3053 listnode_delete(zl3vni
->l2vnis
, zvni
);
3055 /* Free up all neighbors and MACs, if any. */
3056 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
3057 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
3059 /* Free up all remote VTEPs, if any. */
3060 zvni_vtep_del_all(zvni
, 1);
3062 /* Delete the hash entry. */
3067 static void zl3vni_cleanup_all(struct hash_backet
*backet
, void *args
)
3069 zebra_l3vni_t
*zl3vni
= NULL
;
3071 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
3075 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
3078 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
3079 struct prefix
*host
)
3081 struct host_rb_entry lookup
;
3082 struct host_rb_entry
*hle
;
3084 memset(&lookup
, 0, sizeof(lookup
));
3085 memcpy(&lookup
.p
, host
, sizeof(*host
));
3087 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3091 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
3092 memcpy(hle
, &lookup
, sizeof(lookup
));
3094 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
3097 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
3099 struct host_rb_entry lookup
;
3100 struct host_rb_entry
*hle
;
3102 memset(&lookup
, 0, sizeof(lookup
));
3103 memcpy(&lookup
.p
, host
, sizeof(*host
));
3105 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3107 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
3108 XFREE(MTYPE_HOST_PREFIX
, hle
);
3115 * Look up MAC hash entry.
3117 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
3118 struct ethaddr
*rmac
)
3123 memset(&tmp
, 0, sizeof(tmp
));
3124 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
3125 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
3131 * Callback to allocate RMAC hash entry.
3133 static void *zl3vni_rmac_alloc(void *p
)
3135 const zebra_mac_t
*tmp_rmac
= p
;
3138 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3141 return ((void *)zrmac
);
3145 * Add RMAC entry to l3-vni
3147 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
3149 zebra_mac_t tmp_rmac
;
3150 zebra_mac_t
*zrmac
= NULL
;
3152 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
3153 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
3154 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
3157 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
3159 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
3160 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
3168 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3170 zebra_mac_t
*tmp_rmac
;
3171 struct host_rb_entry
*hle
;
3173 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3174 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
3176 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
3177 XFREE(MTYPE_HOST_PREFIX
, hle
);
3180 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
3182 XFREE(MTYPE_MAC
, tmp_rmac
);
3188 * Install remote RMAC into the kernel.
3190 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3192 struct zebra_if
*zif
= NULL
;
3193 struct zebra_l2info_vxlan
*vxl
= NULL
;
3195 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3196 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3199 zif
= zl3vni
->vxlan_if
->info
;
3203 vxl
= &zif
->l2info
.vxl
;
3205 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3206 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3210 * Uninstall remote RMAC from the kernel.
3212 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3214 char buf
[ETHER_ADDR_STRLEN
];
3215 struct zebra_if
*zif
= NULL
;
3216 struct zebra_l2info_vxlan
*vxl
= NULL
;
3218 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3219 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3222 if (!zl3vni
->vxlan_if
) {
3224 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
3225 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
3226 zl3vni
->vni
, zl3vni
);
3230 zif
= zl3vni
->vxlan_if
->info
;
3234 vxl
= &zif
->l2info
.vxl
;
3236 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3237 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3240 /* handle rmac add */
3241 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
3242 struct ipaddr
*vtep_ip
,
3243 struct prefix
*host_prefix
)
3245 char buf
[ETHER_ADDR_STRLEN
];
3246 char buf1
[INET6_ADDRSTRLEN
];
3247 zebra_mac_t
*zrmac
= NULL
;
3249 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3252 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
3255 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
3256 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3258 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
3261 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
3262 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
3264 /* install rmac in kernel */
3265 zl3vni_rmac_install(zl3vni
, zrmac
);
3268 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
3274 /* handle rmac delete */
3275 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
3276 struct prefix
*host_prefix
)
3278 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
3280 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3281 /* uninstall from kernel */
3282 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3284 /* del the rmac entry */
3285 zl3vni_rmac_del(zl3vni
, zrmac
);
3290 * Look up nh hash entry on a l3-vni.
3292 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3297 memset(&tmp
, 0, sizeof(tmp
));
3298 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
3299 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
3306 * Callback to allocate NH hash entry on L3-VNI.
3308 static void *zl3vni_nh_alloc(void *p
)
3310 const zebra_neigh_t
*tmp_n
= p
;
3313 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
3320 * Add neighbor entry.
3322 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3323 struct ethaddr
*mac
)
3325 zebra_neigh_t tmp_n
;
3326 zebra_neigh_t
*n
= NULL
;
3328 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
3329 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
3330 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
3333 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
3335 memcpy(&n
->emac
, mac
, ETH_ALEN
);
3336 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3337 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
3343 * Delete neighbor entry.
3345 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3347 zebra_neigh_t
*tmp_n
;
3348 struct host_rb_entry
*hle
;
3350 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
3351 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
3353 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
3354 XFREE(MTYPE_HOST_PREFIX
, hle
);
3357 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
3359 XFREE(MTYPE_NEIGH
, tmp_n
);
3365 * Install remote nh as neigh into the kernel.
3367 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3369 if (!is_l3vni_oper_up(zl3vni
))
3372 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3373 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3376 return kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
);
3380 * Uninstall remote nh from the kernel.
3382 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
3384 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
3385 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
3388 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
3391 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
3394 /* add remote vtep as a neigh entry */
3395 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
3396 struct ethaddr
*rmac
,
3397 struct prefix
*host_prefix
)
3399 char buf
[ETHER_ADDR_STRLEN
];
3400 char buf1
[INET6_ADDRSTRLEN
];
3401 zebra_neigh_t
*nh
= NULL
;
3403 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
3405 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
3409 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
3410 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
3411 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
3416 /* install the nh neigh in kernel */
3417 zl3vni_nh_install(zl3vni
, nh
);
3420 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
3425 /* handle nh neigh delete */
3426 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
3427 struct prefix
*host_prefix
)
3429 rb_delete_host(&nh
->host_rb
, host_prefix
);
3431 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
3432 /* uninstall from kernel */
3433 zl3vni_nh_uninstall(zl3vni
, nh
);
3435 /* delete the nh entry */
3436 zl3vni_nh_del(zl3vni
, nh
);
3440 /* handle neigh update from kernel - the only thing of interest is to
3441 * readd stale entries.
3443 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
3447 zebra_neigh_t
*n
= NULL
;
3449 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3453 /* all next hop neigh are remote and installed by frr.
3454 * If the kernel has aged this entry, re-install.
3456 if (state
& NUD_STALE
)
3457 zl3vni_nh_install(zl3vni
, n
);
3462 /* handle neigh delete from kernel */
3463 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
3465 zebra_neigh_t
*n
= NULL
;
3467 n
= zl3vni_nh_lookup(zl3vni
, ip
);
3471 /* all next hop neigh are remote and installed by frr.
3472 * If we get an age out notification for these neigh entries, we have to
3475 zl3vni_nh_install(zl3vni
, n
);
3481 * Hash function for L3 VNI.
3483 static unsigned int l3vni_hash_keymake(void *p
)
3485 const zebra_l3vni_t
*zl3vni
= p
;
3487 return jhash_1word(zl3vni
->vni
, 0);
3491 * Compare 2 L3 VNI hash entries.
3493 static int l3vni_hash_cmp(const void *p1
, const void *p2
)
3495 const zebra_l3vni_t
*zl3vni1
= p1
;
3496 const zebra_l3vni_t
*zl3vni2
= p2
;
3498 return (zl3vni1
->vni
== zl3vni2
->vni
);
3502 * Callback to allocate L3 VNI hash entry.
3504 static void *zl3vni_alloc(void *p
)
3506 zebra_l3vni_t
*zl3vni
= NULL
;
3507 const zebra_l3vni_t
*tmp_l3vni
= p
;
3509 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
3510 zl3vni
->vni
= tmp_l3vni
->vni
;
3511 return ((void *)zl3vni
);
3515 * Look up L3 VNI hash entry.
3517 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
3519 struct zebra_ns
*zns
;
3520 zebra_l3vni_t tmp_l3vni
;
3521 zebra_l3vni_t
*zl3vni
= NULL
;
3523 zns
= zebra_ns_lookup(NS_DEFAULT
);
3525 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
3526 tmp_l3vni
.vni
= vni
;
3527 zl3vni
= hash_lookup(zns
->l3vni_table
, &tmp_l3vni
);
3533 * Add L3 VNI hash entry.
3535 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
3537 zebra_l3vni_t tmp_zl3vni
;
3538 struct zebra_ns
*zns
= NULL
;
3539 zebra_l3vni_t
*zl3vni
= NULL
;
3541 zns
= zebra_ns_lookup(NS_DEFAULT
);
3544 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
3545 tmp_zl3vni
.vni
= vni
;
3547 zl3vni
= hash_get(zns
->l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
3550 zl3vni
->vrf_id
= vrf_id
;
3551 zl3vni
->svi_if
= NULL
;
3552 zl3vni
->vxlan_if
= NULL
;
3553 zl3vni
->l2vnis
= list_new();
3554 zl3vni
->l2vnis
->cmp
= (int (*)(void *, void *))vni_hash_cmp
;
3556 /* Create hash table for remote RMAC */
3557 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
3558 "Zebra L3-VNI RMAC-Table");
3560 /* Create hash table for neighbors */
3561 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3562 "Zebra L3-VNI next-hop table");
3568 * Delete L3 VNI hash entry.
3570 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
3572 struct zebra_ns
*zns
;
3573 zebra_l3vni_t
*tmp_zl3vni
;
3575 zns
= zebra_ns_lookup(NS_DEFAULT
);
3578 /* free the list of l2vnis */
3579 list_delete_and_null(&zl3vni
->l2vnis
);
3580 zl3vni
->l2vnis
= NULL
;
3582 /* Free the rmac table */
3583 hash_free(zl3vni
->rmac_table
);
3584 zl3vni
->rmac_table
= NULL
;
3586 /* Free the nh table */
3587 hash_free(zl3vni
->nh_table
);
3588 zl3vni
->nh_table
= NULL
;
3590 /* Free the VNI hash entry and allocated memory. */
3591 tmp_zl3vni
= hash_release(zns
->l3vni_table
, zl3vni
);
3593 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
3598 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
3600 struct zebra_ns
*zns
= NULL
;
3601 struct route_node
*rn
= NULL
;
3602 struct interface
*ifp
= NULL
;
3604 /* loop through all vxlan-interface */
3605 zns
= zebra_ns_lookup(NS_DEFAULT
);
3606 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3608 struct zebra_if
*zif
= NULL
;
3609 struct zebra_l2info_vxlan
*vxl
= NULL
;
3611 ifp
= (struct interface
*)rn
->info
;
3616 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3619 vxl
= &zif
->l2info
.vxl
;
3620 if (vxl
->vni
== zl3vni
->vni
) {
3621 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3629 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
3631 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
3632 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
3637 if (!zl3vni
->vxlan_if
)
3640 zif
= zl3vni
->vxlan_if
->info
;
3644 vxl
= &zif
->l2info
.vxl
;
3646 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3649 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
3651 struct zebra_vrf
*zvrf
= NULL
;
3653 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
3657 return zl3vni_lookup(zvrf
->l3vni
);
3661 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3662 * neighbor notifications, to see if they are of interest.
3664 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
3665 struct interface
*br_if
)
3669 uint8_t bridge_vlan_aware
= 0;
3670 zebra_l3vni_t
*zl3vni
= NULL
;
3671 struct zebra_ns
*zns
= NULL
;
3672 struct route_node
*rn
= NULL
;
3673 struct zebra_if
*zif
= NULL
;
3674 struct interface
*tmp_if
= NULL
;
3675 struct zebra_l2info_bridge
*br
= NULL
;
3676 struct zebra_l2info_vxlan
*vxl
= NULL
;
3681 /* Make sure the linked interface is a bridge. */
3682 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3685 /* Determine if bridge is VLAN-aware or not */
3688 br
= &zif
->l2info
.br
;
3689 bridge_vlan_aware
= br
->vlan_aware
;
3690 if (bridge_vlan_aware
) {
3691 struct zebra_l2info_vlan
*vl
;
3693 if (!IS_ZEBRA_IF_VLAN(ifp
))
3698 vl
= &zif
->l2info
.vl
;
3702 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3703 /* TODO: Optimize with a hash. */
3704 zns
= zebra_ns_lookup(NS_DEFAULT
);
3705 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3706 tmp_if
= (struct interface
*)rn
->info
;
3710 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3712 if (!if_is_operative(tmp_if
))
3714 vxl
= &zif
->l2info
.vxl
;
3716 if (zif
->brslave_info
.br_if
!= br_if
)
3719 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3728 zl3vni
= zl3vni_lookup(vxl
->vni
);
3733 * Inform BGP about l3-vni.
3735 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
3737 struct stream
*s
= NULL
;
3738 struct zserv
*client
= NULL
;
3739 struct ethaddr rmac
;
3740 char buf
[ETHER_ADDR_STRLEN
];
3742 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3743 /* BGP may not be running. */
3748 memset(&rmac
, 0, sizeof(struct ethaddr
));
3749 zl3vni_get_rmac(zl3vni
, &rmac
);
3751 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3753 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
3754 stream_putl(s
, zl3vni
->vni
);
3755 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
3756 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
3757 stream_put(s
, &zl3vni
->filter
, sizeof(int));
3759 /* Write packet size. */
3760 stream_putw_at(s
, 0, stream_get_endp(s
));
3762 if (IS_ZEBRA_DEBUG_VXLAN
)
3764 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
3765 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3766 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
3767 inet_ntoa(zl3vni
->local_vtep_ip
),
3768 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
3769 ? "prefix-routes-only"
3771 zebra_route_string(client
->proto
));
3773 client
->l3vniadd_cnt
++;
3774 return zserv_send_message(client
, s
);
3778 * Inform BGP about local l3-VNI deletion.
3780 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
3782 struct stream
*s
= NULL
;
3783 struct zserv
*client
= NULL
;
3785 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3786 /* BGP may not be running. */
3790 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3792 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
3793 stream_putl(s
, zl3vni
->vni
);
3795 /* Write packet size. */
3796 stream_putw_at(s
, 0, stream_get_endp(s
));
3798 if (IS_ZEBRA_DEBUG_VXLAN
)
3799 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
3800 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
3801 zebra_route_string(client
->proto
));
3803 client
->l3vnidel_cnt
++;
3804 return zserv_send_message(client
, s
);
3807 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
3812 /* send l3vni add to BGP */
3813 zl3vni_send_add_to_client(zl3vni
);
3816 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
3821 /* send l3-vni del to BGP*/
3822 zl3vni_send_del_to_client(zl3vni
);
3825 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
, void *ctxt
)
3827 zebra_vni_t
*zvni
= (zebra_vni_t
*)backet
->data
;
3828 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
3830 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
3831 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3835 * handle transition of vni from l2 to l3 and vice versa
3837 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
3840 zebra_vni_t
*zvni
= NULL
;
3842 /* There is a possibility that VNI notification was already received
3843 * from kernel and we programmed it as L2-VNI
3844 * In such a case we need to delete this L2-VNI first, so
3845 * that it can be reprogrammed as L3-VNI in the system. It is also
3846 * possible that the vrf-vni mapping is removed from FRR while the vxlan
3847 * interface is still present in kernel. In this case to keep it
3848 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
3851 /* Locate hash entry */
3852 zvni
= zvni_lookup(vni
);
3856 if (IS_ZEBRA_DEBUG_VXLAN
)
3857 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
3859 /* Delete VNI from BGP. */
3860 zvni_send_del_to_client(zvni
->vni
);
3862 /* Free up all neighbors and MAC, if any. */
3863 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
3864 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
3866 /* Free up all remote VTEPs, if any. */
3867 zvni_vtep_del_all(zvni
, 0);
3869 /* Delete the hash entry. */
3870 if (zvni_del(zvni
)) {
3871 zlog_err("Failed to del VNI hash %p, VNI %u", zvni
,
3876 /* TODO_MITESH: This needs to be thought through. We don't have
3877 * enough information at this point to reprogram the vni as
3878 * l2-vni. One way is to store the required info in l3-vni and
3879 * used it solely for this purpose
3886 /* delete and uninstall rmac hash entry */
3887 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
, void *ctx
)
3889 zebra_mac_t
*zrmac
= NULL
;
3890 zebra_l3vni_t
*zl3vni
= NULL
;
3892 zrmac
= (zebra_mac_t
*)backet
->data
;
3893 zl3vni
= (zebra_l3vni_t
*)ctx
;
3894 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
3895 zl3vni_rmac_del(zl3vni
, zrmac
);
3898 /* delete and uninstall nh hash entry */
3899 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
, void *ctx
)
3901 zebra_neigh_t
*n
= NULL
;
3902 zebra_l3vni_t
*zl3vni
= NULL
;
3904 n
= (zebra_neigh_t
*)backet
->data
;
3905 zl3vni
= (zebra_l3vni_t
*)ctx
;
3906 zl3vni_nh_uninstall(zl3vni
, n
);
3907 zl3vni_nh_del(zl3vni
, n
);
3910 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
3913 struct zserv
*client
= NULL
;
3914 struct stream
*s
= NULL
;
3915 char buf
[PREFIX_STRLEN
];
3917 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3918 /* BGP may not be running. */
3922 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3924 zclient_create_header(s
, cmd
, vrf_id
);
3925 stream_put(s
, p
, sizeof(struct prefix
));
3927 /* Write packet size. */
3928 stream_putw_at(s
, 0, stream_get_endp(s
));
3930 if (IS_ZEBRA_DEBUG_VXLAN
)
3931 zlog_debug("Send ip prefix %s %s on vrf %s",
3932 prefix2str(p
, buf
, sizeof(buf
)),
3933 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
3934 vrf_id_to_name(vrf_id
));
3936 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
3937 client
->prefixadd_cnt
++;
3939 client
->prefixdel_cnt
++;
3941 return zserv_send_message(client
, s
);
3944 /* re-add remote rmac if needed */
3945 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
3946 struct ethaddr
*rmac
)
3948 char buf
[ETHER_ADDR_STRLEN
];
3949 zebra_mac_t
*zrmac
= NULL
;
3951 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
3955 if (IS_ZEBRA_DEBUG_VXLAN
)
3956 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
3957 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
3959 zl3vni_rmac_install(zl3vni
, zrmac
);
3963 /* Public functions */
3965 int is_l3vni_for_prefix_routes_only(vni_t vni
)
3967 zebra_l3vni_t
*zl3vni
= NULL
;
3969 zl3vni
= zl3vni_lookup(vni
);
3973 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
3976 /* handle evpn route in vrf table */
3977 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
3978 struct ipaddr
*vtep_ip
,
3979 struct prefix
*host_prefix
)
3981 zebra_l3vni_t
*zl3vni
= NULL
;
3982 struct ipaddr ipv4_vtep
;
3984 zl3vni
= zl3vni_from_vrf(vrf_id
);
3985 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
3989 * add the next hop neighbor -
3990 * neigh to be installed is the ipv6 nexthop neigh
3992 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
3995 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
3996 * address. Rmac is programmed against the ipv4 vtep because we only
3997 * support ipv4 tunnels in the h/w right now
3999 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
4000 ipv4_vtep
.ipa_type
= IPADDR_V4
;
4001 if (vtep_ip
->ipa_type
== IPADDR_V6
)
4002 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
4003 &(ipv4_vtep
.ipaddr_v4
));
4005 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
4006 sizeof(struct in_addr
));
4009 * add the rmac - remote rmac to be installed is against the ipv4
4012 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
4015 /* handle evpn vrf route delete */
4016 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
4017 struct ipaddr
*vtep_ip
,
4018 struct prefix
*host_prefix
)
4020 zebra_l3vni_t
*zl3vni
= NULL
;
4021 zebra_neigh_t
*nh
= NULL
;
4022 zebra_mac_t
*zrmac
= NULL
;
4024 zl3vni
= zl3vni_from_vrf(vrf_id
);
4028 /* find the next hop entry and rmac entry */
4029 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4032 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
4034 /* delete the next hop entry */
4035 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
4037 /* delete the rmac entry */
4039 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
4043 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
4044 struct ethaddr
*rmac
,
4047 zebra_l3vni_t
*zl3vni
= NULL
;
4048 zebra_mac_t
*zrmac
= NULL
;
4049 json_object
*json
= NULL
;
4051 if (!is_evpn_enabled()) {
4053 vty_out(vty
, "{}\n");
4058 json
= json_object_new_object();
4060 zl3vni
= zl3vni_lookup(l3vni
);
4063 vty_out(vty
, "{}\n");
4065 vty_out(vty
, "%% L3-VNI %u doesnt exist\n", l3vni
);
4069 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4072 vty_out(vty
, "{}\n");
4075 "%% Requested RMAC doesnt exist in L3-VNI %u",
4080 zl3vni_print_rmac(zrmac
, vty
, json
);
4083 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4084 json
, JSON_C_TO_STRING_PRETTY
));
4085 json_object_free(json
);
4089 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
,
4092 zebra_l3vni_t
*zl3vni
;
4094 struct rmac_walk_ctx wctx
;
4095 json_object
*json
= NULL
;
4097 if (!is_evpn_enabled())
4100 zl3vni
= zl3vni_lookup(l3vni
);
4103 vty_out(vty
, "{}\n");
4105 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4108 num_rmacs
= hashcount(zl3vni
->rmac_table
);
4113 json
= json_object_new_object();
4115 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
4119 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
4121 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
4123 json_object_int_add(json
, "numRmacs", num_rmacs
);
4125 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
4128 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4129 json
, JSON_C_TO_STRING_PRETTY
));
4130 json_object_free(json
);
4134 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, uint8_t use_json
)
4136 struct zebra_ns
*zns
= NULL
;
4137 json_object
*json
= NULL
;
4140 if (!is_evpn_enabled()) {
4142 vty_out(vty
, "{}\n");
4146 zns
= zebra_ns_lookup(NS_DEFAULT
);
4149 vty_out(vty
, "{}\n");
4154 json
= json_object_new_object();
4158 hash_iterate(zns
->l3vni_table
,
4159 (void (*)(struct hash_backet
*,
4160 void *))zl3vni_print_rmac_hash_all_vni
,
4164 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4165 json
, JSON_C_TO_STRING_PRETTY
));
4166 json_object_free(json
);
4170 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
4171 struct ipaddr
*ip
, uint8_t use_json
)
4173 zebra_l3vni_t
*zl3vni
= NULL
;
4174 zebra_neigh_t
*n
= NULL
;
4175 json_object
*json
= NULL
;
4177 if (!is_evpn_enabled()) {
4179 vty_out(vty
, "{}\n");
4184 json
= json_object_new_object();
4186 zl3vni
= zl3vni_lookup(l3vni
);
4189 vty_out(vty
, "{}\n");
4191 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4195 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4198 vty_out(vty
, "{}\n");
4201 "%% Requested next-hop not present for L3-VNI %u",
4206 zl3vni_print_nh(n
, vty
, json
);
4209 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4210 json
, JSON_C_TO_STRING_PRETTY
));
4211 json_object_free(json
);
4215 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, uint8_t use_json
)
4218 struct nh_walk_ctx wctx
;
4219 json_object
*json
= NULL
;
4220 zebra_l3vni_t
*zl3vni
= NULL
;
4222 if (!is_evpn_enabled())
4225 zl3vni
= zl3vni_lookup(l3vni
);
4228 vty_out(vty
, "{}\n");
4230 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
4234 num_nh
= hashcount(zl3vni
->nh_table
);
4239 json
= json_object_new_object();
4244 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
4246 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
4248 json_object_int_add(json
, "numNextHops", num_nh
);
4250 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
4253 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4254 json
, JSON_C_TO_STRING_PRETTY
));
4255 json_object_free(json
);
4259 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, uint8_t use_json
)
4261 struct zebra_ns
*zns
= NULL
;
4262 json_object
*json
= NULL
;
4265 if (!is_evpn_enabled()) {
4267 vty_out(vty
, "{}\n");
4271 zns
= zebra_ns_lookup(NS_DEFAULT
);
4276 json
= json_object_new_object();
4280 hash_iterate(zns
->l3vni_table
,
4281 (void (*)(struct hash_backet
*,
4282 void *))zl3vni_print_nh_hash_all_vni
,
4286 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4287 json
, JSON_C_TO_STRING_PRETTY
));
4288 json_object_free(json
);
4294 * Display L3 VNI information (VTY command handler).
4296 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, uint8_t use_json
)
4299 json_object
*json
= NULL
;
4300 zebra_l3vni_t
*zl3vni
= NULL
;
4302 if (!is_evpn_enabled()) {
4304 vty_out(vty
, "{}\n");
4308 zl3vni
= zl3vni_lookup(vni
);
4311 vty_out(vty
, "{}\n");
4313 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4318 json
= json_object_new_object();
4322 zl3vni_print(zl3vni
, (void *)args
);
4325 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4326 json
, JSON_C_TO_STRING_PRETTY
));
4327 json_object_free(json
);
4331 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4332 json_object
*json_vrfs
)
4334 char buf
[ETHER_ADDR_STRLEN
];
4335 zebra_l3vni_t
*zl3vni
= NULL
;
4337 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4342 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
4343 zvrf_name(zvrf
), zl3vni
->vni
,
4344 zl3vni_vxlan_if_name(zl3vni
),
4345 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
4346 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4348 json_object
*json_vrf
= NULL
;
4349 json_vrf
= json_object_new_object();
4350 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
4351 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
4352 json_object_string_add(json_vrf
, "vxlanIntf",
4353 zl3vni_vxlan_if_name(zl3vni
));
4354 json_object_string_add(json_vrf
, "sviIntf",
4355 zl3vni_svi_if_name(zl3vni
));
4356 json_object_string_add(json_vrf
, "state",
4357 zl3vni_state2str(zl3vni
));
4358 json_object_string_add(
4359 json_vrf
, "routerMac",
4360 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
4361 json_object_array_add(json_vrfs
, json_vrf
);
4366 * Display Neighbors for a VNI (VTY command handler).
4368 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4369 vni_t vni
, uint8_t use_json
)
4373 struct neigh_walk_ctx wctx
;
4374 json_object
*json
= NULL
;
4376 if (!is_evpn_enabled())
4378 zvni
= zvni_lookup(vni
);
4381 vty_out(vty
, "{}\n");
4383 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4386 num_neigh
= hashcount(zvni
->neigh_table
);
4391 json
= json_object_new_object();
4393 /* Since we have IPv6 addresses to deal with which can vary widely in
4394 * size, we try to be a bit more elegant in display by first computing
4395 * the maximum width.
4397 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4400 wctx
.addr_width
= 15;
4402 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
4406 "Number of ARPs (local and remote) known for this VNI: %u\n",
4408 vty_out(vty
, "%*s %-6s %-17s %-21s\n", -wctx
.addr_width
, "IP",
4409 "Type", "MAC", "Remote VTEP");
4411 json_object_int_add(json
, "numArpNd", num_neigh
);
4413 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4415 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4416 json
, JSON_C_TO_STRING_PRETTY
));
4417 json_object_free(json
);
4422 * Display neighbors across all VNIs (VTY command handler).
4424 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4427 json_object
*json
= NULL
;
4430 if (!is_evpn_enabled())
4434 json
= json_object_new_object();
4438 hash_iterate(zvrf
->vni_table
,
4439 (void (*)(struct hash_backet
*,
4440 void *))zvni_print_neigh_hash_all_vni
,
4443 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4444 json
, JSON_C_TO_STRING_PRETTY
));
4445 json_object_free(json
);
4450 * Display specific neighbor for a VNI, if present (VTY command handler).
4452 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
4453 struct zebra_vrf
*zvrf
, vni_t vni
,
4454 struct ipaddr
*ip
, uint8_t use_json
)
4458 json_object
*json
= NULL
;
4460 if (!is_evpn_enabled())
4462 zvni
= zvni_lookup(vni
);
4465 vty_out(vty
, "{}\n");
4467 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4470 n
= zvni_neigh_lookup(zvni
, ip
);
4474 "%% Requested neighbor does not exist in VNI %u\n",
4479 json
= json_object_new_object();
4481 zvni_print_neigh(n
, vty
, json
);
4484 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4485 json
, JSON_C_TO_STRING_PRETTY
));
4486 json_object_free(json
);
4491 * Display neighbors for a VNI from specific VTEP (VTY command handler).
4492 * By definition, these are remote neighbors.
4494 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4495 vni_t vni
, struct in_addr vtep_ip
,
4500 struct neigh_walk_ctx wctx
;
4501 json_object
*json
= NULL
;
4503 if (!is_evpn_enabled())
4505 zvni
= zvni_lookup(vni
);
4508 vty_out(vty
, "{}\n");
4510 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4513 num_neigh
= hashcount(zvni
->neigh_table
);
4517 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
4520 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
4521 wctx
.r_vtep_ip
= vtep_ip
;
4523 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
4526 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4527 json
, JSON_C_TO_STRING_PRETTY
));
4528 json_object_free(json
);
4533 * Display MACs for a VNI (VTY command handler).
4535 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4536 vni_t vni
, uint8_t use_json
)
4540 struct mac_walk_ctx wctx
;
4541 json_object
*json
= NULL
;
4542 json_object
*json_mac
= NULL
;
4544 if (!is_evpn_enabled())
4546 zvni
= zvni_lookup(vni
);
4549 vty_out(vty
, "{}\n");
4551 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4554 num_macs
= num_valid_macs(zvni
);
4559 json
= json_object_new_object();
4560 json_mac
= json_object_new_object();
4563 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4566 wctx
.json
= json_mac
;
4570 "Number of MACs (local and remote) known for this VNI: %u\n",
4572 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
4573 "Intf/Remote VTEP", "VLAN");
4575 json_object_int_add(json
, "numMacs", num_macs
);
4577 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4580 json_object_object_add(json
, "macs", json_mac
);
4581 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4582 json
, JSON_C_TO_STRING_PRETTY
));
4583 json_object_free(json
);
4588 * Display MACs for all VNIs (VTY command handler).
4590 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4593 struct mac_walk_ctx wctx
;
4594 json_object
*json
= NULL
;
4596 if (!is_evpn_enabled()) {
4598 vty_out(vty
, "{}\n");
4602 json
= json_object_new_object();
4604 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4607 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4610 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4611 json
, JSON_C_TO_STRING_PRETTY
));
4612 json_object_free(json
);
4617 * Display MACs for all VNIs (VTY command handler).
4619 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
4620 struct zebra_vrf
*zvrf
,
4621 struct in_addr vtep_ip
,
4624 struct mac_walk_ctx wctx
;
4625 json_object
*json
= NULL
;
4627 if (!is_evpn_enabled())
4631 json
= json_object_new_object();
4633 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4635 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4636 wctx
.r_vtep_ip
= vtep_ip
;
4638 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
4641 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4642 json
, JSON_C_TO_STRING_PRETTY
));
4643 json_object_free(json
);
4648 * Display specific MAC for a VNI, if present (VTY command handler).
4650 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4651 vni_t vni
, struct ethaddr
*macaddr
)
4656 if (!is_evpn_enabled())
4658 zvni
= zvni_lookup(vni
);
4660 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4663 mac
= zvni_mac_lookup(zvni
, macaddr
);
4665 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
4670 zvni_print_mac(mac
, vty
);
4674 * Display MACs for a VNI from specific VTEP (VTY command handler).
4676 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4677 vni_t vni
, struct in_addr vtep_ip
,
4682 struct mac_walk_ctx wctx
;
4683 json_object
*json
= NULL
;
4684 json_object
*json_mac
= NULL
;
4686 if (!is_evpn_enabled())
4688 zvni
= zvni_lookup(vni
);
4691 vty_out(vty
, "{}\n");
4693 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4696 num_macs
= num_valid_macs(zvni
);
4701 json
= json_object_new_object();
4702 json_mac
= json_object_new_object();
4705 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
4708 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
4709 wctx
.r_vtep_ip
= vtep_ip
;
4710 wctx
.json
= json_mac
;
4711 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
4714 json_object_int_add(json
, "numMacs", wctx
.count
);
4716 json_object_object_add(json
, "macs", json_mac
);
4717 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4718 json
, JSON_C_TO_STRING_PRETTY
));
4719 json_object_free(json
);
4725 * Display VNI information (VTY command handler).
4727 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
4730 json_object
*json
= NULL
;
4732 zebra_l3vni_t
*zl3vni
= NULL
;
4733 zebra_vni_t
*zvni
= NULL
;
4735 if (!is_evpn_enabled())
4739 json
= json_object_new_object();
4743 zl3vni
= zl3vni_lookup(vni
);
4745 zl3vni_print(zl3vni
, (void *)args
);
4747 zvni
= zvni_lookup(vni
);
4750 vty_out(vty
, "{}\n");
4752 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
4756 zvni_print(zvni
, (void *)args
);
4760 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4761 json
, JSON_C_TO_STRING_PRETTY
));
4762 json_object_free(json
);
4766 /* Display all global details for EVPN */
4767 void zebra_vxlan_print_evpn(struct vty
*vty
, uint8_t uj
)
4772 json_object
*json
= NULL
;
4773 struct zebra_ns
*zns
= NULL
;
4774 struct zebra_vrf
*zvrf
= NULL
;
4776 if (!is_evpn_enabled())
4779 zns
= zebra_ns_lookup(NS_DEFAULT
);
4783 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
4787 num_l3vnis
= hashcount(zns
->l3vni_table
);
4788 num_l2vnis
= hashcount(zvrf
->vni_table
);
4789 num_vnis
= num_l2vnis
+ num_l3vnis
;
4792 json
= json_object_new_object();
4793 json_object_string_add(json
, "advertiseGatewayMacip",
4794 zvrf
->advertise_gw_macip
? "Yes" : "No");
4795 json_object_int_add(json
, "numVnis", num_vnis
);
4796 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4797 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4799 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
4800 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
4801 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
4802 zvrf
->advertise_gw_macip
? "Yes" : "No");
4806 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4807 json
, JSON_C_TO_STRING_PRETTY
));
4808 json_object_free(json
);
4813 * Display VNI hash table (VTY command handler).
4815 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
4818 json_object
*json
= NULL
;
4819 struct zebra_ns
*zns
= NULL
;
4822 if (!is_evpn_enabled())
4825 zns
= zebra_ns_lookup(NS_DEFAULT
);
4831 json
= json_object_new_object();
4833 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
4834 "Type", "VxLAN IF", "# MACs", "# ARPs",
4835 "# Remote VTEPs", "Tenant VRF");
4840 /* Display all L2-VNIs */
4841 hash_iterate(zvrf
->vni_table
,
4842 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
4845 /* Display all L3-VNIs */
4846 hash_iterate(zns
->l3vni_table
,
4847 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
4851 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4852 json
, JSON_C_TO_STRING_PRETTY
));
4853 json_object_free(json
);
4858 * Handle neighbor delete notification from the kernel (on a VLAN device
4859 * / L3 interface). This may result in either the neighbor getting deleted
4860 * from our database or being re-added to the kernel (if it is a valid
4863 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
4864 struct interface
*link_if
,
4867 char buf
[INET6_ADDRSTRLEN
];
4868 char buf2
[ETHER_ADDR_STRLEN
];
4869 zebra_neigh_t
*n
= NULL
;
4870 zebra_vni_t
*zvni
= NULL
;
4871 zebra_mac_t
*zmac
= NULL
;
4872 zebra_l3vni_t
*zl3vni
= NULL
;
4874 /* check if this is a remote neigh entry corresponding to remote
4877 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4879 return zl3vni_local_nh_del(zl3vni
, ip
);
4881 /* We are only interested in neighbors on an SVI that resides on top
4882 * of a VxLAN bridge.
4884 zvni
= zvni_from_svi(ifp
, link_if
);
4888 if (!zvni
->vxlan_if
) {
4890 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
4895 if (IS_ZEBRA_DEBUG_VXLAN
)
4896 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
4897 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
4898 ifp
->ifindex
, zvni
->vni
);
4900 /* If entry doesn't exist, nothing to do. */
4901 n
= zvni_neigh_lookup(zvni
, ip
);
4905 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
4907 if (IS_ZEBRA_DEBUG_VXLAN
)
4909 "Trying to del a neigh %s without a mac %s on VNI %u",
4910 ipaddr2str(ip
, buf
, sizeof(buf
)),
4911 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
4917 /* If it is a remote entry, the kernel has aged this out or someone has
4918 * deleted it, it needs to be re-installed as Quagga is the owner.
4920 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
4921 zvni_neigh_install(zvni
, n
);
4925 /* Remove neighbor from BGP. */
4926 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
4927 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0);
4929 /* Delete this neighbor entry. */
4930 zvni_neigh_del(zvni
, n
);
4932 /* see if the AUTO mac needs to be deleted */
4933 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
4934 && !listcount(zmac
->neigh_list
))
4935 zvni_mac_del(zvni
, zmac
);
4941 * Handle neighbor add or update notification from the kernel (on a VLAN
4942 * device / L3 interface). This is typically for a local neighbor but can
4943 * also be for a remote neighbor (e.g., ageout notification). It could
4944 * also be a "move" scenario.
4946 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
4947 struct interface
*link_if
,
4949 struct ethaddr
*macaddr
,
4951 uint8_t ext_learned
)
4953 char buf
[ETHER_ADDR_STRLEN
];
4954 char buf2
[INET6_ADDRSTRLEN
];
4955 zebra_vni_t
*zvni
= NULL
;
4956 zebra_l3vni_t
*zl3vni
= NULL
;
4958 /* check if this is a remote neigh entry corresponding to remote
4961 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4963 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
4965 /* We are only interested in neighbors on an SVI that resides on top
4966 * of a VxLAN bridge.
4968 zvni
= zvni_from_svi(ifp
, link_if
);
4972 if (IS_ZEBRA_DEBUG_VXLAN
)
4974 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u",
4975 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
4976 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
4977 ifp
->ifindex
, state
, ext_learned
? "ext-learned " : "",
4980 /* Is this about a local neighbor or a remote one? */
4982 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
);
4984 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
4989 * Handle message from client to delete a remote MACIP for a VNI.
4991 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
4995 struct ethaddr macaddr
;
4997 struct in_addr vtep_ip
;
5001 unsigned short l
= 0, ipa_len
;
5002 char buf
[ETHER_ADDR_STRLEN
];
5003 char buf1
[INET6_ADDRSTRLEN
];
5004 struct interface
*ifp
= NULL
;
5005 struct zebra_if
*zif
= NULL
;
5007 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5008 memset(&ip
, 0, sizeof(struct ipaddr
));
5009 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5013 while (l
< hdr
->length
) {
5014 /* Obtain each remote MACIP and process. */
5015 /* Message contains VNI, followed by MAC followed by IP (if any)
5016 * followed by remote VTEP IP.
5020 memset(&ip
, 0, sizeof(ip
));
5021 STREAM_GETL(s
, vni
);
5022 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5023 STREAM_GETL(s
, ipa_len
);
5025 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5027 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5029 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5030 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5031 l
+= IPV4_MAX_BYTELEN
;
5033 if (IS_ZEBRA_DEBUG_VXLAN
)
5035 "Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s",
5036 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5037 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5039 zebra_route_string(client
->proto
));
5041 /* Locate VNI hash entry - expected to exist. */
5042 zvni
= zvni_lookup(vni
);
5044 if (IS_ZEBRA_DEBUG_VXLAN
)
5046 "Failed to locate VNI hash upon remote MACIP DEL, "
5051 ifp
= zvni
->vxlan_if
;
5054 "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
5060 /* If down or not mapped to a bridge, we're done. */
5061 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5064 /* The remote VTEP specified is normally expected to exist, but
5066 * possible that the peer may delete the VTEP before deleting
5068 * referring to the VTEP, in which case the handler (see
5070 * would have already deleted the MACs.
5072 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5075 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5077 n
= zvni_neigh_lookup(zvni
, &ip
);
5080 zlog_err("Failed to locate MAC %s for neigh %s VNI %u",
5081 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5082 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5086 /* If the remote mac or neighbor doesn't exist there is nothing
5088 * to do. Otherwise, uninstall the entry and then remove it.
5093 /* Ignore the delete if this mac is a gateway mac-ip */
5094 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5095 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5097 "%u: Ignore Del for MAC %s neigh %s on VNI %u as it is configured as a default gateway",
5099 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5100 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
);
5104 /* Uninstall remote neighbor or MAC. */
5106 /* When the MAC changes for an IP, it is possible the
5108 * update the new MAC before trying to delete the "old"
5110 * (as these are two different MACIP routes). Do the
5112 * if the MAC matches.
5114 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5115 && (memcmp(n
->emac
.octet
, macaddr
.octet
, ETH_ALEN
)
5117 zvni_neigh_uninstall(zvni
, n
);
5118 zvni_neigh_del(zvni
, n
);
5119 zvni_deref_ip2mac(zvni
, mac
, 1);
5122 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5123 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5125 if (list_isempty(mac
->neigh_list
)) {
5126 zvni_mac_uninstall(zvni
, mac
, 0);
5127 zvni_mac_del(zvni
, mac
);
5129 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5139 * Handle message from client to add a remote MACIP for a VNI. This
5140 * could be just the add of a MAC address or the add of a neighbor
5143 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
5147 struct ethaddr macaddr
;
5149 struct in_addr vtep_ip
;
5151 zebra_vtep_t
*zvtep
;
5152 zebra_mac_t
*mac
, *old_mac
;
5154 unsigned short l
= 0, ipa_len
;
5155 int update_mac
= 0, update_neigh
= 0;
5156 char buf
[ETHER_ADDR_STRLEN
];
5157 char buf1
[INET6_ADDRSTRLEN
];
5159 u_char remote_gw
= 0;
5161 struct interface
*ifp
= NULL
;
5162 struct zebra_if
*zif
= NULL
;
5164 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5165 memset(&ip
, 0, sizeof(struct ipaddr
));
5166 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
5168 if (!EVPN_ENABLED(zvrf
)) {
5170 "%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
5171 __PRETTY_FUNCTION__
);
5177 while (l
< hdr
->length
) {
5178 /* Obtain each remote MACIP and process. */
5179 /* Message contains VNI, followed by MAC followed by IP (if any)
5180 * followed by remote VTEP IP.
5182 update_mac
= update_neigh
= 0;
5185 memset(&ip
, 0, sizeof(ip
));
5186 STREAM_GETL(s
, vni
);
5187 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
5188 STREAM_GETL(s
, ipa_len
);
5190 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
5192 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
5194 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
5195 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5196 l
+= IPV4_MAX_BYTELEN
;
5198 /* Get flags - sticky mac and/or gateway mac */
5199 STREAM_GETC(s
, flags
);
5200 sticky
= CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5201 remote_gw
= CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5204 if (IS_ZEBRA_DEBUG_VXLAN
)
5206 "Recv MACIP Add MAC %s IP %s VNI %u Remote VTEP %s with flags 0x%x from %s",
5207 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
5208 ipaddr2str(&ip
, buf1
, sizeof(buf1
)), vni
,
5209 inet_ntoa(vtep_ip
), flags
,
5210 zebra_route_string(client
->proto
));
5212 /* Locate VNI hash entry - expected to exist. */
5213 zvni
= zvni_lookup(vni
);
5216 "Failed to locate VNI hash upon remote MACIP ADD, VNI %u",
5220 ifp
= zvni
->vxlan_if
;
5223 "VNI %u hash %p doesn't have intf upon remote MACIP add",
5229 /* If down or not mapped to a bridge, we're done. */
5230 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5233 /* The remote VTEP specified should normally exist, but it is
5235 * that when peering comes up, peer may advertise MACIP routes
5237 * advertising type-3 routes.
5239 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5241 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5243 "Failed to add remote VTEP, VNI %u zvni %p",
5248 zvni_vtep_install(zvni
, &vtep_ip
);
5251 mac
= zvni_mac_lookup(zvni
, &macaddr
);
5253 /* Ignore the update if the mac is already present
5255 if (mac
&& CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)
5256 && CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5257 if (IS_ZEBRA_DEBUG_VXLAN
)
5259 "%u:Ignore MAC %s IP %s on VNI %u as MAC is already configured as gateway mac",
5261 prefix_mac2str(&macaddr
, buf
,
5263 ipaddr2str(&ip
, buf1
, sizeof(buf1
)),
5268 /* check if the remote MAC is unknown or has a change.
5269 * If so, that needs to be updated first. Note that client could
5270 * install MAC and MACIP separately or just install the latter.
5272 if (!mac
|| !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5273 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
) ? 1 : 0)
5275 || (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
) ? 1 : 0)
5277 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
))
5282 mac
= zvni_mac_add(zvni
, &macaddr
);
5285 "Failed to add MAC %s VNI %u Remote VTEP %s",
5286 prefix_mac2str(&macaddr
, buf
,
5288 vni
, inet_ntoa(vtep_ip
));
5292 /* Is this MAC created for a MACIP? */
5294 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5297 /* Set "auto" and "remote" forwarding info. */
5298 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5299 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5300 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5301 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5304 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5306 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5309 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5311 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5313 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5315 /* Install the entry. */
5316 zvni_mac_install(zvni
, mac
);
5319 /* If there is no IP, continue - after clearing AUTO flag of
5322 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5326 /* Check if the remote neighbor itself is unknown or has a
5328 * If so, create or update and then install the entry.
5330 n
= zvni_neigh_lookup(zvni
, &ip
);
5331 if (!n
|| !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5332 || (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
)) != 0)
5333 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
))
5338 n
= zvni_neigh_add(zvni
, &ip
, &macaddr
);
5341 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5342 ipaddr2str(&ip
, buf1
,
5344 prefix_mac2str(&macaddr
, buf
,
5346 vni
, inet_ntoa(vtep_ip
));
5350 } else if (memcmp(&n
->emac
, &macaddr
, sizeof(macaddr
))
5352 /* MAC change, update neigh list for old and new
5354 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5356 listnode_delete(old_mac
->neigh_list
, n
);
5357 zvni_deref_ip2mac(zvni
, old_mac
, 1);
5359 listnode_add_sort(mac
->neigh_list
, n
);
5360 memcpy(&n
->emac
, &macaddr
, ETH_ALEN
);
5363 /* Set "remote" forwarding info. */
5364 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5365 /* TODO: Handle MAC change. */
5366 n
->r_vtep_ip
= vtep_ip
;
5367 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5369 /* Install the entry. */
5370 zvni_neigh_install(zvni
, n
);
5379 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
5380 * us, this must involve a multihoming scenario. Treat this as implicit delete
5381 * of any prior local MAC.
5383 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
5384 struct interface
*br_if
,
5385 struct ethaddr
*macaddr
, vlanid_t vid
)
5387 struct zebra_if
*zif
;
5388 struct zebra_l2info_vxlan
*vxl
;
5392 char buf
[ETHER_ADDR_STRLEN
];
5396 vxl
= &zif
->l2info
.vxl
;
5399 /* Check if EVPN is enabled. */
5400 if (!is_evpn_enabled())
5403 /* Locate hash entry; it is expected to exist. */
5404 zvni
= zvni_lookup(vni
);
5408 /* If entry doesn't exist, nothing to do. */
5409 mac
= zvni_mac_lookup(zvni
, macaddr
);
5413 /* Is it a local entry? */
5414 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5417 if (IS_ZEBRA_DEBUG_VXLAN
)
5419 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
5420 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5423 /* Remove MAC from BGP. */
5424 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5427 * If there are no neigh associated with the mac delete the mac
5428 * else mark it as AUTO for forward reference
5430 if (!listcount(mac
->neigh_list
)) {
5431 zvni_mac_del(zvni
, mac
);
5433 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5434 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5441 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
5442 * This can happen because the remote MAC entries are also added as "dynamic",
5443 * so the kernel can ageout the entry.
5445 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
5446 struct interface
*br_if
,
5447 struct ethaddr
*macaddr
, vlanid_t vid
)
5449 struct zebra_if
*zif
= NULL
;
5450 struct zebra_l2info_vxlan
*vxl
= NULL
;
5452 zebra_vni_t
*zvni
= NULL
;
5453 zebra_l3vni_t
*zl3vni
= NULL
;
5454 zebra_mac_t
*mac
= NULL
;
5455 char buf
[ETHER_ADDR_STRLEN
];
5459 vxl
= &zif
->l2info
.vxl
;
5462 /* Check if EVPN is enabled. */
5463 if (!is_evpn_enabled())
5466 /* check if this is a remote RMAC and readd simillar to remote macs */
5467 zl3vni
= zl3vni_lookup(vni
);
5469 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
5471 /* Locate hash entry; it is expected to exist. */
5472 zvni
= zvni_lookup(vni
);
5476 /* If entry doesn't exist, nothing to do. */
5477 mac
= zvni_mac_lookup(zvni
, macaddr
);
5481 /* Is it a remote entry? */
5482 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
5485 if (IS_ZEBRA_DEBUG_VXLAN
)
5486 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
5487 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5490 zvni_mac_install(zvni
, mac
);
5495 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
5497 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
5498 struct ethaddr
*macaddr
, vlanid_t vid
)
5502 char buf
[ETHER_ADDR_STRLEN
];
5504 /* We are interested in MACs only on ports or (port, VLAN) that
5507 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5510 if (!zvni
->vxlan_if
) {
5511 zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL",
5516 if (IS_ZEBRA_DEBUG_VXLAN
)
5517 zlog_debug("Del MAC %s intf %s(%u) VID %u -> VNI %u",
5518 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5519 ifp
->ifindex
, vid
, zvni
->vni
);
5521 /* If entry doesn't exist, nothing to do. */
5522 mac
= zvni_mac_lookup(zvni
, macaddr
);
5526 /* Is it a local entry? */
5527 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5530 /* Remove MAC from BGP. */
5531 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
, mac
->flags
);
5533 /* Update all the neigh entries associated with this mac */
5534 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
5537 * If there are no neigh associated with the mac delete the mac
5538 * else mark it as AUTO for forward reference
5540 if (!listcount(mac
->neigh_list
)) {
5541 zvni_mac_del(zvni
, mac
);
5543 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5544 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5551 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
5553 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
5554 struct interface
*br_if
,
5555 struct ethaddr
*macaddr
, vlanid_t vid
,
5560 char buf
[ETHER_ADDR_STRLEN
];
5564 /* We are interested in MACs only on ports or (port, VLAN) that
5567 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
5569 if (IS_ZEBRA_DEBUG_VXLAN
)
5571 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
5572 sticky
? "sticky " : "",
5573 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5574 ifp
->name
, ifp
->ifindex
, vid
);
5578 if (!zvni
->vxlan_if
) {
5579 zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD",
5584 if (IS_ZEBRA_DEBUG_VXLAN
)
5585 zlog_debug("Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u",
5586 sticky
? "sticky " : "",
5587 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
5588 ifp
->ifindex
, vid
, zvni
->vni
);
5590 /* If same entry already exists, nothing to do. */
5591 mac
= zvni_mac_lookup(zvni
, macaddr
);
5593 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5594 mac_sticky
= CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5600 * return if nothing has changed.
5601 * inform bgp if sticky flag has changed
5602 * update locally and do not inform bgp if local
5603 * parameters like interface has changed
5605 if (mac_sticky
== sticky
5606 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
5607 && mac
->fwd_info
.local
.vid
== vid
) {
5608 if (IS_ZEBRA_DEBUG_VXLAN
)
5610 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
5611 "entry exists and has not changed ",
5612 sticky
? "sticky " : "",
5613 prefix_mac2str(macaddr
, buf
,
5615 ifp
->name
, ifp
->ifindex
, vid
,
5618 } else if (mac_sticky
!= sticky
) {
5621 add
= 0; /* This is an update of local
5624 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5626 * If we have already learned the MAC as a remote sticky
5628 * this is a operator error and we must log a warning
5630 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
5632 "MAC %s is already learnt as a remote sticky mac behind VTEP %s VNI %d",
5633 prefix_mac2str(macaddr
, buf
,
5635 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
5643 mac
= zvni_mac_add(zvni
, macaddr
);
5645 zlog_err("Failed to add MAC %s intf %s(%u) VID %u",
5646 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5647 ifp
->name
, ifp
->ifindex
, vid
);
5652 /* Set "local" forwarding info. */
5653 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5654 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5655 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5656 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5657 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
5658 mac
->fwd_info
.local
.vid
= vid
;
5661 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5663 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5665 /* Inform BGP if required. */
5667 zvni_process_neigh_on_local_mac_add(zvni
, mac
);
5668 return zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
5676 * Handle message from client to delete a remote VTEP for a VNI.
5678 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
5681 unsigned short l
= 0;
5683 struct in_addr vtep_ip
;
5685 zebra_vtep_t
*zvtep
;
5686 struct interface
*ifp
;
5687 struct zebra_if
*zif
;
5689 if (!is_evpn_enabled()) {
5691 "%s: EVPN is not enabled yet we have received a vtep del command",
5692 __PRETTY_FUNCTION__
);
5696 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5697 zlog_err("Recv MACIP DEL for non-default VRF %u",
5704 while (l
< hdr
->length
) {
5705 /* Obtain each remote VTEP and process. */
5706 STREAM_GETL(s
, vni
);
5708 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5709 l
+= IPV4_MAX_BYTELEN
;
5711 if (IS_ZEBRA_DEBUG_VXLAN
)
5712 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
5713 inet_ntoa(vtep_ip
), vni
,
5714 zebra_route_string(client
->proto
));
5716 /* Locate VNI hash entry - expected to exist. */
5717 zvni
= zvni_lookup(vni
);
5719 if (IS_ZEBRA_DEBUG_VXLAN
)
5721 "Failed to locate VNI hash upon remote VTEP DEL, "
5727 ifp
= zvni
->vxlan_if
;
5730 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
5736 /* If down or not mapped to a bridge, we're done. */
5737 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5740 /* If the remote VTEP does not exist, there's nothing more to
5742 * Otherwise, uninstall any remote MACs pointing to this VTEP
5744 * then, the VTEP entry itself and remove it.
5746 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5750 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
5751 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
5752 zvni_vtep_uninstall(zvni
, &vtep_ip
);
5753 zvni_vtep_del(zvni
, zvtep
);
5761 * Handle message from client to add a remote VTEP for a VNI.
5763 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
5766 unsigned short l
= 0;
5768 struct in_addr vtep_ip
;
5770 struct interface
*ifp
;
5771 struct zebra_if
*zif
;
5773 if (!is_evpn_enabled()) {
5775 "%s: EVPN not enabled yet we received a vtep_add zapi call",
5776 __PRETTY_FUNCTION__
);
5780 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
5781 zlog_err("Recv MACIP ADD for non-default VRF %u",
5788 while (l
< hdr
->length
) {
5789 /* Obtain each remote VTEP and process. */
5790 STREAM_GETL(s
, vni
);
5792 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
5793 l
+= IPV4_MAX_BYTELEN
;
5795 if (IS_ZEBRA_DEBUG_VXLAN
)
5796 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
5797 inet_ntoa(vtep_ip
), vni
,
5798 zebra_route_string(client
->proto
));
5800 /* Locate VNI hash entry - expected to exist. */
5801 zvni
= zvni_lookup(vni
);
5804 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
5809 ifp
= zvni
->vxlan_if
;
5812 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
5819 /* If down or not mapped to a bridge, we're done. */
5820 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5823 /* If the remote VTEP already exists,
5824 there's nothing more to do. */
5825 if (zvni_vtep_find(zvni
, &vtep_ip
))
5828 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5829 zlog_err("Failed to add remote VTEP, VNI %u zvni %p",
5834 zvni_vtep_install(zvni
, &vtep_ip
);
5842 * Add/Del gateway macip to evpn
5844 * 1. SVI interface on a vlan aware bridge
5845 * 2. SVI interface on a vlan unaware bridge
5846 * 3. vrr interface (MACVLAN) associated to a SVI
5847 * We advertise macip routes for an interface if it is associated to VxLan vlan
5849 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
5853 struct ethaddr macaddr
;
5854 zebra_vni_t
*zvni
= NULL
;
5856 memset(&ip
, 0, sizeof(struct ipaddr
));
5857 memset(&macaddr
, 0, sizeof(struct ethaddr
));
5859 /* Check if EVPN is enabled. */
5860 if (!is_evpn_enabled())
5863 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
5864 struct interface
*svi_if
=
5865 NULL
; /* SVI corresponding to the MACVLAN */
5866 struct zebra_if
*ifp_zif
=
5867 NULL
; /* Zebra daemon specific info for MACVLAN */
5868 struct zebra_if
*svi_if_zif
=
5869 NULL
; /* Zebra daemon specific info for SVI*/
5871 ifp_zif
= ifp
->info
;
5876 * for a MACVLAN interface the link represents the svi_if
5878 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
5879 ifp_zif
->link_ifindex
);
5881 zlog_err("MACVLAN %s(%u) without link information",
5882 ifp
->name
, ifp
->ifindex
);
5886 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
5888 * If it is a vlan aware bridge then the link gives the
5889 * bridge information
5891 struct interface
*svi_if_link
= NULL
;
5893 svi_if_zif
= svi_if
->info
;
5895 svi_if_link
= if_lookup_by_index_per_ns(
5896 zebra_ns_lookup(NS_DEFAULT
),
5897 svi_if_zif
->link_ifindex
);
5898 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
5900 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
5902 * If it is a vlan unaware bridge then svi is the bridge
5905 zvni
= zvni_from_svi(svi_if
, svi_if
);
5907 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
5908 struct zebra_if
*svi_if_zif
=
5909 NULL
; /* Zebra daemon specific info for SVI */
5910 struct interface
*svi_if_link
=
5911 NULL
; /* link info for the SVI = bridge info */
5913 svi_if_zif
= ifp
->info
;
5915 svi_if_link
= if_lookup_by_index_per_ns(
5916 zebra_ns_lookup(NS_DEFAULT
),
5917 svi_if_zif
->link_ifindex
);
5919 zvni
= zvni_from_svi(ifp
, svi_if_link
);
5921 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
5922 zvni
= zvni_from_svi(ifp
, ifp
);
5928 if (!zvni
->vxlan_if
) {
5929 zlog_err("VNI %u hash %p doesn't have intf upon MACVLAN up",
5935 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
5937 if (p
->family
== AF_INET
) {
5938 ip
.ipa_type
= IPADDR_V4
;
5939 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
5940 sizeof(struct in_addr
));
5941 } else if (p
->family
== AF_INET6
) {
5942 ip
.ipa_type
= IPADDR_V6
;
5943 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
5944 sizeof(struct in6_addr
));
5949 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
5951 zvni_gw_macip_del(ifp
, zvni
, &ip
);
5957 * Handle SVI interface going down.
5958 * SVI can be associated to either L3-VNI or L2-VNI.
5959 * For L2-VNI: At this point, this is a NOP since
5960 * the kernel deletes the neighbor entries on this SVI (if any).
5961 * We only need to update the vrf corresponding to zvni.
5962 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
5965 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
5967 zebra_l3vni_t
*zl3vni
= NULL
;
5969 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
5972 /* process l3-vni down */
5973 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
5975 /* remove association with svi-if */
5976 zl3vni
->svi_if
= NULL
;
5978 zebra_vni_t
*zvni
= NULL
;
5980 /* since we dont have svi corresponding to zvni, we associate it
5981 * to default vrf. Note: the corresponding neigh entries on the
5982 * SVI would have already been deleted */
5983 zvni
= zvni_from_svi(ifp
, link_if
);
5985 zvni
->vrf_id
= VRF_DEFAULT
;
5987 /* update the tenant vrf in BGP */
5988 zvni_send_add_to_client(zvni
);
5995 * Handle SVI interface coming up.
5996 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
5998 * For L2-VNI: we need to install any remote neighbors entried (used for
6000 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
6002 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
6004 zebra_vni_t
*zvni
= NULL
;
6005 zebra_l3vni_t
*zl3vni
= NULL
;
6007 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6010 /* associate with svi */
6011 zl3vni
->svi_if
= ifp
;
6013 /* process oper-up */
6014 if (is_l3vni_oper_up(zl3vni
))
6015 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6018 /* process SVI up for l2-vni */
6019 struct neigh_walk_ctx n_wctx
;
6021 zvni
= zvni_from_svi(ifp
, link_if
);
6025 if (!zvni
->vxlan_if
) {
6026 zlog_err("VNI %u hash %p doesn't have intf upon SVI up",
6031 if (IS_ZEBRA_DEBUG_VXLAN
)
6033 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
6034 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
6035 vrf_id_to_name(ifp
->vrf_id
));
6037 /* update the vrf information for l2-vni and inform bgp */
6038 zvni
->vrf_id
= ifp
->vrf_id
;
6039 zvni_send_add_to_client(zvni
);
6041 /* Install any remote neighbors for this VNI. */
6042 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6044 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6052 * Handle VxLAN interface down
6054 int zebra_vxlan_if_down(struct interface
*ifp
)
6057 struct zebra_if
*zif
= NULL
;
6058 struct zebra_l2info_vxlan
*vxl
= NULL
;
6059 zebra_l3vni_t
*zl3vni
= NULL
;
6062 /* Check if EVPN is enabled. */
6063 if (!is_evpn_enabled())
6068 vxl
= &zif
->l2info
.vxl
;
6071 zl3vni
= zl3vni_lookup(vni
);
6073 /* process-if-down for l3-vni */
6074 if (IS_ZEBRA_DEBUG_VXLAN
)
6075 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
6078 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6080 /* process if-down for l2-vni */
6081 if (IS_ZEBRA_DEBUG_VXLAN
)
6082 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
6085 /* Locate hash entry; it is expected to exist. */
6086 zvni
= zvni_lookup(vni
);
6089 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
6090 ifp
->name
, ifp
->ifindex
, vni
);
6094 assert(zvni
->vxlan_if
== ifp
);
6096 /* Delete this VNI from BGP. */
6097 zvni_send_del_to_client(zvni
->vni
);
6099 /* Free up all neighbors and MACs, if any. */
6100 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6101 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6103 /* Free up all remote VTEPs, if any. */
6104 zvni_vtep_del_all(zvni
, 1);
6110 * Handle VxLAN interface up - update BGP if required.
6112 int zebra_vxlan_if_up(struct interface
*ifp
)
6115 struct zebra_if
*zif
= NULL
;
6116 struct zebra_l2info_vxlan
*vxl
= NULL
;
6117 zebra_vni_t
*zvni
= NULL
;
6118 zebra_l3vni_t
*zl3vni
= NULL
;
6120 /* Check if EVPN is enabled. */
6121 if (!is_evpn_enabled())
6126 vxl
= &zif
->l2info
.vxl
;
6129 zl3vni
= zl3vni_lookup(vni
);
6132 if (IS_ZEBRA_DEBUG_VXLAN
)
6133 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
6136 /* we need to associate with SVI, if any, we can associate with
6137 * svi-if only after association with vxlan-intf is complete
6139 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6141 if (is_l3vni_oper_up(zl3vni
))
6142 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6144 /* Handle L2-VNI add */
6145 struct interface
*vlan_if
= NULL
;
6147 if (IS_ZEBRA_DEBUG_VXLAN
)
6148 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
6151 /* Locate hash entry; it is expected to exist. */
6152 zvni
= zvni_lookup(vni
);
6155 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
6156 ifp
->name
, ifp
->ifindex
, vni
);
6160 assert(zvni
->vxlan_if
== ifp
);
6161 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6162 zif
->brslave_info
.br_if
);
6164 zvni
->vrf_id
= vlan_if
->vrf_id
;
6165 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6167 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6170 /* If part of a bridge, inform BGP about this VNI. */
6171 /* Also, read and populate local MACs and neighbors. */
6172 if (zif
->brslave_info
.br_if
) {
6173 zvni_send_add_to_client(zvni
);
6174 zvni_read_mac_neigh(zvni
, ifp
);
6182 * Handle VxLAN interface delete. Locate and remove entry in hash table
6183 * and update BGP, if required.
6185 int zebra_vxlan_if_del(struct interface
*ifp
)
6188 struct zebra_if
*zif
= NULL
;
6189 struct zebra_l2info_vxlan
*vxl
= NULL
;
6190 zebra_vni_t
*zvni
= NULL
;
6191 zebra_l3vni_t
*zl3vni
= NULL
;
6193 /* Check if EVPN is enabled. */
6194 if (!is_evpn_enabled())
6199 vxl
= &zif
->l2info
.vxl
;
6202 zl3vni
= zl3vni_lookup(vni
);
6205 if (IS_ZEBRA_DEBUG_VXLAN
)
6206 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
6209 /* process oper-down for l3-vni */
6210 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6212 /* remove the association with vxlan_if */
6213 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
6214 zl3vni
->vxlan_if
= NULL
;
6217 /* process if-del for l2-vni*/
6218 if (IS_ZEBRA_DEBUG_VXLAN
)
6219 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
6222 /* Locate hash entry; it is expected to exist. */
6223 zvni
= zvni_lookup(vni
);
6226 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
6227 ifp
->name
, ifp
->ifindex
, vni
);
6231 /* remove from l3-vni list */
6232 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
6234 listnode_delete(zl3vni
->l2vnis
, zvni
);
6236 /* Delete VNI from BGP. */
6237 zvni_send_del_to_client(zvni
->vni
);
6239 /* Free up all neighbors and MAC, if any. */
6240 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
6241 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
6243 /* Free up all remote VTEPs, if any. */
6244 zvni_vtep_del_all(zvni
, 0);
6246 /* Delete the hash entry. */
6247 if (zvni_del(zvni
)) {
6248 zlog_err("Failed to del VNI hash %p, IF %s(%u) VNI %u",
6249 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
6257 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
6259 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
6262 struct zebra_if
*zif
= NULL
;
6263 struct zebra_l2info_vxlan
*vxl
= NULL
;
6264 zebra_vni_t
*zvni
= NULL
;
6265 zebra_l3vni_t
*zl3vni
= NULL
;
6267 /* Check if EVPN is enabled. */
6268 if (!is_evpn_enabled())
6273 vxl
= &zif
->l2info
.vxl
;
6276 zl3vni
= zl3vni_lookup(vni
);
6279 if (IS_ZEBRA_DEBUG_VXLAN
)
6281 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6282 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6283 inet_ntoa(vxl
->vtep_ip
),
6284 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6286 /* Removed from bridge? Cleanup and return */
6287 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6288 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6289 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6293 /* access-vlan change - process oper down, associate with new
6294 * svi_if and then process oper up again
6296 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6297 if (if_is_operative(ifp
)) {
6298 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6299 zl3vni
->svi_if
= NULL
;
6300 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6301 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6302 if (is_l3vni_oper_up(zl3vni
))
6303 zebra_vxlan_process_l3vni_oper_up(
6309 * local-ip change - process oper down, associate with new
6310 * local-ip and then process oper up again
6312 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
6313 if (if_is_operative(ifp
)) {
6314 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6315 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6316 if (is_l3vni_oper_up(zl3vni
))
6317 zebra_vxlan_process_l3vni_oper_up(
6322 /* Update local tunnel IP. */
6323 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6325 /* if we have a valid new master, process l3-vni oper up */
6326 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
6327 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
6328 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6332 /* Update VNI hash. */
6333 zvni
= zvni_lookup(vni
);
6336 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
6337 ifp
->name
, ifp
->ifindex
, vni
);
6341 if (IS_ZEBRA_DEBUG_VXLAN
)
6343 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
6344 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6345 inet_ntoa(vxl
->vtep_ip
),
6346 zif
->brslave_info
.bridge_ifindex
, chgflags
);
6348 /* Removed from bridge? Cleanup and return */
6349 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6350 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
6351 /* Delete from client, remove all remote VTEPs */
6352 /* Also, free up all MACs and neighbors. */
6353 zvni_send_del_to_client(zvni
->vni
);
6354 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
6355 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
6356 zvni_vtep_del_all(zvni
, 1);
6360 /* Handle other changes. */
6361 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6362 /* Remove all existing local neigh and MACs for this VNI
6363 * (including from BGP)
6365 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6366 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
6369 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6370 zvni
->vxlan_if
= ifp
;
6372 /* Take further actions needed.
6373 * Note that if we are here, there is a change of interest.
6375 /* If down or not mapped to a bridge, we're done. */
6376 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6379 /* Inform BGP, if there is a change of interest. */
6381 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
6382 zvni_send_add_to_client(zvni
);
6384 /* If there is a valid new master or a VLAN mapping change,
6385 * read and populate local MACs and neighbors.
6386 * Also, reinstall any remote MACs and neighbors
6387 * for this VNI (based on new VLAN).
6389 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
6390 zvni_read_mac_neigh(zvni
, ifp
);
6391 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
6392 struct mac_walk_ctx m_wctx
;
6393 struct neigh_walk_ctx n_wctx
;
6395 zvni_read_mac_neigh(zvni
, ifp
);
6397 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6399 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
6402 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6404 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
6413 * Handle VxLAN interface add.
6415 int zebra_vxlan_if_add(struct interface
*ifp
)
6418 struct zebra_if
*zif
= NULL
;
6419 struct zebra_l2info_vxlan
*vxl
= NULL
;
6420 zebra_vni_t
*zvni
= NULL
;
6421 zebra_l3vni_t
*zl3vni
= NULL
;
6423 /* Check if EVPN is enabled. */
6424 if (!is_evpn_enabled())
6429 vxl
= &zif
->l2info
.vxl
;
6432 zl3vni
= zl3vni_lookup(vni
);
6435 /* process if-add for l3-vni*/
6436 if (IS_ZEBRA_DEBUG_VXLAN
)
6438 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
6439 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6440 inet_ntoa(vxl
->vtep_ip
),
6441 zif
->brslave_info
.bridge_ifindex
);
6443 /* associate with vxlan_if */
6444 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
6445 zl3vni
->vxlan_if
= ifp
;
6447 /* Associate with SVI, if any. We can associate with svi-if only
6448 * after association with vxlan_if is complete */
6449 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6451 if (is_l3vni_oper_up(zl3vni
))
6452 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6455 /* process if-add for l2-vni */
6456 struct interface
*vlan_if
= NULL
;
6458 /* Create or update VNI hash. */
6459 zvni
= zvni_lookup(vni
);
6461 zvni
= zvni_add(vni
);
6464 "Failed to add VNI hash, IF %s(%u) VNI %u",
6465 ifp
->name
, ifp
->ifindex
, vni
);
6470 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
6471 zvni
->vxlan_if
= ifp
;
6472 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
6473 zif
->brslave_info
.br_if
);
6475 zvni
->vrf_id
= vlan_if
->vrf_id
;
6476 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
6478 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
6481 if (IS_ZEBRA_DEBUG_VXLAN
)
6483 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
6485 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
6487 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
6488 inet_ntoa(vxl
->vtep_ip
),
6489 zif
->brslave_info
.bridge_ifindex
);
6491 /* If down or not mapped to a bridge, we're done. */
6492 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6496 zvni_send_add_to_client(zvni
);
6498 /* Read and populate local MACs and neighbors */
6499 zvni_read_mac_neigh(zvni
, ifp
);
6505 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
6506 char *err
, int err_str_sz
, int filter
,
6509 zebra_l3vni_t
*zl3vni
= NULL
;
6510 struct zebra_vrf
*zvrf_default
= NULL
;
6512 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
6516 if (IS_ZEBRA_DEBUG_VXLAN
)
6517 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
6518 add
? "ADD" : "DEL");
6522 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6524 /* check if the vni is already present under zvrf */
6526 snprintf(err
, err_str_sz
,
6527 "VNI is already configured under the vrf");
6531 /* check if this VNI is already present in the system */
6532 zl3vni
= zl3vni_lookup(vni
);
6534 snprintf(err
, err_str_sz
,
6535 "VNI is already configured as L3-VNI");
6539 /* add the L3-VNI to the global table */
6540 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
6542 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
6546 /* associate the vrf with vni */
6549 /* set the filter in l3vni to denote if we are using l3vni only
6553 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
6555 /* associate with vxlan-intf;
6556 * we need to associate with the vxlan-intf first
6558 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
6560 /* associate with corresponding SVI interface, we can associate
6561 * with svi-if only after vxlan interface association is
6564 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
6566 /* formulate l2vni list */
6567 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
6570 if (is_l3vni_oper_up(zl3vni
))
6571 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6574 zl3vni
= zl3vni_lookup(vni
);
6576 snprintf(err
, err_str_sz
, "VNI doesn't exist");
6580 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
6581 snprintf(err
, ERR_STR_SZ
,
6582 "prefix-routes-only is not set for the vni");
6586 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6588 /* delete and uninstall all rmacs */
6589 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
6592 /* delete and uninstall all next-hops */
6593 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
6599 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
6604 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
6606 zebra_l3vni_t
*zl3vni
= NULL
;
6609 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6613 zl3vni
->vrf_id
= zvrf_id(zvrf
);
6614 if (is_l3vni_oper_up(zl3vni
))
6615 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
6619 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
6621 zebra_l3vni_t
*zl3vni
= NULL
;
6624 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6628 zl3vni
->vrf_id
= VRF_UNKNOWN
;
6629 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
6633 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
6635 zebra_l3vni_t
*zl3vni
= NULL
;
6639 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6645 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
6651 * Handle message from client to enable/disable advertisement of g/w macip
6654 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
6659 zebra_vni_t
*zvni
= NULL
;
6660 struct interface
*ifp
= NULL
;
6661 struct zebra_if
*zif
= NULL
;
6662 struct zebra_l2info_vxlan zl2_info
;
6663 struct interface
*vlan_if
= NULL
;
6665 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6666 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6672 STREAM_GETC(s
, advertise
);
6673 vni
= stream_get3(s
);
6675 zvni
= zvni_lookup(vni
);
6679 if (zvni
->advertise_subnet
== advertise
)
6682 if (IS_ZEBRA_DEBUG_VXLAN
)
6683 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
6684 advertise
? "enabled" : "disabled", vni
,
6685 zvni
->advertise_subnet
? "enabled" : "disabled");
6688 zvni
->advertise_subnet
= advertise
;
6690 ifp
= zvni
->vxlan_if
;
6696 /* If down or not mapped to a bridge, we're done. */
6697 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6700 zl2_info
= zif
->l2info
.vxl
;
6703 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
6707 if (zvni
->advertise_subnet
)
6708 zvni_advertise_subnet(zvni
, vlan_if
, 1);
6710 zvni_advertise_subnet(zvni
, vlan_if
, 0);
6717 * Handle message from client to enable/disable advertisement of g/w macip
6720 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
6725 zebra_vni_t
*zvni
= NULL
;
6726 struct interface
*ifp
= NULL
;
6728 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6729 zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
6735 STREAM_GETC(s
, advertise
);
6736 STREAM_GETL(s
, vni
);
6739 if (IS_ZEBRA_DEBUG_VXLAN
)
6740 zlog_debug("EVPN gateway macip Adv %s, currently %s",
6741 advertise
? "enabled" : "disabled",
6742 advertise_gw_macip_enabled(NULL
)
6746 if (zvrf
->advertise_gw_macip
== advertise
)
6749 zvrf
->advertise_gw_macip
= advertise
;
6751 if (advertise_gw_macip_enabled(zvni
))
6752 hash_iterate(zvrf
->vni_table
,
6753 zvni_gw_macip_add_for_vni_hash
, NULL
);
6755 hash_iterate(zvrf
->vni_table
,
6756 zvni_gw_macip_del_for_vni_hash
, NULL
);
6759 struct zebra_if
*zif
= NULL
;
6760 struct zebra_l2info_vxlan zl2_info
;
6761 struct interface
*vlan_if
= NULL
;
6762 struct interface
*vrr_if
= NULL
;
6764 zvni
= zvni_lookup(vni
);
6768 if (IS_ZEBRA_DEBUG_VXLAN
)
6770 "EVPN gateway macip Adv %s on VNI %d , currently %s",
6771 advertise
? "enabled" : "disabled", vni
,
6772 advertise_gw_macip_enabled(zvni
) ? "enabled"
6775 if (zvni
->advertise_gw_macip
== advertise
)
6778 zvni
->advertise_gw_macip
= advertise
;
6780 ifp
= zvni
->vxlan_if
;
6786 /* If down or not mapped to a bridge, we're done. */
6787 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
6790 zl2_info
= zif
->l2info
.vxl
;
6792 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
6793 zif
->brslave_info
.br_if
);
6797 if (advertise_gw_macip_enabled(zvni
)) {
6798 /* Add primary SVI MAC-IP */
6799 zvni_add_macip_for_intf(vlan_if
, zvni
);
6801 /* Add VRR MAC-IP - if any*/
6802 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6804 zvni_add_macip_for_intf(vrr_if
, zvni
);
6806 /* Del primary MAC-IP */
6807 zvni_del_macip_for_intf(vlan_if
, zvni
);
6809 /* Del VRR MAC-IP - if any*/
6810 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
6812 zvni_del_macip_for_intf(vrr_if
, zvni
);
6822 * Handle message from client to learn (or stop learning) about VNIs and MACs.
6823 * When enabled, the VNI hash table will be built and MAC FDB table read;
6824 * when disabled, the entries should be deleted and remote VTEPs and MACs
6825 * uninstalled from the kernel.
6827 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
6829 struct stream
*s
= NULL
;
6831 struct zebra_ns
*zns
= NULL
;
6833 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
6834 zlog_err("EVPN VNI Adv for non-default VRF %u", zvrf_id(zvrf
));
6839 STREAM_GETC(s
, advertise
);
6841 if (IS_ZEBRA_DEBUG_VXLAN
)
6842 zlog_debug("EVPN VNI Adv %s, currently %s",
6843 advertise
? "enabled" : "disabled",
6844 is_evpn_enabled() ? "enabled" : "disabled");
6846 if (zvrf
->advertise_all_vni
== advertise
)
6849 zvrf
->advertise_all_vni
= advertise
;
6850 if (is_evpn_enabled()) {
6851 /* Build VNI hash table and inform BGP. */
6852 zvni_build_hash_table();
6854 /* Add all SVI (L3 GW) MACs to BGP*/
6855 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
6858 /* Read the MAC FDB */
6859 macfdb_read(zvrf
->zns
);
6861 /* Read neighbors */
6862 neigh_read(zvrf
->zns
);
6864 /* Cleanup VTEPs for all VNIs - uninstall from
6865 * kernel and free entries.
6867 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6869 /* cleanup all l3vnis */
6870 zns
= zebra_ns_lookup(NS_DEFAULT
);
6874 hash_iterate(zns
->l3vni_table
, zl3vni_cleanup_all
, NULL
);
6882 * Allocate VNI hash table for this VRF and do other initialization.
6883 * NOTE: Currently supported only for default VRF.
6885 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
6889 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
6890 "Zebra VRF VNI Table");
6893 /* Cleanup VNI info, but don't free the table. */
6894 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
6898 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6901 /* Close all VNI handling */
6902 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
6906 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
6907 hash_free(zvrf
->vni_table
);
6910 /* init the l3vni table */
6911 void zebra_vxlan_ns_init(struct zebra_ns
*zns
)
6913 zns
->l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
6914 "Zebra VRF L3 VNI table");
6917 /* free l3vni table */
6918 void zebra_vxlan_ns_disable(struct zebra_ns
*zns
)
6920 hash_free(zns
->l3vni_table
);
6923 /* get the l3vni svi ifindex */
6924 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
6926 zebra_l3vni_t
*zl3vni
= NULL
;
6928 zl3vni
= zl3vni_from_vrf(vrf_id
);
6929 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
6932 return zl3vni
->svi_if
->ifindex
;