2 * Zebra EVPN for VxLAN code
3 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
5 * This file is part of FRR.
7 * FRR is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * FRR is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with FRR; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
37 #include <linux/neighbour.h>
39 #include "lib/printfrr.h"
41 #include "zebra/zebra_router.h"
42 #include "zebra/debug.h"
43 #include "zebra/interface.h"
44 #include "zebra/rib.h"
46 #include "zebra/rt_netlink.h"
47 #include "zebra/zebra_errors.h"
48 #include "zebra/zebra_l2.h"
49 #include "zebra/zebra_l2_bridge_if.h"
50 #include "zebra/zebra_ns.h"
51 #include "zebra/zebra_vrf.h"
52 #include "zebra/zebra_vxlan.h"
53 #include "zebra/zebra_vxlan_private.h"
54 #include "zebra/zebra_evpn.h"
55 #include "zebra/zebra_evpn_mac.h"
56 #include "zebra/zebra_evpn_neigh.h"
57 #include "zebra/zebra_evpn_mh.h"
58 #include "zebra/zebra_evpn_vxlan.h"
59 #include "zebra/zebra_router.h"
61 DEFINE_MTYPE_STATIC(ZEBRA
, HOST_PREFIX
, "host prefix");
62 DEFINE_MTYPE_STATIC(ZEBRA
, ZL3VNI
, "L3 VNI hash");
63 DEFINE_MTYPE_STATIC(ZEBRA
, L3VNI_MAC
, "EVPN L3VNI MAC");
64 DEFINE_MTYPE_STATIC(ZEBRA
, L3NEIGH
, "EVPN Neighbor");
65 DEFINE_MTYPE_STATIC(ZEBRA
, ZVXLAN_SG
, "zebra VxLAN multicast group");
66 DEFINE_MTYPE_STATIC(ZEBRA
, EVPN_VTEP
, "zebra VxLAN VTEP IP");
68 DEFINE_HOOK(zebra_rmac_update
,
69 (struct zebra_mac
* rmac
, struct zebra_l3vni
*zl3vni
, bool delete,
71 (rmac
, zl3vni
, delete, reason
));
74 static bool accept_bgp_seq
= true;
76 /* static function declarations */
77 static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket
*bucket
,
79 static void zl3vni_print_nh(struct zebra_neigh
*n
, struct vty
*vty
,
81 static void zl3vni_print_rmac(struct zebra_mac
*zrmac
, struct vty
*vty
,
83 static void zevpn_print_mac_hash_all_evpn(struct hash_bucket
*bucket
, void *ctxt
);
85 /* l3-vni next-hop neigh related APIs */
86 static struct zebra_neigh
*zl3vni_nh_lookup(struct zebra_l3vni
*zl3vni
,
87 const struct ipaddr
*ip
);
88 static void *zl3vni_nh_alloc(void *p
);
89 static struct zebra_neigh
*zl3vni_nh_add(struct zebra_l3vni
*zl3vni
,
90 const struct ipaddr
*vtep_ip
,
91 const struct ethaddr
*rmac
);
92 static int zl3vni_nh_del(struct zebra_l3vni
*zl3vni
, struct zebra_neigh
*n
);
93 static int zl3vni_nh_install(struct zebra_l3vni
*zl3vni
, struct zebra_neigh
*n
);
94 static int zl3vni_nh_uninstall(struct zebra_l3vni
*zl3vni
,
95 struct zebra_neigh
*n
);
97 /* l3-vni rmac related APIs */
98 static void zl3vni_print_rmac_hash(struct hash_bucket
*, void *);
99 static struct zebra_mac
*zl3vni_rmac_lookup(struct zebra_l3vni
*zl3vni
,
100 const struct ethaddr
*rmac
);
101 static void *zl3vni_rmac_alloc(void *p
);
102 static struct zebra_mac
*zl3vni_rmac_add(struct zebra_l3vni
*zl3vni
,
103 const struct ethaddr
*rmac
);
104 static int zl3vni_rmac_del(struct zebra_l3vni
*zl3vni
, struct zebra_mac
*zrmac
);
105 static int zl3vni_rmac_install(struct zebra_l3vni
*zl3vni
,
106 struct zebra_mac
*zrmac
);
107 static int zl3vni_rmac_uninstall(struct zebra_l3vni
*zl3vni
,
108 struct zebra_mac
*zrmac
);
110 /* l3-vni related APIs*/
111 static void *zl3vni_alloc(void *p
);
112 static struct zebra_l3vni
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
113 static int zl3vni_del(struct zebra_l3vni
*zl3vni
);
115 static void zevpn_build_hash_table(void);
116 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
);
117 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
);
118 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
119 struct in_addr sip
, struct in_addr mcast_grp
);
120 static struct zebra_vxlan_sg
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*vrf
,
122 struct in_addr mcast_grp
);
123 static void zebra_vxlan_cleanup_sg_table(struct zebra_vrf
*zvrf
);
125 bool zebra_evpn_do_dup_addr_detect(struct zebra_vrf
*zvrf
)
127 return zvrf
->dup_addr_detect
&& zebra_evpn_mh_do_dup_addr_detect();
130 /* Private functions */
131 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
132 const struct host_rb_entry
*hle2
)
134 if (hle1
->p
.family
< hle2
->p
.family
)
137 if (hle1
->p
.family
> hle2
->p
.family
)
140 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
143 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
146 if (hle1
->p
.family
== AF_INET
) {
147 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
150 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
154 } else if (hle1
->p
.family
== AF_INET6
) {
155 return memcmp(&hle1
->p
.u
.prefix6
, &hle2
->p
.u
.prefix6
,
157 } else if (hle1
->p
.family
== AF_EVPN
) {
161 /* two (v4/v6) dummy prefixes of route_type BGP_EVPN_AD_ROUTE
162 * are used for all nexthops associated with a non-zero ESI
164 family1
= is_evpn_prefix_ipaddr_v4(
165 (const struct prefix_evpn
*)&hle1
->p
)
168 family2
= is_evpn_prefix_ipaddr_v4(
169 (const struct prefix_evpn
*)&hle2
->p
)
174 if (family1
< family2
)
177 if (family1
> family2
)
182 zlog_debug("%s: Unexpected family type: %d", __func__
,
187 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
189 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
191 struct host_rb_entry
*hle
;
194 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
200 static int l3vni_rmac_nh_list_cmp(void *p1
, void *p2
)
202 const struct ipaddr
*vtep_ip1
= p1
;
203 const struct ipaddr
*vtep_ip2
= p2
;
205 return !ipaddr_cmp(vtep_ip1
, vtep_ip2
);
208 static void l3vni_rmac_nh_free(struct ipaddr
*vtep_ip
)
210 XFREE(MTYPE_EVPN_VTEP
, vtep_ip
);
213 static void l3vni_rmac_nh_list_nh_delete(struct zebra_l3vni
*zl3vni
,
214 struct zebra_mac
*zrmac
,
215 struct ipaddr
*vtep_ip
)
217 struct listnode
*node
= NULL
, *nnode
= NULL
;
218 struct ipaddr
*vtep
= NULL
;
220 for (ALL_LIST_ELEMENTS(zrmac
->nh_list
, node
, nnode
, vtep
)) {
221 if (ipaddr_cmp(vtep
, vtep_ip
) == 0)
226 l3vni_rmac_nh_free(vtep
);
227 list_delete_node(zrmac
->nh_list
, node
);
232 * Print neighbors for all EVPN.
234 static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket
*bucket
,
238 json_object
*json
= NULL
, *json_evpn
= NULL
;
239 struct zebra_evpn
*zevpn
;
241 struct neigh_walk_ctx wctx
;
242 char vni_str
[VNI_STR_LEN
];
245 vty
= (struct vty
*)args
[0];
246 json
= (json_object
*)args
[1];
247 print_dup
= (uint32_t)(uintptr_t)args
[2];
249 zevpn
= (struct zebra_evpn
*)bucket
->data
;
251 num_neigh
= hashcount(zevpn
->neigh_table
);
254 num_neigh
= num_dup_detected_neighs(zevpn
);
258 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
259 zevpn
->vni
, num_neigh
);
261 json_evpn
= json_object_new_object();
262 json_object_int_add(json_evpn
, "numArpNd", num_neigh
);
263 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
268 json_object_object_add(json
, vni_str
, json_evpn
);
272 /* Since we have IPv6 addresses to deal with which can vary widely in
273 * size, we try to be a bit more elegant in display by first computing
276 memset(&wctx
, 0, sizeof(wctx
));
279 wctx
.addr_width
= 15;
280 wctx
.json
= json_evpn
;
281 hash_iterate(zevpn
->neigh_table
, zebra_evpn_find_neigh_addr_width
,
285 zebra_evpn_print_neigh_hdr(vty
, &wctx
);
288 hash_iterate(zevpn
->neigh_table
,
289 zebra_evpn_print_dad_neigh_hash
, &wctx
);
291 hash_iterate(zevpn
->neigh_table
, zebra_evpn_print_neigh_hash
,
295 json_object_object_add(json
, vni_str
, json_evpn
);
299 * Print neighbors for all EVPNs in detail.
301 static void zevpn_print_neigh_hash_all_evpn_detail(struct hash_bucket
*bucket
,
305 json_object
*json
= NULL
, *json_evpn
= NULL
;
306 struct zebra_evpn
*zevpn
;
308 struct neigh_walk_ctx wctx
;
309 char vni_str
[VNI_STR_LEN
];
312 vty
= (struct vty
*)args
[0];
313 json
= (json_object
*)args
[1];
314 print_dup
= (uint32_t)(uintptr_t)args
[2];
316 zevpn
= (struct zebra_evpn
*)bucket
->data
;
319 vty_out(vty
, "{}\n");
322 num_neigh
= hashcount(zevpn
->neigh_table
);
324 if (print_dup
&& num_dup_detected_neighs(zevpn
) == 0)
329 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
330 zevpn
->vni
, num_neigh
);
332 json_evpn
= json_object_new_object();
333 json_object_int_add(json_evpn
, "numArpNd", num_neigh
);
334 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
338 json_object_object_add(json
, vni_str
, json_evpn
);
342 memset(&wctx
, 0, sizeof(wctx
));
345 wctx
.addr_width
= 15;
346 wctx
.json
= json_evpn
;
349 hash_iterate(zevpn
->neigh_table
,
350 zebra_evpn_print_dad_neigh_hash_detail
, &wctx
);
352 hash_iterate(zevpn
->neigh_table
,
353 zebra_evpn_print_neigh_hash_detail
, &wctx
);
356 json_object_object_add(json
, vni_str
, json_evpn
);
359 /* print a specific next hop for an l3vni */
360 static void zl3vni_print_nh(struct zebra_neigh
*n
, struct vty
*vty
,
363 char buf1
[ETHER_ADDR_STRLEN
];
364 char buf2
[INET6_ADDRSTRLEN
];
365 json_object
*json_hosts
= NULL
;
366 struct host_rb_entry
*hle
;
369 vty_out(vty
, "Ip: %s\n",
370 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
371 vty_out(vty
, " RMAC: %s\n",
372 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
373 vty_out(vty
, " Refcount: %d\n",
374 rb_host_count(&n
->host_rb
));
375 vty_out(vty
, " Prefixes:\n");
376 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
377 vty_out(vty
, " %pFX\n", &hle
->p
);
379 json_hosts
= json_object_new_array();
380 json_object_string_add(
381 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
382 json_object_string_add(
384 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
385 json_object_int_add(json
, "refCount",
386 rb_host_count(&n
->host_rb
));
387 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
388 json_object_array_add(json_hosts
,
389 json_object_new_string(prefix2str(
390 &hle
->p
, buf2
, sizeof(buf2
))));
391 json_object_object_add(json
, "prefixList", json_hosts
);
395 /* Print a specific RMAC entry */
396 static void zl3vni_print_rmac(struct zebra_mac
*zrmac
, struct vty
*vty
,
399 struct listnode
*node
= NULL
;
400 struct ipaddr
*vtep
= NULL
;
401 json_object
*json_nhs
= NULL
;
404 vty_out(vty
, "MAC: %pEA\n", &zrmac
->macaddr
);
405 vty_out(vty
, " Remote VTEP: %pI4\n",
406 &zrmac
->fwd_info
.r_vtep_ip
);
408 json_nhs
= json_object_new_array();
409 json_object_string_addf(json
, "routerMac", "%pEA",
411 json_object_string_addf(json
, "vtepIp", "%pI4",
412 &zrmac
->fwd_info
.r_vtep_ip
);
413 for (ALL_LIST_ELEMENTS_RO(zrmac
->nh_list
, node
, vtep
)) {
414 json_object_array_add(json_nhs
, json_object_new_stringf(
417 json_object_object_add(json
, "nexthops", json_nhs
);
422 * Print MACs for all EVPNs.
424 static void zevpn_print_mac_hash_all_evpn(struct hash_bucket
*bucket
, void *ctxt
)
427 json_object
*json
= NULL
, *json_evpn
= NULL
;
428 json_object
*json_mac
= NULL
;
429 struct zebra_evpn
*zevpn
;
431 struct mac_walk_ctx
*wctx
= ctxt
;
432 char vni_str
[VNI_STR_LEN
];
437 zevpn
= (struct zebra_evpn
*)bucket
->data
;
440 /*We are iterating over a new VNI, set the count to 0*/
443 num_macs
= num_valid_macs(zevpn
);
448 num_macs
= num_dup_detected_macs(zevpn
);
451 json_evpn
= json_object_new_object();
452 json_mac
= json_object_new_object();
453 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
456 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
458 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
459 zevpn
->vni
, num_macs
);
461 "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
462 vty_out(vty
, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC",
463 "Type", "Flags", "Intf/Remote ES/VTEP",
466 json_object_int_add(json_evpn
, "numMacs", num_macs
);
471 json_object_int_add(json_evpn
, "numMacs", num_macs
);
472 json_object_object_add(json
, vni_str
, json_evpn
);
477 /* assign per-evpn to wctx->json object to fill macs
478 * under the evpn. Re-assign primary json object to fill
479 * next evpn information.
481 wctx
->json
= json_mac
;
483 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_dad_mac_hash
,
486 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_mac_hash
, wctx
);
490 json_object_object_add(json_evpn
, "macs", json_mac
);
491 json_object_object_add(json
, vni_str
, json_evpn
);
496 * Print MACs in detail for all EVPNs.
498 static void zevpn_print_mac_hash_all_evpn_detail(struct hash_bucket
*bucket
,
502 json_object
*json
= NULL
, *json_evpn
= NULL
;
503 json_object
*json_mac
= NULL
;
504 struct zebra_evpn
*zevpn
;
506 struct mac_walk_ctx
*wctx
= ctxt
;
507 char vni_str
[VNI_STR_LEN
];
512 zevpn
= (struct zebra_evpn
*)bucket
->data
;
515 vty_out(vty
, "{}\n");
520 /*We are iterating over a new EVPN, set the count to 0*/
523 num_macs
= num_valid_macs(zevpn
);
527 if (wctx
->print_dup
&& (num_dup_detected_macs(zevpn
) == 0))
531 json_evpn
= json_object_new_object();
532 json_mac
= json_object_new_object();
533 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
536 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
538 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
539 zevpn
->vni
, num_macs
);
541 json_object_int_add(json_evpn
, "numMacs", num_macs
);
543 /* assign per-evpn to wctx->json object to fill macs
544 * under the evpn. Re-assign primary json object to fill
545 * next evpn information.
547 wctx
->json
= json_mac
;
549 hash_iterate(zevpn
->mac_table
,
550 zebra_evpn_print_dad_mac_hash_detail
, wctx
);
552 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_mac_hash_detail
,
557 json_object_object_add(json_evpn
, "macs", json_mac
);
558 json_object_object_add(json
, vni_str
, json_evpn
);
562 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
564 struct nh_walk_ctx
*wctx
= NULL
;
565 struct vty
*vty
= NULL
;
566 struct json_object
*json_evpn
= NULL
;
567 struct json_object
*json_nh
= NULL
;
568 struct zebra_neigh
*n
= NULL
;
569 char buf1
[ETHER_ADDR_STRLEN
];
570 char buf2
[INET6_ADDRSTRLEN
];
572 wctx
= (struct nh_walk_ctx
*)ctx
;
574 json_evpn
= wctx
->json
;
576 json_nh
= json_object_new_object();
577 n
= (struct zebra_neigh
*)bucket
->data
;
580 vty_out(vty
, "%-15s %-17s\n",
581 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
582 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
584 json_object_string_add(json_nh
, "nexthopIp",
585 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
586 json_object_string_add(
587 json_nh
, "routerMac",
588 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
589 json_object_object_add(json_evpn
,
590 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
595 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
598 struct vty
*vty
= NULL
;
599 json_object
*json
= NULL
;
600 json_object
*json_evpn
= NULL
;
601 struct zebra_l3vni
*zl3vni
= NULL
;
603 struct nh_walk_ctx wctx
;
604 char vni_str
[VNI_STR_LEN
];
606 vty
= (struct vty
*)args
[0];
607 json
= (struct json_object
*)args
[1];
609 zl3vni
= (struct zebra_l3vni
*)bucket
->data
;
611 num_nh
= hashcount(zl3vni
->nh_table
);
616 json_evpn
= json_object_new_object();
617 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
621 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
622 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
624 json_object_int_add(json_evpn
, "numNextHops", num_nh
);
626 memset(&wctx
, 0, sizeof(wctx
));
628 wctx
.json
= json_evpn
;
629 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
631 json_object_object_add(json
, vni_str
, json_evpn
);
634 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
637 struct vty
*vty
= NULL
;
638 json_object
*json
= NULL
;
639 json_object
*json_evpn
= NULL
;
640 struct zebra_l3vni
*zl3vni
= NULL
;
642 struct rmac_walk_ctx wctx
;
643 char vni_str
[VNI_STR_LEN
];
645 vty
= (struct vty
*)args
[0];
646 json
= (struct json_object
*)args
[1];
648 zl3vni
= (struct zebra_l3vni
*)bucket
->data
;
650 num_rmacs
= hashcount(zl3vni
->rmac_table
);
655 json_evpn
= json_object_new_object();
656 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
660 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
661 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
663 json_object_int_add(json_evpn
, "numRmacs", num_rmacs
);
665 /* assign per-vni to wctx->json object to fill macs
666 * under the vni. Re-assign primary json object to fill
667 * next vni information.
669 memset(&wctx
, 0, sizeof(wctx
));
671 wctx
.json
= json_evpn
;
672 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
674 json_object_object_add(json
, vni_str
, json_evpn
);
677 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
679 struct zebra_mac
*zrmac
= NULL
;
680 struct rmac_walk_ctx
*wctx
= NULL
;
681 struct vty
*vty
= NULL
;
682 struct json_object
*json
= NULL
;
683 struct json_object
*json_rmac
= NULL
;
684 char buf
[PREFIX_STRLEN
];
686 wctx
= (struct rmac_walk_ctx
*)ctx
;
690 json_rmac
= json_object_new_object();
691 zrmac
= (struct zebra_mac
*)bucket
->data
;
694 vty_out(vty
, "%-17s %-21pI4\n",
695 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
696 &zrmac
->fwd_info
.r_vtep_ip
);
698 json_object_string_add(
699 json_rmac
, "routerMac",
700 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
701 json_object_string_addf(json_rmac
, "vtepIp", "%pI4",
702 &zrmac
->fwd_info
.r_vtep_ip
);
703 json_object_object_add(
704 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
709 /* print a specific L3 VNI entry */
710 static void zl3vni_print(struct zebra_l3vni
*zl3vni
, void **ctx
)
712 char buf
[PREFIX_STRLEN
];
713 struct vty
*vty
= NULL
;
714 json_object
*json
= NULL
;
715 struct zebra_evpn
*zevpn
= NULL
;
716 json_object
*json_evpn_list
= NULL
;
717 struct listnode
*node
= NULL
, *nnode
= NULL
;
723 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
724 vty_out(vty
, " Type: %s\n", "L3");
725 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
726 vty_out(vty
, " Vlan: %u\n", zl3vni
->vid
);
727 vty_out(vty
, " Bridge: %s\n",
728 zl3vni
->bridge_if
? zl3vni
->bridge_if
->name
: "-");
729 vty_out(vty
, " Local Vtep Ip: %pI4\n",
730 &zl3vni
->local_vtep_ip
);
731 vty_out(vty
, " Vxlan-Intf: %s\n",
732 zl3vni_vxlan_if_name(zl3vni
));
733 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
734 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
735 vty_out(vty
, " VNI Filter: %s\n",
736 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
737 ? "prefix-routes-only"
739 vty_out(vty
, " System MAC: %s\n",
740 zl3vni_sysmac2str(zl3vni
, buf
, sizeof(buf
)));
741 vty_out(vty
, " Router MAC: %s\n",
742 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
743 vty_out(vty
, " L2 VNIs: ");
744 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zevpn
))
745 vty_out(vty
, "%u ", zevpn
->vni
);
748 json_evpn_list
= json_object_new_array();
749 json_object_int_add(json
, "vni", zl3vni
->vni
);
750 json_object_string_add(json
, "type", "L3");
751 #if CONFDATE > 20240210
752 CPP_NOTICE("Drop `vrf` from JSON outputs")
754 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
755 json_object_string_add(json
, "tenantVrf",
756 zl3vni_vrf_name(zl3vni
));
757 json_object_string_addf(json
, "localVtepIp", "%pI4",
758 &zl3vni
->local_vtep_ip
);
759 json_object_string_add(json
, "vxlanIntf",
760 zl3vni_vxlan_if_name(zl3vni
));
761 json_object_string_add(json
, "sviIntf",
762 zl3vni_svi_if_name(zl3vni
));
763 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
764 json_object_string_add(
766 zl3vni_sysmac2str(zl3vni
, buf
, sizeof(buf
)));
767 json_object_string_add(
769 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
770 json_object_string_add(
772 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
773 ? "prefix-routes-only"
775 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zevpn
)) {
776 json_object_array_add(json_evpn_list
,
777 json_object_new_int(zevpn
->vni
));
779 json_object_object_add(json
, "l2Vnis", json_evpn_list
);
783 /* print a L3 VNI hash entry */
784 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
786 struct vty
*vty
= NULL
;
787 json_object
*json
= NULL
;
788 json_object
*json_evpn
= NULL
;
789 struct zebra_l3vni
*zl3vni
= NULL
;
791 vty
= (struct vty
*)ctx
[0];
792 json
= (json_object
*)ctx
[1];
794 zl3vni
= (struct zebra_l3vni
*)bucket
->data
;
797 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
798 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
799 hashcount(zl3vni
->rmac_table
),
800 hashcount(zl3vni
->nh_table
), "n/a",
801 zl3vni_vrf_name(zl3vni
));
803 char vni_str
[VNI_STR_LEN
];
805 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
806 json_evpn
= json_object_new_object();
807 json_object_int_add(json_evpn
, "vni", zl3vni
->vni
);
808 json_object_string_add(json_evpn
, "vxlanIf",
809 zl3vni_vxlan_if_name(zl3vni
));
810 json_object_int_add(json_evpn
, "numMacs",
811 hashcount(zl3vni
->rmac_table
));
812 json_object_int_add(json_evpn
, "numArpNd",
813 hashcount(zl3vni
->nh_table
));
814 json_object_string_add(json_evpn
, "numRemoteVteps", "n/a");
815 json_object_string_add(json_evpn
, "type", "L3");
816 json_object_string_add(json_evpn
, "tenantVrf",
817 zl3vni_vrf_name(zl3vni
));
818 json_object_object_add(json
, vni_str
, json_evpn
);
822 /* print a L3 VNI hash entry in detail*/
823 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
825 struct vty
*vty
= NULL
;
826 struct zebra_l3vni
*zl3vni
= NULL
;
827 json_object
*json_array
= NULL
;
828 bool use_json
= false;
829 struct zebra_evpn_show
*zes
= data
;
832 json_array
= zes
->json
;
833 use_json
= zes
->use_json
;
835 zl3vni
= (struct zebra_l3vni
*)bucket
->data
;
837 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
,
838 use_json
, json_array
);
844 static int zvni_map_to_svi_ns(struct ns
*ns
,
848 struct zebra_ns
*zns
= ns
->info
;
849 struct route_node
*rn
;
850 struct zebra_from_svi_param
*in_param
=
851 (struct zebra_from_svi_param
*)_in_param
;
852 struct zebra_l2info_vlan
*vl
;
853 struct interface
*tmp_if
= NULL
;
854 struct interface
**p_ifp
= (struct interface
**)_p_ifp
;
855 struct zebra_if
*zif
;
857 assert(in_param
&& p_ifp
);
859 /* TODO: Optimize with a hash. */
860 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
861 tmp_if
= (struct interface
*)rn
->info
;
862 /* Check oper status of the SVI. */
863 if (!tmp_if
|| !if_is_operative(tmp_if
))
866 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
867 || zif
->link
!= in_param
->br_if
)
869 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
871 if (vl
->vid
== in_param
->vid
) {
876 return NS_WALK_CONTINUE
;
879 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
881 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
882 * linked to the bridge
883 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge interface
886 struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
888 struct interface
*tmp_if
= NULL
;
889 struct zebra_if
*zif
;
890 struct zebra_from_svi_param in_param
;
891 struct interface
**p_ifp
;
892 /* Defensive check, caller expected to invoke only with valid bridge. */
896 /* Determine if bridge is VLAN-aware or not */
899 in_param
.bridge_vlan_aware
= IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zif
);
900 /* Check oper status of the SVI. */
901 if (!in_param
.bridge_vlan_aware
)
902 return if_is_operative(br_if
) ? br_if
: NULL
;
905 in_param
.br_if
= br_if
;
908 /* Identify corresponding VLAN interface. */
909 ns_walk_func(zvni_map_to_svi_ns
, (void *)&in_param
,
914 int zebra_evpn_vxlan_del(struct zebra_evpn
*zevpn
)
917 zevpn_vxlan_if_set(zevpn
, zevpn
->vxlan_if
, false /* set */);
918 zevpn_bridge_if_set(zevpn
, zevpn
->bridge_if
, false /* set */);
920 /* Remove references to the BUM mcast grp */
921 zebra_vxlan_sg_deref(zevpn
->local_vtep_ip
, zevpn
->mcast_grp
);
923 return zebra_evpn_del(zevpn
);
926 static int zevpn_build_vni_hash_table(struct zebra_if
*zif
,
927 struct zebra_vxlan_vni
*vnip
, void *arg
)
930 struct zebra_evpn
*zevpn
;
931 struct zebra_l3vni
*zl3vni
;
932 struct interface
*ifp
;
933 struct zebra_l2info_vxlan
*vxl
;
934 struct interface
*br_if
;
937 vxl
= &zif
->l2info
.vxl
;
940 if (IS_ZEBRA_DEBUG_VXLAN
)
941 zlog_debug("Build vni table for vni %u for Intf %s", vni
,
944 /* L3-VNI and L2-VNI are handled seperately */
945 zl3vni
= zl3vni_lookup(vni
);
948 if (IS_ZEBRA_DEBUG_VXLAN
)
950 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
951 ifp
->name
, ifp
->ifindex
, vni
);
953 /* associate with vxlan_if */
954 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
955 zl3vni
->vxlan_if
= ifp
;
958 * we need to associate with SVI.
959 * we can associate with svi-if only after association
960 * with vxlan-intf is complete
962 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
964 /* Associate l3vni to mac-vlan and extract VRR MAC */
965 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
967 if (IS_ZEBRA_DEBUG_VXLAN
)
969 "create l3vni %u svi_if %s mac_vlan_if %s", vni
,
970 zl3vni
->svi_if
? zl3vni
->svi_if
->name
: "NIL",
971 zl3vni
->mac_vlan_if
? zl3vni
->mac_vlan_if
->name
974 if (is_l3vni_oper_up(zl3vni
))
975 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
978 struct interface
*vlan_if
= NULL
;
980 if (IS_ZEBRA_DEBUG_VXLAN
)
982 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %pI4",
983 ifp
->name
, ifp
->ifindex
, vni
, &vxl
->vtep_ip
);
986 * EVPN hash entry is expected to exist, if the BGP process is
989 zevpn
= zebra_evpn_lookup(vni
);
992 "EVPN hash already present for IF %s(%u) L2-VNI %u",
993 ifp
->name
, ifp
->ifindex
, vni
);
996 * Inform BGP if intf is up and mapped to
999 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
1000 zebra_evpn_send_add_to_client(zevpn
);
1002 /* Send Local MAC-entries to client */
1003 zebra_evpn_send_mac_list_to_client(zevpn
);
1005 /* Send Loval Neighbor entries to client */
1006 zebra_evpn_send_neigh_to_client(zevpn
);
1008 zevpn
= zebra_evpn_add(vni
);
1011 "Failed to add EVPN hash, IF %s(%u) L2-VNI %u",
1012 ifp
->name
, ifp
->ifindex
, vni
);
1016 if (zevpn
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
1017 || zevpn
->mcast_grp
.s_addr
1018 != vnip
->mcast_grp
.s_addr
) {
1019 zebra_vxlan_sg_deref(zevpn
->local_vtep_ip
,
1021 zebra_vxlan_sg_ref(vxl
->vtep_ip
,
1023 zevpn
->local_vtep_ip
= vxl
->vtep_ip
;
1024 zevpn
->mcast_grp
= vnip
->mcast_grp
;
1025 /* on local vtep-ip check if ES
1026 * orig-ip needs to be updated
1028 zebra_evpn_es_set_base_evpn(zevpn
);
1030 zevpn_vxlan_if_set(zevpn
, ifp
, true /* set */);
1031 br_if
= zif
->brslave_info
.br_if
;
1032 zevpn_bridge_if_set(zevpn
, br_if
, true /* set */);
1033 vlan_if
= zvni_map_to_svi(vnip
->access_vlan
, br_if
);
1035 zevpn
->vid
= vnip
->access_vlan
;
1036 zevpn
->svi_if
= vlan_if
;
1037 zevpn
->vrf_id
= vlan_if
->vrf
->vrf_id
;
1038 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf
->vrf_id
);
1040 listnode_add_sort(zl3vni
->l2vnis
,
1045 * Inform BGP if intf is up and mapped to
1048 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
1049 zebra_evpn_send_add_to_client(zevpn
);
1056 static int zevpn_build_hash_table_zns(struct ns
*ns
,
1057 void *param_in
__attribute__((unused
)),
1058 void **param_out
__attribute__((unused
)))
1060 struct zebra_ns
*zns
= ns
->info
;
1061 struct route_node
*rn
;
1062 struct interface
*ifp
;
1063 struct zebra_vrf
*zvrf
;
1065 zvrf
= zebra_vrf_get_evpn();
1067 /* Walk VxLAN interfaces and create EVPN hash. */
1068 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
1069 struct zebra_if
*zif
;
1070 struct zebra_l2info_vxlan
*vxl
;
1072 ifp
= (struct interface
*)rn
->info
;
1076 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
1079 vxl
= &zif
->l2info
.vxl
;
1080 /* link of VXLAN interface should be in zebra_evpn_vrf */
1081 if (zvrf
->zns
->ns_id
!= vxl
->link_nsid
) {
1082 if (IS_ZEBRA_DEBUG_VXLAN
)
1084 "Intf %s(%u) link not in same "
1085 "namespace than BGP EVPN core instance ",
1086 ifp
->name
, ifp
->ifindex
);
1090 if (IS_ZEBRA_DEBUG_VXLAN
)
1091 zlog_debug("Building vni table for %s-if %s",
1092 IS_ZEBRA_VXLAN_IF_VNI(zif
) ? "vni" : "svd",
1095 zebra_vxlan_if_vni_iterate(zif
, zevpn_build_vni_hash_table
,
1098 return NS_WALK_CONTINUE
;
1102 * Build the VNI hash table by going over the VxLAN interfaces. This
1103 * is called when EVPN (advertise-all-vni) is enabled.
1106 static void zevpn_build_hash_table(void)
1108 ns_walk_func(zevpn_build_hash_table_zns
, NULL
, NULL
);
1112 * Cleanup EVPN/VTEP and update kernel
1114 static void zebra_evpn_vxlan_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
1116 struct zebra_evpn
*zevpn
= NULL
;
1117 struct zebra_l3vni
*zl3vni
= NULL
;
1119 zevpn
= (struct zebra_evpn
*)bucket
->data
;
1121 /* remove l2vni from l2vni's tenant-vrf l3-vni list */
1122 zl3vni
= zl3vni_from_vrf(zevpn
->vrf_id
);
1124 listnode_delete(zl3vni
->l2vnis
, zevpn
);
1126 zebra_evpn_cleanup_all(bucket
, arg
);
1130 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
1132 struct zebra_l3vni
*zl3vni
= NULL
;
1134 zl3vni
= (struct zebra_l3vni
*)bucket
->data
;
1136 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
1139 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
1140 const struct prefix
*host
)
1142 struct host_rb_entry lookup
;
1143 struct host_rb_entry
*hle
;
1145 memset(&lookup
, 0, sizeof(lookup
));
1146 memcpy(&lookup
.p
, host
, sizeof(*host
));
1148 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
1152 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
1153 memcpy(hle
, &lookup
, sizeof(lookup
));
1155 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
1158 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
1160 struct host_rb_entry lookup
;
1161 struct host_rb_entry
*hle
;
1163 memset(&lookup
, 0, sizeof(lookup
));
1164 memcpy(&lookup
.p
, host
, sizeof(*host
));
1166 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
1168 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
1169 XFREE(MTYPE_HOST_PREFIX
, hle
);
1176 * Look up MAC hash entry.
1178 static struct zebra_mac
*zl3vni_rmac_lookup(struct zebra_l3vni
*zl3vni
,
1179 const struct ethaddr
*rmac
)
1181 struct zebra_mac tmp
;
1182 struct zebra_mac
*pmac
;
1184 memset(&tmp
, 0, sizeof(tmp
));
1185 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
1186 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
1192 * Callback to allocate RMAC hash entry.
1194 static void *zl3vni_rmac_alloc(void *p
)
1196 const struct zebra_mac
*tmp_rmac
= p
;
1197 struct zebra_mac
*zrmac
;
1199 zrmac
= XCALLOC(MTYPE_L3VNI_MAC
, sizeof(struct zebra_mac
));
1202 return ((void *)zrmac
);
1206 * Add RMAC entry to l3-vni
1208 static struct zebra_mac
*zl3vni_rmac_add(struct zebra_l3vni
*zl3vni
,
1209 const struct ethaddr
*rmac
)
1211 struct zebra_mac tmp_rmac
;
1212 struct zebra_mac
*zrmac
= NULL
;
1214 memset(&tmp_rmac
, 0, sizeof(tmp_rmac
));
1215 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
1216 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
1217 zrmac
->nh_list
= list_new();
1218 zrmac
->nh_list
->cmp
= (int (*)(void *, void *))l3vni_rmac_nh_list_cmp
;
1219 zrmac
->nh_list
->del
= (void (*)(void *))l3vni_rmac_nh_free
;
1221 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
1222 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
1230 static int zl3vni_rmac_del(struct zebra_l3vni
*zl3vni
, struct zebra_mac
*zrmac
)
1232 struct zebra_mac
*tmp_rmac
;
1234 /* free the list of nh list*/
1235 list_delete(&zrmac
->nh_list
);
1237 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
1238 XFREE(MTYPE_L3VNI_MAC
, tmp_rmac
);
1244 * Install remote RMAC into the forwarding plane.
1246 static int zl3vni_rmac_install(struct zebra_l3vni
*zl3vni
,
1247 struct zebra_mac
*zrmac
)
1249 const struct zebra_if
*zif
= NULL
, *br_zif
= NULL
;
1250 const struct zebra_vxlan_vni
*vni
;
1251 const struct interface
*br_ifp
;
1252 enum zebra_dplane_result res
;
1255 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
1256 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
1259 zif
= zl3vni
->vxlan_if
->info
;
1263 br_ifp
= zif
->brslave_info
.br_if
;
1267 vni
= zebra_vxlan_if_vni_find(zif
, zl3vni
->vni
);
1269 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
1271 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
1272 vid
= vni
->access_vlan
;
1276 res
= dplane_rem_mac_add(zl3vni
->vxlan_if
, br_ifp
, vid
, &zrmac
->macaddr
,
1277 vni
->vni
, zrmac
->fwd_info
.r_vtep_ip
, 0, 0,
1278 false /*was_static*/);
1279 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
1286 * Uninstall remote RMAC from the forwarding plane.
1288 static int zl3vni_rmac_uninstall(struct zebra_l3vni
*zl3vni
,
1289 struct zebra_mac
*zrmac
)
1291 const struct zebra_if
*zif
= NULL
, *br_zif
;
1292 const struct zebra_vxlan_vni
*vni
;
1293 const struct interface
*br_ifp
;
1295 enum zebra_dplane_result res
;
1297 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
1298 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
1301 if (!zl3vni
->vxlan_if
) {
1302 if (IS_ZEBRA_DEBUG_VXLAN
)
1304 "RMAC %pEA on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
1305 &zrmac
->macaddr
, zl3vni
->vni
, zl3vni
);
1309 zif
= zl3vni
->vxlan_if
->info
;
1313 br_ifp
= zif
->brslave_info
.br_if
;
1317 vni
= zebra_vxlan_if_vni_find(zif
, zl3vni
->vni
);
1319 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
1320 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
1321 vid
= vni
->access_vlan
;
1325 res
= dplane_rem_mac_del(zl3vni
->vxlan_if
, br_ifp
, vid
, &zrmac
->macaddr
,
1326 vni
->vni
, zrmac
->fwd_info
.r_vtep_ip
);
1327 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
1333 /* handle rmac add */
1334 static int zl3vni_remote_rmac_add(struct zebra_l3vni
*zl3vni
,
1335 const struct ethaddr
*rmac
,
1336 const struct ipaddr
*vtep_ip
)
1338 struct zebra_mac
*zrmac
= NULL
;
1339 struct ipaddr
*vtep
= NULL
;
1341 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
1344 /* Create the RMAC entry, or update its vtep, if necessary. */
1345 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
1348 "Failed to add RMAC %pEA L3VNI %u Remote VTEP %pIA",
1349 rmac
, zl3vni
->vni
, vtep_ip
);
1352 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
1353 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
1355 vtep
= XCALLOC(MTYPE_EVPN_VTEP
, sizeof(struct ipaddr
));
1356 memcpy(vtep
, vtep_ip
, sizeof(struct ipaddr
));
1357 if (!listnode_add_sort_nodup(zrmac
->nh_list
, (void *)vtep
))
1358 XFREE(MTYPE_EVPN_VTEP
, vtep
);
1360 /* Send RMAC for FPM processing */
1361 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, false,
1364 /* install rmac in kernel */
1365 zl3vni_rmac_install(zl3vni
, zrmac
);
1366 } else if (!IPV4_ADDR_SAME(&zrmac
->fwd_info
.r_vtep_ip
,
1367 &vtep_ip
->ipaddr_v4
)) {
1368 if (IS_ZEBRA_DEBUG_VXLAN
)
1370 "L3VNI %u Remote VTEP change(%pI4 -> %pIA) for RMAC %pEA",
1371 zl3vni
->vni
, &zrmac
->fwd_info
.r_vtep_ip
,
1374 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
1376 vtep
= XCALLOC(MTYPE_EVPN_VTEP
, sizeof(struct ipaddr
));
1377 memcpy(vtep
, vtep_ip
, sizeof(struct ipaddr
));
1378 if (!listnode_add_sort_nodup(zrmac
->nh_list
, (void *)vtep
))
1379 XFREE(MTYPE_EVPN_VTEP
, vtep
);
1381 /* install rmac in kernel */
1382 zl3vni_rmac_install(zl3vni
, zrmac
);
1389 /* handle rmac delete */
1390 static void zl3vni_remote_rmac_del(struct zebra_l3vni
*zl3vni
,
1391 struct zebra_mac
*zrmac
,
1392 struct ipaddr
*vtep_ip
)
1394 struct ipaddr ipv4_vtep
;
1396 if (!zl3vni_nh_lookup(zl3vni
, vtep_ip
)) {
1397 memset(&ipv4_vtep
, 0, sizeof(ipv4_vtep
));
1398 ipv4_vtep
.ipa_type
= IPADDR_V4
;
1399 if (vtep_ip
->ipa_type
== IPADDR_V6
)
1400 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
1401 &ipv4_vtep
.ipaddr_v4
);
1403 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
1404 sizeof(struct in_addr
));
1406 /* remove nh from rmac's list */
1407 l3vni_rmac_nh_list_nh_delete(zl3vni
, zrmac
, &ipv4_vtep
);
1408 /* delete nh is same as current selected, fall back to
1409 * one present in the list
1411 if (IPV4_ADDR_SAME(&zrmac
->fwd_info
.r_vtep_ip
,
1412 &ipv4_vtep
.ipaddr_v4
) &&
1413 listcount(zrmac
->nh_list
)) {
1414 struct ipaddr
*vtep
;
1416 vtep
= listgetdata(listhead(zrmac
->nh_list
));
1417 zrmac
->fwd_info
.r_vtep_ip
= vtep
->ipaddr_v4
;
1418 if (IS_ZEBRA_DEBUG_VXLAN
)
1420 "L3VNI %u Remote VTEP nh change(%pIA -> %pI4) for RMAC %pEA",
1421 zl3vni
->vni
, &ipv4_vtep
,
1422 &zrmac
->fwd_info
.r_vtep_ip
,
1425 /* install rmac in kernel */
1426 zl3vni_rmac_install(zl3vni
, zrmac
);
1429 if (!listcount(zrmac
->nh_list
)) {
1430 /* uninstall from kernel */
1431 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
1433 /* Send RMAC for FPM processing */
1434 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true,
1437 if (IS_ZEBRA_DEBUG_VXLAN
)
1439 "L3VNI %u RMAC %pEA vtep_ip %pIA delete",
1440 zl3vni
->vni
, &zrmac
->macaddr
, vtep_ip
);
1442 /* del the rmac entry */
1443 zl3vni_rmac_del(zl3vni
, zrmac
);
1449 * Look up nh hash entry on a l3-vni.
1451 static struct zebra_neigh
*zl3vni_nh_lookup(struct zebra_l3vni
*zl3vni
,
1452 const struct ipaddr
*ip
)
1454 struct zebra_neigh tmp
;
1455 struct zebra_neigh
*n
;
1457 memset(&tmp
, 0, sizeof(tmp
));
1458 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
1459 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
1466 * Callback to allocate NH hash entry on L3-VNI.
1468 static void *zl3vni_nh_alloc(void *p
)
1470 const struct zebra_neigh
*tmp_n
= p
;
1471 struct zebra_neigh
*n
;
1473 n
= XCALLOC(MTYPE_L3NEIGH
, sizeof(struct zebra_neigh
));
1480 * Add neighbor entry.
1482 static struct zebra_neigh
*zl3vni_nh_add(struct zebra_l3vni
*zl3vni
,
1483 const struct ipaddr
*ip
,
1484 const struct ethaddr
*mac
)
1486 struct zebra_neigh tmp_n
;
1487 struct zebra_neigh
*n
= NULL
;
1489 memset(&tmp_n
, 0, sizeof(tmp_n
));
1490 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1491 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
1493 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
1495 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1496 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
1497 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
1503 * Delete neighbor entry.
1505 static int zl3vni_nh_del(struct zebra_l3vni
*zl3vni
, struct zebra_neigh
*n
)
1507 struct zebra_neigh
*tmp_n
;
1508 struct host_rb_entry
*hle
;
1510 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
1511 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
1513 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
1514 XFREE(MTYPE_HOST_PREFIX
, hle
);
1517 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
1518 XFREE(MTYPE_L3NEIGH
, tmp_n
);
1524 * Install remote nh as neigh into the kernel.
1526 static int zl3vni_nh_install(struct zebra_l3vni
*zl3vni
, struct zebra_neigh
*n
)
1531 if (!is_l3vni_oper_up(zl3vni
))
1534 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
1535 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
1538 flags
= DPLANE_NTF_EXT_LEARNED
;
1539 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
1540 flags
|= DPLANE_NTF_ROUTER
;
1542 dplane_rem_neigh_add(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
,
1543 false /*was_static*/);
1549 * Uninstall remote nh from the kernel.
1551 static int zl3vni_nh_uninstall(struct zebra_l3vni
*zl3vni
,
1552 struct zebra_neigh
*n
)
1554 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
1555 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
1558 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
1561 dplane_rem_neigh_delete(zl3vni
->svi_if
, &n
->ip
);
1566 /* add remote vtep as a neigh entry */
1567 static int zl3vni_remote_nh_add(struct zebra_l3vni
*zl3vni
,
1568 const struct ipaddr
*vtep_ip
,
1569 const struct ethaddr
*rmac
,
1570 const struct prefix
*host_prefix
)
1572 struct zebra_neigh
*nh
= NULL
;
1574 /* Create the next hop entry, or update its mac, if necessary. */
1575 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
1577 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
1580 "Failed to add NH %pIA as Neigh (RMAC %pEA L3-VNI %u prefix %pFX)",
1581 vtep_ip
, rmac
, zl3vni
->vni
, host_prefix
);
1585 /* install the nh neigh in kernel */
1586 zl3vni_nh_install(zl3vni
, nh
);
1587 } else if (memcmp(&nh
->emac
, rmac
, ETH_ALEN
) != 0) {
1588 if (IS_ZEBRA_DEBUG_VXLAN
)
1590 "L3VNI %u RMAC change(%pEA --> %pEA) for nexthop %pIA, prefix %pFX",
1591 zl3vni
->vni
, &nh
->emac
, rmac
, vtep_ip
,
1594 memcpy(&nh
->emac
, rmac
, ETH_ALEN
);
1595 /* install (update) the nh neigh in kernel */
1596 zl3vni_nh_install(zl3vni
, nh
);
1599 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
1604 /* handle nh neigh delete */
1605 static void zl3vni_remote_nh_del(struct zebra_l3vni
*zl3vni
,
1606 struct zebra_neigh
*nh
,
1607 struct prefix
*host_prefix
)
1609 rb_delete_host(&nh
->host_rb
, host_prefix
);
1611 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
1612 /* uninstall from kernel */
1613 zl3vni_nh_uninstall(zl3vni
, nh
);
1615 /* delete the nh entry */
1616 zl3vni_nh_del(zl3vni
, nh
);
1620 /* handle neigh update from kernel - the only thing of interest is to
1621 * readd stale entries.
1623 static int zl3vni_local_nh_add_update(struct zebra_l3vni
*zl3vni
,
1624 struct ipaddr
*ip
, uint16_t state
)
1627 struct zebra_neigh
*n
= NULL
;
1629 n
= zl3vni_nh_lookup(zl3vni
, ip
);
1633 /* all next hop neigh are remote and installed by frr.
1634 * If the kernel has aged this entry, re-install.
1636 if (state
& NUD_STALE
)
1637 zl3vni_nh_install(zl3vni
, n
);
1642 /* handle neigh delete from kernel */
1643 static int zl3vni_local_nh_del(struct zebra_l3vni
*zl3vni
, struct ipaddr
*ip
)
1645 struct zebra_neigh
*n
= NULL
;
1647 n
= zl3vni_nh_lookup(zl3vni
, ip
);
1651 /* all next hop neigh are remote and installed by frr.
1652 * If we get an age out notification for these neigh entries, we have to
1655 zl3vni_nh_install(zl3vni
, n
);
1661 * Hash function for L3 VNI.
1663 static unsigned int l3vni_hash_keymake(const void *p
)
1665 const struct zebra_l3vni
*zl3vni
= p
;
1667 return jhash_1word(zl3vni
->vni
, 0);
1671 * Compare 2 L3 VNI hash entries.
1673 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
1675 const struct zebra_l3vni
*zl3vni1
= p1
;
1676 const struct zebra_l3vni
*zl3vni2
= p2
;
1678 return (zl3vni1
->vni
== zl3vni2
->vni
);
1682 * Callback to allocate L3 VNI hash entry.
1684 static void *zl3vni_alloc(void *p
)
1686 struct zebra_l3vni
*zl3vni
= NULL
;
1687 const struct zebra_l3vni
*tmp_l3vni
= p
;
1689 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(struct zebra_l3vni
));
1690 zl3vni
->vni
= tmp_l3vni
->vni
;
1691 return ((void *)zl3vni
);
1695 * Look up L3 VNI hash entry.
1697 struct zebra_l3vni
*zl3vni_lookup(vni_t vni
)
1699 struct zebra_l3vni tmp_l3vni
;
1700 struct zebra_l3vni
*zl3vni
= NULL
;
1702 memset(&tmp_l3vni
, 0, sizeof(tmp_l3vni
));
1703 tmp_l3vni
.vni
= vni
;
1704 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
1710 * Add L3 VNI hash entry.
1712 static struct zebra_l3vni
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
1714 struct zebra_l3vni tmp_zl3vni
;
1715 struct zebra_l3vni
*zl3vni
= NULL
;
1717 memset(&tmp_zl3vni
, 0, sizeof(tmp_zl3vni
));
1718 tmp_zl3vni
.vni
= vni
;
1720 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
1722 zl3vni
->vrf_id
= vrf_id
;
1723 zl3vni
->svi_if
= NULL
;
1724 zl3vni
->vxlan_if
= NULL
;
1725 zl3vni
->l2vnis
= list_new();
1726 zl3vni
->l2vnis
->cmp
= zebra_evpn_list_cmp
;
1728 /* Create hash table for remote RMAC */
1729 zl3vni
->rmac_table
= zebra_mac_db_create("Zebra L3-VNI RMAC-Table");
1731 /* Create hash table for neighbors */
1732 zl3vni
->nh_table
= zebra_neigh_db_create("Zebra L3-VNI next-hop table");
1738 * Delete L3 VNI hash entry.
1740 static int zl3vni_del(struct zebra_l3vni
*zl3vni
)
1742 struct zebra_l3vni
*tmp_zl3vni
;
1744 /* free the list of l2vnis */
1745 list_delete(&zl3vni
->l2vnis
);
1746 zl3vni
->l2vnis
= NULL
;
1748 /* Free the rmac table */
1749 hash_free(zl3vni
->rmac_table
);
1750 zl3vni
->rmac_table
= NULL
;
1752 /* Free the nh table */
1753 hash_free(zl3vni
->nh_table
);
1754 zl3vni
->nh_table
= NULL
;
1756 /* Free the VNI hash entry and allocated memory. */
1757 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
1758 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
1763 static int zl3vni_map_to_vxlan_if_ns(struct ns
*ns
,
1767 struct zebra_ns
*zns
= ns
->info
;
1768 struct zebra_l3vni
*zl3vni
= (struct zebra_l3vni
*)_zl3vni
;
1769 struct route_node
*rn
= NULL
;
1770 struct interface
*ifp
= NULL
;
1771 struct zebra_vrf
*zvrf
;
1773 zvrf
= zebra_vrf_get_evpn();
1777 /* loop through all vxlan-interface */
1778 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
1780 struct zebra_if
*zif
= NULL
;
1781 struct zebra_l2info_vxlan
*vxl
;
1782 struct zebra_vxlan_vni
*vni
= NULL
;
1784 ifp
= (struct interface
*)rn
->info
;
1789 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
1792 vxl
= &zif
->l2info
.vxl
;
1793 vni
= zebra_vxlan_if_vni_find(zif
, zl3vni
->vni
);
1794 if (!vni
|| vni
->vni
!= zl3vni
->vni
)
1797 /* link of VXLAN interface should be in zebra_evpn_vrf */
1798 if (zvrf
->zns
->ns_id
!= vxl
->link_nsid
) {
1799 if (IS_ZEBRA_DEBUG_VXLAN
)
1801 "Intf %s(%u) VNI %u, link not in same "
1802 "namespace than BGP EVPN core instance ",
1803 ifp
->name
, ifp
->ifindex
, vni
->vni
);
1808 zl3vni
->local_vtep_ip
= zif
->l2info
.vxl
.vtep_ip
;
1809 *_pifp
= (void *)ifp
;
1810 return NS_WALK_STOP
;
1813 return NS_WALK_CONTINUE
;
1816 struct interface
*zl3vni_map_to_vxlan_if(struct zebra_l3vni
*zl3vni
)
1818 struct interface
**p_ifp
;
1819 struct interface
*ifp
= NULL
;
1823 ns_walk_func(zl3vni_map_to_vxlan_if_ns
,
1824 (void *)zl3vni
, (void **)p_ifp
);
1828 struct interface
*zl3vni_map_to_svi_if(struct zebra_l3vni
*zl3vni
)
1830 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
1831 struct zebra_vxlan_vni
*vni
= NULL
; /* vni info in vxlan_if */
1836 if (!zl3vni
->vxlan_if
)
1839 zif
= zl3vni
->vxlan_if
->info
;
1843 vni
= zebra_vxlan_if_vni_find(zif
, zl3vni
->vni
);
1847 return zvni_map_to_svi(vni
->access_vlan
, zif
->brslave_info
.br_if
);
1850 struct interface
*zl3vni_map_to_mac_vlan_if(struct zebra_l3vni
*zl3vni
)
1852 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
1857 if (!zl3vni
->vxlan_if
)
1860 zif
= zl3vni
->vxlan_if
->info
;
1864 return zebra_evpn_map_to_macvlan(zif
->brslave_info
.br_if
,
1869 struct zebra_l3vni
*zl3vni_from_vrf(vrf_id_t vrf_id
)
1871 struct zebra_vrf
*zvrf
= NULL
;
1873 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
1877 return zl3vni_lookup(zvrf
->l3vni
);
1880 static int zl3vni_from_svi_ns(struct ns
*ns
, void *_in_param
, void **_p_zl3vni
)
1884 struct zebra_ns
*zns
= ns
->info
;
1885 struct zebra_l3vni
**p_zl3vni
= (struct zebra_l3vni
**)_p_zl3vni
;
1886 struct zebra_from_svi_param
*in_param
=
1887 (struct zebra_from_svi_param
*)_in_param
;
1888 struct route_node
*rn
= NULL
;
1889 struct interface
*tmp_if
= NULL
;
1890 struct zebra_if
*zif
= NULL
;
1891 struct zebra_if
*br_zif
= NULL
;
1893 assert(in_param
&& p_zl3vni
);
1895 br_zif
= in_param
->br_if
->info
;
1898 if (in_param
->bridge_vlan_aware
) {
1899 vni_id
= zebra_l2_bridge_if_vni_find(br_zif
, in_param
->vid
);
1903 /* loop through all vxlan-interface */
1904 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
1905 tmp_if
= (struct interface
*)rn
->info
;
1909 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
1911 if (!if_is_operative(tmp_if
))
1914 if (zif
->brslave_info
.br_if
!= in_param
->br_if
)
1917 vni_id
= zebra_vxlan_if_access_vlan_vni_find(
1918 zif
, in_param
->br_if
);
1927 return NS_WALK_CONTINUE
;
1929 *p_zl3vni
= zl3vni_lookup(vni_id
);
1930 return NS_WALK_STOP
;
1934 * Map SVI and associated bridge to a VNI. This is invoked upon getting
1935 * neighbor notifications, to see if they are of interest.
1937 static struct zebra_l3vni
*zl3vni_from_svi(struct interface
*ifp
,
1938 struct interface
*br_if
)
1940 struct zebra_l3vni
*zl3vni
= NULL
;
1941 struct zebra_if
*zif
= NULL
;
1942 struct zebra_from_svi_param in_param
= {};
1943 struct zebra_l3vni
**p_zl3vni
;
1948 /* Make sure the linked interface is a bridge. */
1949 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
1951 in_param
.br_if
= br_if
;
1953 /* Determine if bridge is VLAN-aware or not */
1956 in_param
.bridge_vlan_aware
= IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zif
);
1957 if (in_param
.bridge_vlan_aware
) {
1958 struct zebra_l2info_vlan
*vl
;
1960 if (!IS_ZEBRA_IF_VLAN(ifp
))
1965 vl
= &zif
->l2info
.vl
;
1966 in_param
.vid
= vl
->vid
;
1969 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
1970 /* TODO: Optimize with a hash. */
1974 ns_walk_func(zl3vni_from_svi_ns
, (void *)&in_param
, (void **)p_zl3vni
);
1978 vni_t
vni_id_from_svi(struct interface
*ifp
, struct interface
*br_if
)
1981 struct zebra_evpn
*zevpn
= NULL
;
1982 struct zebra_l3vni
*zl3vni
= NULL
;
1984 /* Check if an L3VNI belongs to this SVI interface.
1985 * If not, check if an L2VNI belongs to this SVI interface.
1987 zl3vni
= zl3vni_from_svi(ifp
, br_if
);
1991 zevpn
= zebra_evpn_from_svi(ifp
, br_if
);
1999 static inline void zl3vni_get_vrr_rmac(struct zebra_l3vni
*zl3vni
,
2000 struct ethaddr
*rmac
)
2005 if (!is_l3vni_oper_up(zl3vni
))
2008 if (zl3vni
->mac_vlan_if
&& if_is_operative(zl3vni
->mac_vlan_if
))
2009 memcpy(rmac
->octet
, zl3vni
->mac_vlan_if
->hw_addr
, ETH_ALEN
);
2013 * Inform BGP about l3-vni.
2015 static int zl3vni_send_add_to_client(struct zebra_l3vni
*zl3vni
)
2017 struct stream
*s
= NULL
;
2018 struct zserv
*client
= NULL
;
2019 struct ethaddr svi_rmac
, vrr_rmac
= {.octet
= {0} };
2020 struct zebra_vrf
*zvrf
;
2021 bool is_anycast_mac
= true;
2023 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2024 /* BGP may not be running. */
2028 zvrf
= zebra_vrf_lookup_by_id(zl3vni
->vrf_id
);
2031 /* get the svi and vrr rmac values */
2032 memset(&svi_rmac
, 0, sizeof(svi_rmac
));
2033 zl3vni_get_svi_rmac(zl3vni
, &svi_rmac
);
2034 zl3vni_get_vrr_rmac(zl3vni
, &vrr_rmac
);
2036 /* In absence of vrr mac use svi mac as anycast MAC value */
2037 if (is_zero_mac(&vrr_rmac
)) {
2038 memcpy(&vrr_rmac
, &svi_rmac
, ETH_ALEN
);
2039 is_anycast_mac
= false;
2042 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2044 /* The message is used for both vni add and/or update like
2045 * vrr mac is added for l3vni SVI.
2047 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
2048 stream_putl(s
, zl3vni
->vni
);
2049 stream_put(s
, &svi_rmac
, sizeof(struct ethaddr
));
2050 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
2051 stream_put(s
, &zl3vni
->filter
, sizeof(int));
2052 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
2053 stream_put(s
, &vrr_rmac
, sizeof(struct ethaddr
));
2054 stream_putl(s
, is_anycast_mac
);
2056 /* Write packet size. */
2057 stream_putw_at(s
, 0, stream_get_endp(s
));
2059 if (IS_ZEBRA_DEBUG_VXLAN
)
2061 "Send L3_VNI_ADD %u VRF %s RMAC %pEA VRR %pEA local-ip %pI4 filter %s to %s",
2062 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
2063 &svi_rmac
, &vrr_rmac
, &zl3vni
->local_vtep_ip
,
2064 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
2065 ? "prefix-routes-only"
2067 zebra_route_string(client
->proto
));
2069 client
->l3vniadd_cnt
++;
2070 return zserv_send_message(client
, s
);
2074 * Inform BGP about local l3-VNI deletion.
2076 static int zl3vni_send_del_to_client(struct zebra_l3vni
*zl3vni
)
2078 struct stream
*s
= NULL
;
2079 struct zserv
*client
= NULL
;
2081 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2082 /* BGP may not be running. */
2086 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2088 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
2089 stream_putl(s
, zl3vni
->vni
);
2091 /* Write packet size. */
2092 stream_putw_at(s
, 0, stream_get_endp(s
));
2094 if (IS_ZEBRA_DEBUG_VXLAN
)
2095 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
2096 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
2097 zebra_route_string(client
->proto
));
2099 client
->l3vnidel_cnt
++;
2100 return zserv_send_message(client
, s
);
2103 void zebra_vxlan_process_l3vni_oper_up(struct zebra_l3vni
*zl3vni
)
2108 /* send l3vni add to BGP */
2109 zl3vni_send_add_to_client(zl3vni
);
2112 void zebra_vxlan_process_l3vni_oper_down(struct zebra_l3vni
*zl3vni
)
2117 /* send l3-vni del to BGP*/
2118 zl3vni_send_del_to_client(zl3vni
);
2121 static void zevpn_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
2123 struct zebra_evpn
*zevpn
= (struct zebra_evpn
*)bucket
->data
;
2124 struct zebra_l3vni
*zl3vni
= (struct zebra_l3vni
*)ctxt
;
2126 if (zevpn
->vrf_id
== zl3vni_vrf_id(zl3vni
))
2127 listnode_add_sort(zl3vni
->l2vnis
, zevpn
);
2131 * Handle transition of vni from l2 to l3 and vice versa.
2132 * This function handles only the L2VNI add/delete part of
2133 * the above transition.
2134 * L3VNI add/delete is handled by the calling functions.
2136 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
2139 struct zebra_evpn
*zevpn
= NULL
;
2140 struct zebra_l3vni
*zl3vni
= NULL
;
2142 /* There is a possibility that VNI notification was already received
2143 * from kernel and we programmed it as L2-VNI
2144 * In such a case we need to delete this L2-VNI first, so
2145 * that it can be reprogrammed as L3-VNI in the system. It is also
2146 * possible that the vrf-vni mapping is removed from FRR while the vxlan
2147 * interface is still present in kernel. In this case to keep it
2148 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
2151 /* Locate hash entry */
2152 zevpn
= zebra_evpn_lookup(vni
);
2156 if (IS_ZEBRA_DEBUG_VXLAN
)
2157 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
2159 /* Delete EVPN from BGP. */
2160 zebra_evpn_send_del_to_client(zevpn
);
2162 zebra_evpn_neigh_del_all(zevpn
, 0, 0, DEL_ALL_NEIGH
);
2163 zebra_evpn_mac_del_all(zevpn
, 0, 0, DEL_ALL_MAC
);
2165 /* Free up all remote VTEPs, if any. */
2166 zebra_evpn_vtep_del_all(zevpn
, 1);
2168 zl3vni
= zl3vni_from_vrf(zevpn
->vrf_id
);
2170 listnode_delete(zl3vni
->l2vnis
, zevpn
);
2172 /* Delete the hash entry. */
2173 if (zebra_evpn_vxlan_del(zevpn
)) {
2174 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
2175 "Failed to del EVPN hash %p, VNI %u", zevpn
,
2180 struct zebra_ns
*zns
;
2181 struct route_node
*rn
;
2182 struct interface
*ifp
;
2183 struct zebra_if
*zif
;
2184 struct zebra_vxlan_vni
*vnip
;
2185 struct zebra_l2info_vxlan
*vxl
;
2186 struct interface
*vlan_if
;
2189 if (IS_ZEBRA_DEBUG_VXLAN
)
2190 zlog_debug("Adding L2-VNI %u - transition from L3-VNI",
2193 /* Find VxLAN interface for this VNI. */
2194 zns
= zebra_ns_lookup(NS_DEFAULT
);
2195 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2196 ifp
= (struct interface
*)rn
->info
;
2200 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2203 vxl
= &zif
->l2info
.vxl
;
2204 vnip
= zebra_vxlan_if_vni_find(zif
, vni
);
2212 if (IS_ZEBRA_DEBUG_VXLAN
)
2214 "Adding L2-VNI - Failed to find VxLAN interface for VNI %u",
2219 /* Create VNI hash entry for L2VNI */
2220 zevpn
= zebra_evpn_lookup(vni
);
2224 zevpn
= zebra_evpn_add(vni
);
2226 /* Find bridge interface for the VNI */
2227 vlan_if
= zvni_map_to_svi(vnip
->access_vlan
,
2228 zif
->brslave_info
.br_if
);
2230 zevpn
->vrf_id
= vlan_if
->vrf
->vrf_id
;
2231 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf
->vrf_id
);
2233 listnode_add_sort_nodup(zl3vni
->l2vnis
, zevpn
);
2236 zevpn
->vxlan_if
= ifp
;
2237 zevpn
->local_vtep_ip
= vxl
->vtep_ip
;
2239 /* Inform BGP if the VNI is up and mapped to a bridge. */
2240 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
) {
2241 zebra_evpn_send_add_to_client(zevpn
);
2242 zebra_evpn_read_mac_neigh(zevpn
, ifp
);
2249 /* delete and uninstall rmac hash entry */
2250 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
2252 struct zebra_mac
*zrmac
= NULL
;
2253 struct zebra_l3vni
*zl3vni
= NULL
;
2255 zrmac
= (struct zebra_mac
*)bucket
->data
;
2256 zl3vni
= (struct zebra_l3vni
*)ctx
;
2257 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
2259 /* Send RMAC for FPM processing */
2260 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true, "RMAC deleted");
2262 zl3vni_rmac_del(zl3vni
, zrmac
);
2265 /* delete and uninstall nh hash entry */
2266 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
2268 struct zebra_neigh
*n
= NULL
;
2269 struct zebra_l3vni
*zl3vni
= NULL
;
2271 n
= (struct zebra_neigh
*)bucket
->data
;
2272 zl3vni
= (struct zebra_l3vni
*)ctx
;
2273 zl3vni_nh_uninstall(zl3vni
, n
);
2274 zl3vni_nh_del(zl3vni
, n
);
2277 /* re-add remote rmac if needed */
2278 static int zebra_vxlan_readd_remote_rmac(struct zebra_l3vni
*zl3vni
,
2279 struct ethaddr
*rmac
)
2281 struct zebra_mac
*zrmac
= NULL
;
2283 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
2287 if (IS_ZEBRA_DEBUG_VXLAN
)
2288 zlog_debug("Del remote RMAC %pEA L3VNI %u - readd",
2291 zl3vni_rmac_install(zl3vni
, zrmac
);
2295 /* Public functions */
2297 int is_l3vni_for_prefix_routes_only(vni_t vni
)
2299 struct zebra_l3vni
*zl3vni
= NULL
;
2301 zl3vni
= zl3vni_lookup(vni
);
2305 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
2308 /* handle evpn route in vrf table */
2309 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, const struct ethaddr
*rmac
,
2310 const struct ipaddr
*vtep_ip
,
2311 const struct prefix
*host_prefix
)
2313 struct zebra_l3vni
*zl3vni
= NULL
;
2314 struct ipaddr ipv4_vtep
;
2316 zl3vni
= zl3vni_from_vrf(vrf_id
);
2317 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
2321 * add the next hop neighbor -
2322 * neigh to be installed is the ipv6 nexthop neigh
2324 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
2327 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
2328 * address. Rmac is programmed against the ipv4 vtep because we only
2329 * support ipv4 tunnels in the h/w right now
2331 memset(&ipv4_vtep
, 0, sizeof(ipv4_vtep
));
2332 ipv4_vtep
.ipa_type
= IPADDR_V4
;
2333 if (vtep_ip
->ipa_type
== IPADDR_V6
)
2334 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
2335 &(ipv4_vtep
.ipaddr_v4
));
2337 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
2338 sizeof(struct in_addr
));
2341 * add the rmac - remote rmac to be installed is against the ipv4
2344 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
);
2347 /* handle evpn vrf route delete */
2348 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
2349 struct ipaddr
*vtep_ip
,
2350 struct prefix
*host_prefix
)
2352 struct zebra_l3vni
*zl3vni
= NULL
;
2353 struct zebra_neigh
*nh
= NULL
;
2354 struct zebra_mac
*zrmac
= NULL
;
2356 zl3vni
= zl3vni_from_vrf(vrf_id
);
2360 /* find the next hop entry and rmac entry */
2361 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
2364 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
2366 /* delete the next hop entry */
2367 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
2369 /* delete the rmac entry */
2371 zl3vni_remote_rmac_del(zl3vni
, zrmac
, vtep_ip
);
2374 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
2375 struct ethaddr
*rmac
, bool use_json
)
2377 struct zebra_l3vni
*zl3vni
= NULL
;
2378 struct zebra_mac
*zrmac
= NULL
;
2379 json_object
*json
= NULL
;
2381 if (!is_evpn_enabled()) {
2383 vty_out(vty
, "{}\n");
2388 json
= json_object_new_object();
2390 zl3vni
= zl3vni_lookup(l3vni
);
2393 vty_out(vty
, "{}\n");
2395 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
2399 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
2402 vty_out(vty
, "{}\n");
2405 "%% Requested RMAC doesn't exist in L3-VNI %u\n",
2410 zl3vni_print_rmac(zrmac
, vty
, json
);
2413 vty_json(vty
, json
);
2416 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
2418 struct zebra_l3vni
*zl3vni
;
2420 struct rmac_walk_ctx wctx
;
2421 json_object
*json
= NULL
;
2423 if (!is_evpn_enabled())
2426 zl3vni
= zl3vni_lookup(l3vni
);
2429 vty_out(vty
, "{}\n");
2431 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
2434 num_rmacs
= hashcount(zl3vni
->rmac_table
);
2439 json
= json_object_new_object();
2441 memset(&wctx
, 0, sizeof(wctx
));
2445 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
2447 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
2449 json_object_int_add(json
, "numRmacs", num_rmacs
);
2451 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
2454 vty_json(vty
, json
);
2457 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
2459 json_object
*json
= NULL
;
2462 if (!is_evpn_enabled()) {
2464 vty_out(vty
, "{}\n");
2469 json
= json_object_new_object();
2473 hash_iterate(zrouter
.l3vni_table
,
2474 (void (*)(struct hash_bucket
*,
2475 void *))zl3vni_print_rmac_hash_all_vni
,
2479 vty_json(vty
, json
);
2482 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
2483 struct ipaddr
*ip
, bool use_json
)
2485 struct zebra_l3vni
*zl3vni
= NULL
;
2486 struct zebra_neigh
*n
= NULL
;
2487 json_object
*json
= NULL
;
2489 if (!is_evpn_enabled()) {
2491 vty_out(vty
, "{}\n");
2496 json
= json_object_new_object();
2498 zl3vni
= zl3vni_lookup(l3vni
);
2501 vty_out(vty
, "{}\n");
2503 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
2507 n
= zl3vni_nh_lookup(zl3vni
, ip
);
2510 vty_out(vty
, "{}\n");
2513 "%% Requested next-hop not present for L3-VNI %u",
2518 zl3vni_print_nh(n
, vty
, json
);
2521 vty_json(vty
, json
);
2524 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
2527 struct nh_walk_ctx wctx
;
2528 json_object
*json
= NULL
;
2529 struct zebra_l3vni
*zl3vni
= NULL
;
2531 if (!is_evpn_enabled())
2534 zl3vni
= zl3vni_lookup(l3vni
);
2537 vty_out(vty
, "{}\n");
2539 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
2543 num_nh
= hashcount(zl3vni
->nh_table
);
2548 json
= json_object_new_object();
2553 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
2555 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
2557 json_object_int_add(json
, "numNextHops", num_nh
);
2559 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
2562 vty_json(vty
, json
);
2565 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
2567 json_object
*json
= NULL
;
2570 if (!is_evpn_enabled()) {
2572 vty_out(vty
, "{}\n");
2577 json
= json_object_new_object();
2581 hash_iterate(zrouter
.l3vni_table
,
2582 (void (*)(struct hash_bucket
*,
2583 void *))zl3vni_print_nh_hash_all_vni
,
2587 vty_json(vty
, json
);
2591 * Display L3 VNI information (VTY command handler).
2593 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
2596 json_object
*json
= NULL
;
2597 struct zebra_l3vni
*zl3vni
= NULL
;
2599 if (!is_evpn_enabled()) {
2601 vty_out(vty
, "{}\n");
2605 zl3vni
= zl3vni_lookup(vni
);
2608 vty_out(vty
, "{}\n");
2610 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2615 json
= json_object_new_object();
2619 zl3vni_print(zl3vni
, (void *)args
);
2622 vty_json(vty
, json
);
2625 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2626 json_object
*json_vrfs
)
2628 char buf
[ETHER_ADDR_STRLEN
];
2629 struct zebra_l3vni
*zl3vni
= NULL
;
2631 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
2636 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
2637 zvrf_name(zvrf
), zl3vni
->vni
,
2638 zl3vni_vxlan_if_name(zl3vni
),
2639 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
2640 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
2642 json_object
*json_vrf
= NULL
;
2644 json_vrf
= json_object_new_object();
2645 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
2646 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
2647 json_object_string_add(json_vrf
, "vxlanIntf",
2648 zl3vni_vxlan_if_name(zl3vni
));
2649 json_object_string_add(json_vrf
, "sviIntf",
2650 zl3vni_svi_if_name(zl3vni
));
2651 json_object_string_add(json_vrf
, "state",
2652 zl3vni_state2str(zl3vni
));
2653 json_object_string_add(
2654 json_vrf
, "routerMac",
2655 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
2656 json_object_array_add(json_vrfs
, json_vrf
);
2661 * Display Neighbors for a VNI (VTY command handler).
2663 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2664 vni_t vni
, bool use_json
)
2666 struct zebra_evpn
*zevpn
;
2668 struct neigh_walk_ctx wctx
;
2669 json_object
*json
= NULL
;
2671 if (!is_evpn_enabled())
2673 zevpn
= zebra_evpn_lookup(vni
);
2676 vty_out(vty
, "{}\n");
2678 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2681 num_neigh
= hashcount(zevpn
->neigh_table
);
2686 json
= json_object_new_object();
2688 /* Since we have IPv6 addresses to deal with which can vary widely in
2689 * size, we try to be a bit more elegant in display by first computing
2690 * the maximum width.
2692 memset(&wctx
, 0, sizeof(wctx
));
2695 wctx
.addr_width
= 15;
2697 hash_iterate(zevpn
->neigh_table
, zebra_evpn_find_neigh_addr_width
,
2702 "Number of ARPs (local and remote) known for this VNI: %u\n",
2704 zebra_evpn_print_neigh_hdr(vty
, &wctx
);
2706 json_object_int_add(json
, "numArpNd", num_neigh
);
2708 hash_iterate(zevpn
->neigh_table
, zebra_evpn_print_neigh_hash
, &wctx
);
2710 vty_json(vty
, json
);
2714 * Display neighbors across all VNIs (VTY command handler).
2716 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2717 bool print_dup
, bool use_json
)
2719 json_object
*json
= NULL
;
2722 if (!is_evpn_enabled())
2726 json
= json_object_new_object();
2730 args
[2] = (void *)(ptrdiff_t)print_dup
;
2732 hash_iterate(zvrf
->evpn_table
,
2733 (void (*)(struct hash_bucket
*,
2734 void *))zevpn_print_neigh_hash_all_evpn
,
2737 vty_json(vty
, json
);
2741 * Display neighbors across all VNIs in detail(VTY command handler).
2743 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
2744 struct zebra_vrf
*zvrf
,
2745 bool print_dup
, bool use_json
)
2747 json_object
*json
= NULL
;
2750 if (!is_evpn_enabled())
2754 json
= json_object_new_object();
2758 args
[2] = (void *)(ptrdiff_t)print_dup
;
2760 hash_iterate(zvrf
->evpn_table
,
2761 (void (*)(struct hash_bucket
*,
2762 void *))zevpn_print_neigh_hash_all_evpn_detail
,
2765 vty_json(vty
, json
);
2769 * Display specific neighbor for a VNI, if present (VTY command handler).
2771 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
2772 struct zebra_vrf
*zvrf
, vni_t vni
,
2773 struct ipaddr
*ip
, bool use_json
)
2775 struct zebra_evpn
*zevpn
;
2776 struct zebra_neigh
*n
;
2777 json_object
*json
= NULL
;
2779 if (!is_evpn_enabled())
2781 zevpn
= zebra_evpn_lookup(vni
);
2784 vty_out(vty
, "{}\n");
2786 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2789 n
= zebra_evpn_neigh_lookup(zevpn
, ip
);
2793 "%% Requested neighbor does not exist in VNI %u\n",
2798 json
= json_object_new_object();
2800 zebra_evpn_print_neigh(n
, vty
, json
);
2803 vty_json(vty
, json
);
2807 * Display neighbors for a VNI from specific VTEP (VTY command handler).
2808 * By definition, these are remote neighbors.
2810 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2811 vni_t vni
, struct in_addr vtep_ip
,
2814 struct zebra_evpn
*zevpn
;
2816 struct neigh_walk_ctx wctx
;
2817 json_object
*json
= NULL
;
2819 if (!is_evpn_enabled())
2821 zevpn
= zebra_evpn_lookup(vni
);
2824 vty_out(vty
, "{}\n");
2826 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2829 num_neigh
= hashcount(zevpn
->neigh_table
);
2834 json
= json_object_new_object();
2836 memset(&wctx
, 0, sizeof(wctx
));
2839 wctx
.addr_width
= 15;
2840 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
2841 wctx
.r_vtep_ip
= vtep_ip
;
2843 hash_iterate(zevpn
->neigh_table
, zebra_evpn_find_neigh_addr_width
,
2845 hash_iterate(zevpn
->neigh_table
, zebra_evpn_print_neigh_hash
, &wctx
);
2848 vty_json(vty
, json
);
2852 * Display Duplicate detected Neighbors for a VNI
2853 * (VTY command handler).
2855 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
2856 struct zebra_vrf
*zvrf
,
2860 struct zebra_evpn
*zevpn
;
2862 struct neigh_walk_ctx wctx
;
2863 json_object
*json
= NULL
;
2865 if (!is_evpn_enabled())
2868 zevpn
= zebra_evpn_lookup(vni
);
2870 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2874 num_neigh
= hashcount(zevpn
->neigh_table
);
2878 num_neigh
= num_dup_detected_neighs(zevpn
);
2883 json
= json_object_new_object();
2885 /* Since we have IPv6 addresses to deal with which can vary widely in
2886 * size, we try to be a bit more elegant in display by first computing
2887 * the maximum width.
2889 memset(&wctx
, 0, sizeof(wctx
));
2892 wctx
.addr_width
= 15;
2894 hash_iterate(zevpn
->neigh_table
, zebra_evpn_find_neigh_addr_width
,
2899 "Number of ARPs (local and remote) known for this VNI: %u\n",
2901 vty_out(vty
, "%*s %-6s %-8s %-17s %-30s\n",
2902 -wctx
.addr_width
, "IP", "Type",
2903 "State", "MAC", "Remote ES/VTEP");
2905 json_object_int_add(json
, "numArpNd", num_neigh
);
2907 hash_iterate(zevpn
->neigh_table
, zebra_evpn_print_dad_neigh_hash
,
2911 vty_json(vty
, json
);
2915 * Display MACs for a VNI (VTY command handler).
2917 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2918 vni_t vni
, bool use_json
, bool detail
)
2920 struct zebra_evpn
*zevpn
;
2922 struct mac_walk_ctx wctx
;
2923 json_object
*json
= NULL
;
2924 json_object
*json_mac
= NULL
;
2926 if (!is_evpn_enabled())
2928 zevpn
= zebra_evpn_lookup(vni
);
2931 vty_out(vty
, "{}\n");
2933 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2936 num_macs
= num_valid_macs(zevpn
);
2941 json
= json_object_new_object();
2942 json_mac
= json_object_new_object();
2945 memset(&wctx
, 0, sizeof(wctx
));
2948 wctx
.json
= json_mac
;
2952 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
2953 zevpn
->vni
, num_macs
);
2956 "Number of MACs (local and remote) known for this VNI: %u\n",
2959 "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
2960 vty_out(vty
, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC",
2961 "Type", "Flags", "Intf/Remote ES/VTEP", "VLAN",
2965 json_object_int_add(json
, "numMacs", num_macs
);
2968 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_mac_hash_detail
,
2971 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_mac_hash
,
2975 json_object_object_add(json
, "macs", json_mac
);
2976 vty_json(vty
, json
);
2981 * Display MACs for all VNIs (VTY command handler).
2983 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2984 bool print_dup
, bool use_json
)
2986 struct mac_walk_ctx wctx
;
2987 json_object
*json
= NULL
;
2989 if (!is_evpn_enabled()) {
2991 vty_out(vty
, "{}\n");
2995 json
= json_object_new_object();
2997 memset(&wctx
, 0, sizeof(wctx
));
3000 wctx
.print_dup
= print_dup
;
3001 hash_iterate(zvrf
->evpn_table
, zevpn_print_mac_hash_all_evpn
, &wctx
);
3004 vty_json(vty
, json
);
3008 * Display MACs in detail for all VNIs (VTY command handler).
3010 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
3011 struct zebra_vrf
*zvrf
,
3012 bool print_dup
, bool use_json
)
3014 struct mac_walk_ctx wctx
;
3015 json_object
*json
= NULL
;
3017 if (!is_evpn_enabled()) {
3019 vty_out(vty
, "{}\n");
3023 json
= json_object_new_object();
3025 memset(&wctx
, 0, sizeof(wctx
));
3028 wctx
.print_dup
= print_dup
;
3029 hash_iterate(zvrf
->evpn_table
, zevpn_print_mac_hash_all_evpn_detail
,
3033 vty_json(vty
, json
);
3037 * Display MACs for all VNIs (VTY command handler).
3039 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
3040 struct zebra_vrf
*zvrf
,
3041 struct in_addr vtep_ip
, bool use_json
)
3043 struct mac_walk_ctx wctx
;
3044 json_object
*json
= NULL
;
3046 if (!is_evpn_enabled())
3050 json
= json_object_new_object();
3052 memset(&wctx
, 0, sizeof(wctx
));
3054 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
3055 wctx
.r_vtep_ip
= vtep_ip
;
3057 hash_iterate(zvrf
->evpn_table
, zevpn_print_mac_hash_all_evpn
, &wctx
);
3060 vty_json(vty
, json
);
3064 * Display specific MAC for a VNI, if present (VTY command handler).
3066 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
3067 vni_t vni
, struct ethaddr
*macaddr
,
3070 struct zebra_evpn
*zevpn
;
3071 struct zebra_mac
*mac
;
3072 json_object
*json
= NULL
;
3074 if (!is_evpn_enabled())
3077 zevpn
= zebra_evpn_lookup(vni
);
3080 vty_out(vty
, "{}\n");
3082 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
3085 mac
= zebra_evpn_mac_lookup(zevpn
, macaddr
);
3088 vty_out(vty
, "{}\n");
3091 "%% Requested MAC does not exist in VNI %u\n",
3097 json
= json_object_new_object();
3099 zebra_evpn_print_mac(mac
, vty
, json
);
3101 vty_json(vty
, json
);
3104 /* Print Duplicate MACs per VNI */
3105 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
3106 struct zebra_vrf
*zvrf
,
3107 vni_t vni
, bool use_json
)
3109 struct zebra_evpn
*zevpn
;
3110 struct mac_walk_ctx wctx
;
3112 json_object
*json
= NULL
;
3113 json_object
*json_mac
= NULL
;
3115 if (!is_evpn_enabled())
3118 zevpn
= zebra_evpn_lookup(vni
);
3120 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
3124 num_macs
= num_valid_macs(zevpn
);
3128 num_macs
= num_dup_detected_macs(zevpn
);
3133 json
= json_object_new_object();
3134 json_mac
= json_object_new_object();
3137 memset(&wctx
, 0, sizeof(wctx
));
3140 wctx
.json
= json_mac
;
3144 "Number of MACs (local and remote) known for this VNI: %u\n",
3146 vty_out(vty
, "%-17s %-6s %-5s %-30s %-5s\n", "MAC", "Type",
3147 "Flags", "Intf/Remote ES/VTEP", "VLAN");
3149 json_object_int_add(json
, "numMacs", num_macs
);
3151 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_dad_mac_hash
, &wctx
);
3154 json_object_object_add(json
, "macs", json_mac
);
3155 vty_json(vty
, json
);
3160 int zebra_vxlan_clear_dup_detect_vni_mac(struct zebra_vrf
*zvrf
, vni_t vni
,
3161 struct ethaddr
*macaddr
, char *errmsg
,
3164 struct zebra_evpn
*zevpn
;
3165 struct zebra_mac
*mac
;
3166 struct listnode
*node
= NULL
;
3167 struct zebra_neigh
*nbr
= NULL
;
3169 if (!is_evpn_enabled())
3172 zevpn
= zebra_evpn_lookup(vni
);
3174 snprintfrr(errmsg
, errmsg_len
, "VNI %u does not exist", vni
);
3178 mac
= zebra_evpn_mac_lookup(zevpn
, macaddr
);
3180 snprintf(errmsg
, errmsg_len
,
3181 "Requested MAC does not exist in VNI %u\n", vni
);
3185 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
3186 snprintfrr(errmsg
, errmsg_len
,
3187 "Requested MAC is not duplicate detected\n");
3191 /* Remove all IPs as duplicate associcated with this MAC */
3192 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
3193 /* For local neigh mark inactive so MACIP update is generated
3194 * to BGP. This is a scenario where MAC update received
3195 * and detected as duplicate which marked neigh as duplicate.
3196 * Later local neigh update did not get a chance to relay
3197 * to BGP. Similarly remote macip update, neigh needs to be
3198 * installed locally.
3200 if (zvrf
->dad_freeze
&&
3201 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
3202 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
3203 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
3204 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
3205 zebra_evpn_rem_neigh_install(
3206 zevpn
, nbr
, false /*was_static*/);
3209 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
3211 nbr
->detect_start_time
.tv_sec
= 0;
3212 nbr
->dad_dup_detect_time
= 0;
3215 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
3217 mac
->detect_start_time
.tv_sec
= 0;
3218 mac
->detect_start_time
.tv_usec
= 0;
3219 mac
->dad_dup_detect_time
= 0;
3220 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3222 /* warn-only action return */
3223 if (!zvrf
->dad_freeze
)
3226 /* Local: Notify Peer VTEPs, Remote: Install the entry */
3227 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
3229 if (zebra_evpn_mac_send_add_to_client(zevpn
->vni
, &mac
->macaddr
,
3230 mac
->flags
, mac
->loc_seq
,
3234 /* Process all neighbors associated with this MAC. */
3235 zebra_evpn_process_neigh_on_local_mac_change(zevpn
, mac
, 0,
3238 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
3239 zebra_evpn_process_neigh_on_remote_mac_add(zevpn
, mac
);
3241 /* Install the entry. */
3242 zebra_evpn_rem_mac_install(zevpn
, mac
, false /* was_static */);
3248 int zebra_vxlan_clear_dup_detect_vni_ip(struct zebra_vrf
*zvrf
, vni_t vni
,
3249 struct ipaddr
*ip
, char *errmsg
,
3252 struct zebra_evpn
*zevpn
;
3253 struct zebra_neigh
*nbr
;
3254 struct zebra_mac
*mac
;
3255 char buf
[INET6_ADDRSTRLEN
];
3256 char buf2
[ETHER_ADDR_STRLEN
];
3258 if (!is_evpn_enabled())
3261 zevpn
= zebra_evpn_lookup(vni
);
3263 snprintfrr(errmsg
, errmsg_len
, "VNI %u does not exist\n", vni
);
3267 nbr
= zebra_evpn_neigh_lookup(zevpn
, ip
);
3269 snprintfrr(errmsg
, errmsg_len
,
3270 "Requested host IP does not exist in VNI %u\n", vni
);
3274 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
3276 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
3277 snprintfrr(errmsg
, errmsg_len
,
3278 "Requested host IP %s is not duplicate detected\n",
3283 mac
= zebra_evpn_mac_lookup(zevpn
, &nbr
->emac
);
3285 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
3288 "Requested IP's associated MAC %s is still in duplicate state\n",
3289 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
3293 if (IS_ZEBRA_DEBUG_VXLAN
)
3294 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
3295 __func__
, buf
, nbr
->flags
, nbr
->loc_seq
);
3297 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
3299 nbr
->detect_start_time
.tv_sec
= 0;
3300 nbr
->detect_start_time
.tv_usec
= 0;
3301 nbr
->dad_dup_detect_time
= 0;
3302 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
3304 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3305 zebra_evpn_neigh_send_add_to_client(zevpn
->vni
, ip
, &nbr
->emac
,
3306 nbr
->mac
, nbr
->flags
,
3308 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3309 zebra_evpn_rem_neigh_install(zevpn
, nbr
, false /*was_static*/);
3315 static void zevpn_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3317 struct mac_walk_ctx
*wctx
= ctxt
;
3318 struct zebra_mac
*mac
;
3319 struct zebra_evpn
*zevpn
;
3320 struct listnode
*node
= NULL
;
3321 struct zebra_neigh
*nbr
= NULL
;
3323 mac
= (struct zebra_mac
*)bucket
->data
;
3327 zevpn
= wctx
->zevpn
;
3329 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
3332 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
3334 mac
->detect_start_time
.tv_sec
= 0;
3335 mac
->detect_start_time
.tv_usec
= 0;
3336 mac
->dad_dup_detect_time
= 0;
3337 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3339 /* Remove all IPs as duplicate associcated with this MAC */
3340 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
3341 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
3343 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
3345 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
3347 nbr
->detect_start_time
.tv_sec
= 0;
3348 nbr
->dad_dup_detect_time
= 0;
3351 /* Local: Notify Peer VTEPs, Remote: Install the entry */
3352 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
3354 if (zebra_evpn_mac_send_add_to_client(zevpn
->vni
, &mac
->macaddr
,
3355 mac
->flags
, mac
->loc_seq
,
3359 /* Process all neighbors associated with this MAC. */
3360 zebra_evpn_process_neigh_on_local_mac_change(zevpn
, mac
, 0,
3363 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
3364 zebra_evpn_process_neigh_on_remote_mac_add(zevpn
, mac
);
3366 /* Install the entry. */
3367 zebra_evpn_rem_mac_install(zevpn
, mac
, false /* was_static */);
3371 static void zevpn_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
3374 struct zebra_evpn
*zevpn
;
3375 struct zebra_vrf
*zvrf
;
3376 struct mac_walk_ctx m_wctx
;
3377 struct neigh_walk_ctx n_wctx
;
3379 zevpn
= (struct zebra_evpn
*)bucket
->data
;
3383 zvrf
= (struct zebra_vrf
*)args
[0];
3385 if (hashcount(zevpn
->neigh_table
)) {
3386 memset(&n_wctx
, 0, sizeof(n_wctx
));
3387 n_wctx
.zevpn
= zevpn
;
3389 hash_iterate(zevpn
->neigh_table
,
3390 zebra_evpn_clear_dup_neigh_hash
, &n_wctx
);
3393 if (num_valid_macs(zevpn
)) {
3394 memset(&m_wctx
, 0, sizeof(m_wctx
));
3395 m_wctx
.zevpn
= zevpn
;
3397 hash_iterate(zevpn
->mac_table
, zevpn_clear_dup_mac_hash
, &m_wctx
);
3402 int zebra_vxlan_clear_dup_detect_vni_all(struct zebra_vrf
*zvrf
)
3406 if (!is_evpn_enabled())
3411 hash_iterate(zvrf
->evpn_table
,
3412 (void (*)(struct hash_bucket
*, void *))
3413 zevpn_clear_dup_detect_hash_vni_all
, args
);
3418 int zebra_vxlan_clear_dup_detect_vni(struct zebra_vrf
*zvrf
, vni_t vni
)
3420 struct zebra_evpn
*zevpn
;
3421 struct mac_walk_ctx m_wctx
;
3422 struct neigh_walk_ctx n_wctx
;
3424 if (!is_evpn_enabled())
3427 zevpn
= zebra_evpn_lookup(vni
);
3429 zlog_warn("VNI %u does not exist", vni
);
3433 if (hashcount(zevpn
->neigh_table
)) {
3434 memset(&n_wctx
, 0, sizeof(n_wctx
));
3435 n_wctx
.zevpn
= zevpn
;
3437 hash_iterate(zevpn
->neigh_table
,
3438 zebra_evpn_clear_dup_neigh_hash
, &n_wctx
);
3441 if (num_valid_macs(zevpn
)) {
3442 memset(&m_wctx
, 0, sizeof(m_wctx
));
3443 m_wctx
.zevpn
= zevpn
;
3445 hash_iterate(zevpn
->mac_table
, zevpn_clear_dup_mac_hash
, &m_wctx
);
3452 * Display MACs for a VNI from specific VTEP (VTY command handler).
3454 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
3455 vni_t vni
, struct in_addr vtep_ip
,
3458 struct zebra_evpn
*zevpn
;
3460 struct mac_walk_ctx wctx
;
3461 json_object
*json
= NULL
;
3462 json_object
*json_mac
= NULL
;
3464 if (!is_evpn_enabled())
3466 zevpn
= zebra_evpn_lookup(vni
);
3469 vty_out(vty
, "{}\n");
3471 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
3474 num_macs
= num_valid_macs(zevpn
);
3479 json
= json_object_new_object();
3480 json_mac
= json_object_new_object();
3483 memset(&wctx
, 0, sizeof(wctx
));
3486 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
3487 wctx
.r_vtep_ip
= vtep_ip
;
3488 wctx
.json
= json_mac
;
3489 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_mac_hash
, &wctx
);
3492 json_object_int_add(json
, "numMacs", wctx
.count
);
3494 json_object_object_add(json
, "macs", json_mac
);
3495 vty_json(vty
, json
);
3501 * Display VNI information (VTY command handler).
3503 * use_json flag indicates that output should be in JSON format.
3504 * json_array is non NULL when JSON output needs to be aggregated (by the
3505 * caller) and then printed, otherwise, JSON evpn vni info is printed
3508 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
3509 bool use_json
, json_object
*json_array
)
3511 json_object
*json
= NULL
;
3513 struct zebra_l3vni
*zl3vni
= NULL
;
3514 struct zebra_evpn
*zevpn
= NULL
;
3516 if (!is_evpn_enabled())
3520 json
= json_object_new_object();
3525 zl3vni
= zl3vni_lookup(vni
);
3527 zl3vni_print(zl3vni
, (void *)args
);
3529 zevpn
= zebra_evpn_lookup(vni
);
3531 zebra_evpn_print(zevpn
, (void *)args
);
3533 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
3538 * Each "json" object contains info about 1 VNI.
3539 * When "json_array" is non-null, we aggreggate the json output
3540 * into json_array and print it as a JSON array.
3543 json_object_array_add(json_array
, json
);
3545 vty_json(vty
, json
);
3549 /* Display all global details for EVPN */
3550 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
3555 json_object
*json
= NULL
;
3556 struct zebra_vrf
*zvrf
= NULL
;
3558 if (!is_evpn_enabled())
3561 zvrf
= zebra_vrf_get_evpn();
3563 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
3564 num_l2vnis
= hashcount(zvrf
->evpn_table
);
3565 num_vnis
= num_l2vnis
+ num_l3vnis
;
3568 json
= json_object_new_object();
3569 json_object_string_add(json
, "advertiseGatewayMacip",
3570 zvrf
->advertise_gw_macip
? "Yes" : "No");
3571 json_object_string_add(json
, "advertiseSviMacip",
3572 zvrf
->advertise_svi_macip
? "Yes"
3574 json_object_string_add(json
, "advertiseSviMac",
3575 zebra_evpn_mh_do_adv_svi_mac() ? "Yes"
3577 json_object_int_add(json
, "numVnis", num_vnis
);
3578 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3579 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3580 if (zebra_evpn_do_dup_addr_detect(zvrf
))
3581 json_object_boolean_true_add(json
,
3582 "isDuplicateAddrDetection");
3584 json_object_boolean_false_add(json
,
3585 "isDuplicateAddrDetection");
3586 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
3587 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
3588 json_object_int_add(json
, "detectionFreezeTime",
3589 zvrf
->dad_freeze_time
);
3590 zebra_evpn_mh_json(json
);
3592 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
3593 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
3594 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
3595 zvrf
->advertise_gw_macip
? "Yes" : "No");
3596 vty_out(vty
, "Advertise svi mac-ip: %s\n",
3597 zvrf
->advertise_svi_macip
? "Yes" : "No");
3598 vty_out(vty
, "Advertise svi mac: %s\n",
3599 zebra_evpn_mh_do_adv_svi_mac() ? "Yes" : "No");
3600 vty_out(vty
, "Duplicate address detection: %s\n",
3601 zebra_evpn_do_dup_addr_detect(zvrf
) ? "Enable"
3603 vty_out(vty
, " Detection max-moves %u, time %d\n",
3604 zvrf
->dad_max_moves
, zvrf
->dad_time
);
3605 if (zvrf
->dad_freeze
) {
3606 if (zvrf
->dad_freeze_time
)
3607 vty_out(vty
, " Detection freeze %u\n",
3608 zvrf
->dad_freeze_time
);
3610 vty_out(vty
, " Detection freeze %s\n",
3613 zebra_evpn_mh_print(vty
);
3617 vty_json(vty
, json
);
3621 * Display VNI hash table (VTY command handler).
3623 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
3626 json_object
*json
= NULL
;
3629 if (!is_evpn_enabled())
3633 json
= json_object_new_object();
3635 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
3636 "Type", "VxLAN IF", "# MACs", "# ARPs",
3637 "# Remote VTEPs", "Tenant VRF");
3642 /* Display all L2-VNIs */
3645 (void (*)(struct hash_bucket
*, void *))zebra_evpn_print_hash
,
3648 /* Display all L3-VNIs */
3649 hash_iterate(zrouter
.l3vni_table
,
3650 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
3654 vty_json(vty
, json
);
3657 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
3661 uint32_t max_moves
= 0;
3662 uint32_t freeze_time
= 0;
3663 bool dup_addr_detect
= false;
3664 bool freeze
= false;
3665 bool old_addr_detect
;
3668 STREAM_GETL(s
, dup_addr_detect
);
3669 STREAM_GETL(s
, time
);
3670 STREAM_GETL(s
, max_moves
);
3671 STREAM_GETL(s
, freeze
);
3672 STREAM_GETL(s
, freeze_time
);
3674 old_addr_detect
= zebra_evpn_do_dup_addr_detect(zvrf
);
3675 zvrf
->dup_addr_detect
= dup_addr_detect
;
3676 dup_addr_detect
= zebra_evpn_do_dup_addr_detect(zvrf
);
3678 /* DAD previous state was enabled, and new state is disable,
3679 * clear all duplicate detected addresses.
3681 if (old_addr_detect
&& !dup_addr_detect
)
3682 zebra_vxlan_clear_dup_detect_vni_all(zvrf
);
3684 zvrf
->dad_time
= time
;
3685 zvrf
->dad_max_moves
= max_moves
;
3686 zvrf
->dad_freeze
= freeze
;
3687 zvrf
->dad_freeze_time
= freeze_time
;
3689 if (IS_ZEBRA_DEBUG_VXLAN
)
3691 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
3692 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
3693 dup_addr_detect
? "enable" : "disable",
3694 zvrf
->dad_max_moves
, zvrf
->dad_time
,
3695 zvrf
->dad_freeze
? "enable" : "disable",
3696 zvrf
->dad_freeze_time
);
3703 * Display VNI hash table in detail(VTY command handler).
3705 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
3708 json_object
*json_array
= NULL
;
3709 struct zebra_ns
*zns
= NULL
;
3710 struct zebra_evpn_show zes
;
3712 if (!is_evpn_enabled())
3715 zns
= zebra_ns_lookup(NS_DEFAULT
);
3720 json_array
= json_object_new_array();
3723 zes
.json
= json_array
;
3725 zes
.use_json
= use_json
;
3727 /* Display all L2-VNIs */
3728 hash_iterate(zvrf
->evpn_table
,
3729 (void (*)(struct hash_bucket
*,
3730 void *))zebra_evpn_print_hash_detail
,
3733 /* Display all L3-VNIs */
3734 hash_iterate(zrouter
.l3vni_table
,
3735 (void (*)(struct hash_bucket
*,
3736 void *))zl3vni_print_hash_detail
,
3740 vty_json(vty
, json_array
);
3744 * Handle neighbor delete notification from the kernel (on a VLAN device
3745 * / L3 interface). This may result in either the neighbor getting deleted
3746 * from our database or being re-added to the kernel (if it is a valid
3749 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
3750 struct interface
*link_if
,
3753 struct zebra_evpn
*zevpn
= NULL
;
3754 struct zebra_l3vni
*zl3vni
= NULL
;
3756 /* check if this is a remote neigh entry corresponding to remote
3759 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
3761 return zl3vni_local_nh_del(zl3vni
, ip
);
3763 /* We are only interested in neighbors on an SVI that resides on top
3764 * of a VxLAN bridge.
3766 zevpn
= zebra_evpn_from_svi(ifp
, link_if
);
3768 if (IS_ZEBRA_DEBUG_VXLAN
)
3770 "%s: Del neighbor %pIA EVPN is not present for interface %s",
3771 __func__
, ip
, ifp
->name
);
3775 if (!zevpn
->vxlan_if
) {
3777 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
3782 if (IS_ZEBRA_DEBUG_VXLAN
)
3783 zlog_debug("Del neighbor %pIA intf %s(%u) -> L2-VNI %u",
3784 ip
, ifp
->name
, ifp
->ifindex
, zevpn
->vni
);
3786 return zebra_evpn_neigh_del_ip(zevpn
, ip
);
3790 * Handle neighbor add or update notification from the kernel (on a VLAN
3791 * device / L3 interface). This is typically for a local neighbor but can
3792 * also be for a remote neighbor (e.g., ageout notification). It could
3793 * also be a "move" scenario.
3795 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
3796 struct interface
*link_if
,
3798 struct ethaddr
*macaddr
,
3802 bool local_inactive
, bool dp_static
)
3804 struct zebra_evpn
*zevpn
= NULL
;
3805 struct zebra_l3vni
*zl3vni
= NULL
;
3807 /* check if this is a remote neigh entry corresponding to remote
3810 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
3812 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
3814 /* We are only interested in neighbors on an SVI that resides on top
3815 * of a VxLAN bridge.
3817 zevpn
= zebra_evpn_from_svi(ifp
, link_if
);
3821 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
3823 "Add/Update neighbor %pIA MAC %pEA intf %s(%u) state 0x%x %s%s%s%s-> L2-VNI %u",
3824 ip
, macaddr
, ifp
->name
,
3825 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
3826 is_router
? "router " : "",
3827 local_inactive
? "local_inactive " : "",
3828 dp_static
? "peer_sync " : "", zevpn
->vni
);
3830 /* Is this about a local neighbor or a remote one? */
3832 return zebra_evpn_local_neigh_update(zevpn
, ifp
, ip
, macaddr
,
3833 is_router
, local_inactive
,
3836 return zebra_evpn_remote_neigh_update(zevpn
, ifp
, ip
, macaddr
, state
);
3840 zebra_vxlan_remote_macip_helper(bool add
, struct stream
*s
, vni_t
*vni
,
3841 struct ethaddr
*macaddr
, uint16_t *ipa_len
,
3842 struct ipaddr
*ip
, struct in_addr
*vtep_ip
,
3843 uint8_t *flags
, uint32_t *seq
, esi_t
*esi
)
3848 * Obtain each remote MACIP and process.
3849 * Message contains VNI, followed by MAC followed by IP (if any)
3850 * followed by remote VTEP IP.
3852 memset(ip
, 0, sizeof(*ip
));
3853 STREAM_GETL(s
, *vni
);
3854 STREAM_GET(macaddr
->octet
, s
, ETH_ALEN
);
3855 STREAM_GETW(s
, *ipa_len
);
3858 if (*ipa_len
== IPV4_MAX_BYTELEN
)
3859 ip
->ipa_type
= IPADDR_V4
;
3860 else if (*ipa_len
== IPV6_MAX_BYTELEN
)
3861 ip
->ipa_type
= IPADDR_V6
;
3863 if (IS_ZEBRA_DEBUG_VXLAN
)
3865 "ipa_len *must* be %d or %d bytes in length not %d",
3866 IPV4_MAX_BYTELEN
, IPV6_MAX_BYTELEN
,
3868 goto stream_failure
;
3871 STREAM_GET(&ip
->ip
.addr
, s
, *ipa_len
);
3873 l
+= 4 + ETH_ALEN
+ 4 + *ipa_len
;
3874 STREAM_GET(&vtep_ip
->s_addr
, s
, IPV4_MAX_BYTELEN
);
3875 l
+= IPV4_MAX_BYTELEN
;
3878 STREAM_GETC(s
, *flags
);
3879 STREAM_GETL(s
, *seq
);
3881 STREAM_GET(esi
, s
, sizeof(esi_t
));
3892 * Handle message from client to delete a remote MACIP for a VNI.
3894 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
3898 struct ethaddr macaddr
;
3900 struct in_addr vtep_ip
;
3901 uint16_t l
= 0, ipa_len
;
3902 char buf1
[INET6_ADDRSTRLEN
];
3906 while (l
< hdr
->length
) {
3907 int res_length
= zebra_vxlan_remote_macip_helper(
3908 false, s
, &vni
, &macaddr
, &ipa_len
, &ip
, &vtep_ip
, NULL
,
3911 if (res_length
== -1)
3912 goto stream_failure
;
3915 if (IS_ZEBRA_DEBUG_VXLAN
)
3917 "Recv MACIP DEL VNI %u MAC %pEA%s%s Remote VTEP %pI4 from %s",
3919 ipa_len
? " IP " : "",
3921 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
3922 &vtep_ip
, zebra_route_string(client
->proto
));
3924 /* Enqueue to workqueue for processing */
3925 zebra_rib_queue_evpn_rem_macip_del(vni
, &macaddr
, &ip
, vtep_ip
);
3933 * Handle message from client to add a remote MACIP for a VNI. This
3934 * could be just the add of a MAC address or the add of a neighbor
3937 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
3941 struct ethaddr macaddr
;
3943 struct in_addr vtep_ip
;
3944 uint16_t l
= 0, ipa_len
;
3947 char buf1
[INET6_ADDRSTRLEN
];
3949 char esi_buf
[ESI_STR_LEN
];
3951 if (!EVPN_ENABLED(zvrf
)) {
3952 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
3958 while (l
< hdr
->length
) {
3960 int res_length
= zebra_vxlan_remote_macip_helper(
3961 true, s
, &vni
, &macaddr
, &ipa_len
, &ip
, &vtep_ip
,
3962 &flags
, &seq
, &esi
);
3964 if (res_length
== -1)
3965 goto stream_failure
;
3968 if (IS_ZEBRA_DEBUG_VXLAN
) {
3969 if (memcmp(&esi
, zero_esi
, sizeof(esi_t
)))
3970 esi_to_str(&esi
, esi_buf
, sizeof(esi_buf
));
3972 strlcpy(esi_buf
, "-", ESI_STR_LEN
);
3974 "Recv %sMACIP ADD VNI %u MAC %pEA%s%s flags 0x%x seq %u VTEP %pI4 ESI %s from %s",
3975 (flags
& ZEBRA_MACIP_TYPE_SYNC_PATH
) ?
3978 ipa_len
? " IP " : "",
3980 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
3981 flags
, seq
, &vtep_ip
, esi_buf
,
3982 zebra_route_string(client
->proto
));
3985 /* Enqueue to workqueue for processing */
3986 zebra_rib_queue_evpn_rem_macip_add(vni
, &macaddr
, &ip
, flags
,
3987 seq
, vtep_ip
, &esi
);
3995 * Handle remote vtep delete by kernel; re-add the vtep if we have it
3997 int zebra_vxlan_check_readd_vtep(struct interface
*ifp
, vni_t vni
,
3998 struct in_addr vtep_ip
)
4000 struct zebra_if
*zif
;
4001 struct zebra_vrf
*zvrf
= NULL
;
4002 struct zebra_evpn
*zevpn
= NULL
;
4003 struct zebra_vtep
*zvtep
= NULL
;
4004 struct zebra_vxlan_vni
*vnip
;
4009 /* If EVPN is not enabled, nothing to do. */
4010 if (!is_evpn_enabled())
4013 /* Locate VRF corresponding to interface. */
4014 zvrf
= ifp
->vrf
->info
;
4018 vnip
= zebra_vxlan_if_vni_find(zif
, vni
);
4022 /* Locate hash entry; it is expected to exist. */
4023 zevpn
= zebra_evpn_lookup(vni
);
4027 /* If the remote vtep entry doesn't exists nothing to do */
4028 zvtep
= zebra_evpn_vtep_find(zevpn
, &vtep_ip
);
4032 if (IS_ZEBRA_DEBUG_VXLAN
)
4034 "Del MAC for remote VTEP %pI4 intf %s(%u) VNI %u - readd",
4035 &vtep_ip
, ifp
->name
, ifp
->ifindex
, vni
);
4037 zebra_evpn_vtep_install(zevpn
, zvtep
);
4042 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
4043 * us, this must involve a multihoming scenario. Treat this as implicit delete
4044 * of any prior local MAC.
4046 static int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
4047 struct interface
*br_if
,
4048 struct ethaddr
*macaddr
,
4049 vlanid_t vid
, vni_t vni
)
4051 struct zebra_if
*zif
;
4052 struct zebra_evpn
*zevpn
;
4053 struct zebra_mac
*mac
;
4058 /* Check if EVPN is enabled. */
4059 if (!is_evpn_enabled())
4062 /* Locate hash entry; it is expected to exist. */
4063 zevpn
= zebra_evpn_lookup(vni
);
4067 /* If entry doesn't exist, nothing to do. */
4068 mac
= zebra_evpn_mac_lookup(zevpn
, macaddr
);
4072 /* Is it a local entry? */
4073 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
4076 if (IS_ZEBRA_DEBUG_VXLAN
)
4078 "Add/update remote MAC %pEA intf %s(%u) VNI %u flags 0x%x - del local",
4079 macaddr
, ifp
->name
, ifp
->ifindex
, vni
, mac
->flags
);
4081 /* Remove MAC from BGP. */
4082 zebra_evpn_mac_send_del_to_client(zevpn
->vni
, macaddr
, mac
->flags
,
4086 * If there are no neigh associated with the mac delete the mac
4087 * else mark it as AUTO for forward reference
4089 if (!listcount(mac
->neigh_list
)) {
4090 zebra_evpn_mac_del(zevpn
, mac
);
4092 zebra_evpn_mac_clear_fwd_info(mac
);
4093 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_ALL_LOCAL_FLAGS
);
4094 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
4095 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
4101 /* MAC notification from the dataplane with a network dest port -
4102 * 1. This can be a local MAC on a down ES (if fast-failover is not possible
4103 * 2. Or it can be a remote MAC
4105 int zebra_vxlan_dp_network_mac_add(struct interface
*ifp
,
4106 struct interface
*br_if
,
4107 struct ethaddr
*macaddr
, vlanid_t vid
,
4108 vni_t vni
, uint32_t nhg_id
, bool sticky
,
4111 struct zebra_evpn_es
*es
;
4112 struct interface
*acc_ifp
;
4114 /* If netlink message is with vid, it will have no nexthop.
4118 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
4119 zlog_debug("dpAdd MAC %pEA VID %u - ignore as no nhid",
4124 /* Get vxlan's vid for netlink message has no it. */
4125 vid
= ((struct zebra_if
*)ifp
->info
)->l2info
.vxl
.access_vlan
;
4127 /* if remote mac delete the local entry */
4128 if (!nhg_id
|| !zebra_evpn_nhg_is_local_es(nhg_id
, &es
)
4129 || !zebra_evpn_es_local_mac_via_network_port(es
)) {
4130 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
4131 zlog_debug("dpAdd remote MAC %pEA VID %u", macaddr
,
4133 return zebra_vxlan_check_del_local_mac(ifp
, br_if
, macaddr
, vid
,
4137 /* If local MAC on a down local ES translate the network-mac-add
4138 * to a local-active-mac-add
4140 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
4141 zlog_debug("dpAdd local-nw-MAC %pEA VID %u", macaddr
, vid
);
4142 acc_ifp
= es
->zif
->ifp
;
4143 return zebra_vxlan_local_mac_add_update(
4144 acc_ifp
, br_if
, macaddr
, vid
, sticky
,
4145 false /* local_inactive */, dp_static
);
4149 * Handle network MAC delete by kernel -
4150 * 1. readd the remote MAC if we have it
4151 * 2. local MAC with does ES may also need to be re-installed
4153 int zebra_vxlan_dp_network_mac_del(struct interface
*ifp
,
4154 struct interface
*br_if
,
4155 struct ethaddr
*macaddr
, vlanid_t vid
,
4158 struct zebra_if
*zif
= NULL
;
4159 struct zebra_evpn
*zevpn
= NULL
;
4160 struct zebra_l3vni
*zl3vni
= NULL
;
4161 struct zebra_mac
*mac
= NULL
;
4166 /* Check if EVPN is enabled. */
4167 if (!is_evpn_enabled())
4170 /* check if this is a remote RMAC and readd simillar to remote macs */
4171 zl3vni
= zl3vni_lookup(vni
);
4173 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
4175 /* Locate hash entry; it is expected to exist. */
4176 zevpn
= zebra_evpn_lookup(vni
);
4180 /* If entry doesn't exist, nothing to do. */
4181 mac
= zebra_evpn_mac_lookup(zevpn
, macaddr
);
4185 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
4186 /* If remote entry simply re-install */
4187 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
4189 "dpDel remote MAC %pEA intf %s(%u) VNI %u - readd",
4190 macaddr
, ifp
->name
, ifp
->ifindex
, vni
);
4191 zebra_evpn_rem_mac_install(zevpn
, mac
, false /* was_static */);
4192 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
) && mac
->es
4193 && zebra_evpn_es_local_mac_via_network_port(mac
->es
)) {
4194 /* If local entry via nw-port call local-del which will
4195 * re-install entry in the dataplane is needed
4197 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
4198 zlog_debug("dpDel local-nw-MAC %pEA VNI %u", macaddr
,
4201 zebra_evpn_del_local_mac(zevpn
, mac
, false);
4208 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
4210 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
4211 struct ethaddr
*macaddr
, vlanid_t vid
)
4213 struct zebra_evpn
*zevpn
;
4214 struct zebra_mac
*mac
;
4216 /* We are interested in MACs only on ports or (port, VLAN) that
4219 zevpn
= zebra_evpn_map_vlan(ifp
, br_if
, vid
);
4222 if (!zevpn
->vxlan_if
) {
4224 "VNI %u hash %p doesn't have intf upon local MAC DEL",
4229 /* If entry doesn't exist, nothing to do. */
4230 mac
= zebra_evpn_mac_lookup(zevpn
, macaddr
);
4234 /* Is it a local entry? */
4235 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
4238 return zebra_evpn_del_local_mac(zevpn
, mac
, false);
4242 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
4244 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
4245 struct interface
*br_if
,
4246 struct ethaddr
*macaddr
, vlanid_t vid
,
4247 bool sticky
, bool local_inactive
,
4250 struct zebra_evpn
*zevpn
;
4251 struct zebra_vrf
*zvrf
;
4255 /* We are interested in MACs only on ports or (port, VLAN) that
4258 zevpn
= zebra_evpn_map_vlan(ifp
, br_if
, vid
);
4260 if (IS_ZEBRA_DEBUG_VXLAN
)
4262 " Add/Update %sMAC %pEA intf %s(%u) VID %u, could not find EVPN",
4263 sticky
? "sticky " : "", macaddr
,
4264 ifp
->name
, ifp
->ifindex
, vid
);
4268 if (!zevpn
->vxlan_if
) {
4269 if (IS_ZEBRA_DEBUG_VXLAN
)
4271 " VNI %u hash %p doesn't have intf upon local MAC ADD",
4276 zvrf
= zebra_vrf_get_evpn();
4277 return zebra_evpn_add_update_local_mac(zvrf
, zevpn
, ifp
, macaddr
, vid
,
4278 sticky
, local_inactive
,
4283 * Handle message from client to delete a remote VTEP for an EVPN.
4285 void zebra_vxlan_remote_vtep_del_zapi(ZAPI_HANDLER_ARGS
)
4288 unsigned short l
= 0;
4290 struct in_addr vtep_ip
;
4292 if (!is_evpn_enabled()) {
4294 "%s: EVPN is not enabled yet we have received a VTEP DEL msg",
4299 if (!EVPN_ENABLED(zvrf
)) {
4300 zlog_debug("Recv VTEP DEL zapi for non-EVPN VRF %u",
4307 while (l
< hdr
->length
) {
4308 int flood_control
__attribute__((unused
));
4310 /* Obtain each remote VTEP and process. */
4311 STREAM_GETL(s
, vni
);
4313 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
4314 l
+= IPV4_MAX_BYTELEN
;
4316 /* Flood control is intentionally ignored right now */
4317 STREAM_GETL(s
, flood_control
);
4320 if (IS_ZEBRA_DEBUG_VXLAN
)
4321 zlog_debug("Recv VTEP DEL %pI4 VNI %u from %s",
4323 zebra_route_string(client
->proto
));
4325 /* Enqueue for processing */
4326 zebra_rib_queue_evpn_rem_vtep_del(zvrf_id(zvrf
), vni
, vtep_ip
);
4334 * Handle message from client to delete a remote VTEP for an EVPN.
4336 void zebra_vxlan_remote_vtep_del(vrf_id_t vrf_id
, vni_t vni
,
4337 struct in_addr vtep_ip
)
4339 struct zebra_evpn
*zevpn
;
4340 struct zebra_vtep
*zvtep
;
4341 struct interface
*ifp
;
4342 struct zebra_if
*zif
;
4343 struct zebra_vrf
*zvrf
;
4345 if (!is_evpn_enabled()) {
4346 zlog_debug("%s: Can't process vtep del: EVPN is not enabled",
4351 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4355 if (!EVPN_ENABLED(zvrf
)) {
4356 zlog_debug("Can't process VTEP DEL for non-EVPN VRF %u",
4361 /* Locate VNI hash entry - expected to exist. */
4362 zevpn
= zebra_evpn_lookup(vni
);
4364 if (IS_ZEBRA_DEBUG_VXLAN
)
4366 "Failed to locate VNI hash for remote VTEP DEL, VNI %u",
4371 ifp
= zevpn
->vxlan_if
;
4374 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
4380 /* If down or not mapped to a bridge, we're done. */
4381 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
4384 /* If the remote VTEP does not exist, there's nothing more to
4386 * Otherwise, uninstall any remote MACs pointing to this VTEP
4387 * and then, the VTEP entry itself and remove it.
4389 zvtep
= zebra_evpn_vtep_find(zevpn
, &vtep_ip
);
4393 zebra_evpn_vtep_uninstall(zevpn
, &vtep_ip
);
4394 zebra_evpn_vtep_del(zevpn
, zvtep
);
4398 * Handle message from client to add a remote VTEP for an EVPN.
4400 void zebra_vxlan_remote_vtep_add(vrf_id_t vrf_id
, vni_t vni
,
4401 struct in_addr vtep_ip
, int flood_control
)
4403 struct zebra_evpn
*zevpn
;
4404 struct interface
*ifp
;
4405 struct zebra_if
*zif
;
4406 struct zebra_vtep
*zvtep
;
4407 struct zebra_vrf
*zvrf
;
4409 if (!is_evpn_enabled()) {
4410 zlog_debug("%s: EVPN not enabled: can't process a VTEP ADD",
4415 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4419 if (!EVPN_ENABLED(zvrf
)) {
4420 zlog_debug("Can't process VTEP ADD for non-EVPN VRF %u",
4425 /* Locate VNI hash entry - expected to exist. */
4426 zevpn
= zebra_evpn_lookup(vni
);
4429 EC_ZEBRA_VTEP_ADD_FAILED
,
4430 "Failed to locate EVPN hash upon remote VTEP ADD, VNI %u",
4435 ifp
= zevpn
->vxlan_if
;
4438 EC_ZEBRA_VTEP_ADD_FAILED
,
4439 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
4446 /* If down or not mapped to a bridge, we're done. */
4447 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
4450 zvtep
= zebra_evpn_vtep_find(zevpn
, &vtep_ip
);
4452 /* If the remote VTEP already exists check if
4453 * the flood mode has changed
4455 if (zvtep
->flood_control
!= flood_control
) {
4456 if (zvtep
->flood_control
== VXLAN_FLOOD_DISABLED
)
4457 /* old mode was head-end-replication but
4458 * is no longer; get rid of the HER fdb
4459 * entry installed before
4461 zebra_evpn_vtep_uninstall(zevpn
, &vtep_ip
);
4462 zvtep
->flood_control
= flood_control
;
4463 zebra_evpn_vtep_install(zevpn
, zvtep
);
4466 zvtep
= zebra_evpn_vtep_add(zevpn
, &vtep_ip
, flood_control
);
4468 zebra_evpn_vtep_install(zevpn
, zvtep
);
4470 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
4471 "Failed to add remote VTEP, VNI %u zevpn %p",
4477 * Handle message from client to add a remote VTEP for an EVPN.
4479 void zebra_vxlan_remote_vtep_add_zapi(ZAPI_HANDLER_ARGS
)
4482 unsigned short l
= 0;
4484 struct in_addr vtep_ip
;
4487 if (!is_evpn_enabled()) {
4489 "%s: EVPN not enabled yet we received a VTEP ADD zapi msg",
4494 if (!EVPN_ENABLED(zvrf
)) {
4495 zlog_debug("Recv VTEP ADD zapi for non-EVPN VRF %u",
4502 while (l
< hdr
->length
) {
4503 /* Obtain each remote VTEP and process. */
4504 STREAM_GETL(s
, vni
);
4506 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
4507 STREAM_GETL(s
, flood_control
);
4508 l
+= IPV4_MAX_BYTELEN
+ 4;
4510 if (IS_ZEBRA_DEBUG_VXLAN
)
4511 zlog_debug("Recv VTEP ADD %pI4 VNI %u flood %d from %s",
4512 &vtep_ip
, vni
, flood_control
,
4513 zebra_route_string(client
->proto
));
4515 /* Enqueue for processing */
4516 zebra_rib_queue_evpn_rem_vtep_add(zvrf_id(zvrf
), vni
, vtep_ip
,
4525 * Add/Del gateway macip to evpn
4527 * 1. SVI interface on a vlan aware bridge
4528 * 2. SVI interface on a vlan unaware bridge
4529 * 3. vrr interface (MACVLAN) associated to a SVI
4530 * We advertise macip routes for an interface if it is associated to VxLan vlan
4532 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, const struct prefix
*p
,
4536 struct ethaddr macaddr
;
4537 struct zebra_evpn
*zevpn
= NULL
;
4539 memset(&ip
, 0, sizeof(ip
));
4540 memset(&macaddr
, 0, sizeof(macaddr
));
4542 /* Check if EVPN is enabled. */
4543 if (!is_evpn_enabled())
4546 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
4547 struct interface
*svi_if
=
4548 NULL
; /* SVI corresponding to the MACVLAN */
4549 struct zebra_if
*ifp_zif
=
4550 NULL
; /* Zebra daemon specific info for MACVLAN */
4551 struct zebra_if
*svi_if_zif
=
4552 NULL
; /* Zebra daemon specific info for SVI*/
4554 ifp_zif
= ifp
->info
;
4559 * for a MACVLAN interface the link represents the svi_if
4561 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
4562 ifp_zif
->link_ifindex
);
4564 zlog_debug("MACVLAN %s(%u) without link information",
4565 ifp
->name
, ifp
->ifindex
);
4569 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
4571 * If it is a vlan aware bridge then the link gives the
4572 * bridge information
4574 struct interface
*svi_if_link
= NULL
;
4576 svi_if_zif
= svi_if
->info
;
4578 svi_if_link
= if_lookup_by_index_per_ns(
4579 zebra_ns_lookup(NS_DEFAULT
),
4580 svi_if_zif
->link_ifindex
);
4581 zevpn
= zebra_evpn_from_svi(svi_if
,
4584 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
4586 * If it is a vlan unaware bridge then svi is the bridge
4589 zevpn
= zebra_evpn_from_svi(svi_if
, svi_if
);
4591 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
4592 struct zebra_if
*svi_if_zif
=
4593 NULL
; /* Zebra daemon specific info for SVI */
4594 struct interface
*svi_if_link
=
4595 NULL
; /* link info for the SVI = bridge info */
4597 svi_if_zif
= ifp
->info
;
4599 svi_if_link
= if_lookup_by_index_per_ns(
4600 zebra_ns_lookup(NS_DEFAULT
),
4601 svi_if_zif
->link_ifindex
);
4603 zevpn
= zebra_evpn_from_svi(ifp
, svi_if_link
);
4605 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
4606 zevpn
= zebra_evpn_from_svi(ifp
, ifp
);
4612 if (!zevpn
->vxlan_if
) {
4613 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
4618 /* VRR IP is advertised only if gw-macip-adv-enabled */
4619 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
4620 if (!advertise_gw_macip_enabled(zevpn
))
4623 /* SVI IP is advertised if gw or svi macip-adv-enabled */
4624 if (!advertise_svi_macip_enabled(zevpn
)
4625 && !advertise_gw_macip_enabled(zevpn
))
4629 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
4631 if (p
->family
== AF_INET
) {
4632 ip
.ipa_type
= IPADDR_V4
;
4633 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
4634 sizeof(struct in_addr
));
4635 } else if (p
->family
== AF_INET6
) {
4636 ip
.ipa_type
= IPADDR_V6
;
4637 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
4638 sizeof(struct in6_addr
));
4643 zebra_evpn_gw_macip_add(ifp
, zevpn
, &macaddr
, &ip
);
4645 zebra_evpn_gw_macip_del(ifp
, zevpn
, &ip
);
4651 * Handle SVI interface going down.
4652 * SVI can be associated to either L3-VNI or L2-VNI.
4653 * For L2-VNI: At this point, this is a NOP since
4654 * the kernel deletes the neighbor entries on this SVI (if any).
4655 * We only need to update the vrf corresponding to zevpn.
4656 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
4659 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
4661 struct zebra_l3vni
*zl3vni
= NULL
;
4663 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4666 /* process l3-vni down */
4667 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4669 /* remove association with svi-if */
4670 zl3vni
->svi_if
= NULL
;
4672 struct zebra_evpn
*zevpn
= NULL
;
4674 /* Unlink the SVI from the access VLAN */
4675 zebra_evpn_acc_bd_svi_set(ifp
->info
, link_if
->info
, false);
4677 /* since we dont have svi corresponding to zevpn, we associate it
4678 * to default vrf. Note: the corresponding neigh entries on the
4679 * SVI would have already been deleted */
4680 zevpn
= zebra_evpn_from_svi(ifp
, link_if
);
4683 /* remove from l3-vni list */
4684 zl3vni
= zl3vni_from_vrf(zevpn
->vrf_id
);
4686 listnode_delete(zl3vni
->l2vnis
, zevpn
);
4688 zevpn
->svi_if
= NULL
;
4689 zevpn
->vrf_id
= VRF_DEFAULT
;
4691 /* update the tenant vrf in BGP */
4692 if (if_is_operative(zevpn
->vxlan_if
))
4693 zebra_evpn_send_add_to_client(zevpn
);
4700 * Handle SVI interface coming up.
4701 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
4703 * For L2-VNI: we need to install any remote neighbors entried (used for
4705 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
4707 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
4709 struct zebra_evpn
*zevpn
= NULL
;
4710 struct zebra_l3vni
*zl3vni
= NULL
;
4712 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4715 /* associate with svi */
4716 zl3vni
->svi_if
= ifp
;
4718 /* process oper-up */
4719 if (is_l3vni_oper_up(zl3vni
))
4720 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4723 /* process SVI up for l2-vni */
4724 struct neigh_walk_ctx n_wctx
;
4726 zevpn
= zebra_evpn_from_svi(ifp
, link_if
);
4730 if (!zevpn
->vxlan_if
) {
4732 "VNI %u hash %p doesn't have intf upon SVI up",
4737 if (IS_ZEBRA_DEBUG_VXLAN
)
4739 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
4740 ifp
->name
, ifp
->ifindex
, zevpn
->vni
,
4743 /* update the vrf information for l2-vni and inform bgp */
4744 zevpn
->svi_if
= ifp
;
4745 zevpn
->vrf_id
= ifp
->vrf
->vrf_id
;
4747 zl3vni
= zl3vni_from_vrf(zevpn
->vrf_id
);
4749 listnode_add_sort_nodup(zl3vni
->l2vnis
, zevpn
);
4751 if (if_is_operative(zevpn
->vxlan_if
))
4752 zebra_evpn_send_add_to_client(zevpn
);
4754 /* Install any remote neighbors for this VNI. */
4755 memset(&n_wctx
, 0, sizeof(n_wctx
));
4756 n_wctx
.zevpn
= zevpn
;
4757 hash_iterate(zevpn
->neigh_table
, zebra_evpn_install_neigh_hash
,
4760 /* Link the SVI from the access VLAN */
4761 zebra_evpn_acc_bd_svi_set(ifp
->info
, link_if
->info
, true);
4763 /* Update MACIP routes created by advertise-svi-ip */
4764 if (advertise_svi_macip_enabled(zevpn
)) {
4765 zebra_evpn_del_macip_for_intf(ifp
, zevpn
);
4766 zebra_evpn_add_macip_for_intf(ifp
, zevpn
);
4774 * Handle MAC-VLAN interface going down.
4775 * L3VNI: When MAC-VLAN interface goes down,
4776 * find its associated SVI and update type2/type-5 routes
4779 void zebra_vxlan_macvlan_down(struct interface
*ifp
)
4781 struct zebra_l3vni
*zl3vni
= NULL
;
4782 struct zebra_if
*zif
, *link_zif
;
4783 struct interface
*link_ifp
, *link_if
;
4787 link_ifp
= zif
->link
;
4789 if (IS_ZEBRA_DEBUG_VXLAN
)
4791 "macvlan parent link is not found. Parent index %d ifp %s",
4793 ifindex2ifname(zif
->link_ifindex
,
4797 link_zif
= link_ifp
->info
;
4800 link_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
4801 link_zif
->link_ifindex
);
4803 zl3vni
= zl3vni_from_svi(link_ifp
, link_if
);
4805 zl3vni
->mac_vlan_if
= NULL
;
4806 if (is_l3vni_oper_up(zl3vni
))
4807 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4812 * Handle MAC-VLAN interface going up.
4813 * L3VNI: When MAC-VLAN interface comes up,
4814 * find its associated SVI and update type-2 routes
4815 * with MAC-VLAN's MAC as RMAC and for type-5 routes
4816 * use SVI's MAC as RMAC.
4818 void zebra_vxlan_macvlan_up(struct interface
*ifp
)
4820 struct zebra_l3vni
*zl3vni
= NULL
;
4821 struct zebra_if
*zif
, *link_zif
;
4822 struct interface
*link_ifp
, *link_if
;
4826 link_ifp
= zif
->link
;
4827 link_zif
= link_ifp
->info
;
4830 link_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
4831 link_zif
->link_ifindex
);
4832 zl3vni
= zl3vni_from_svi(link_ifp
, link_if
);
4834 /* associate with macvlan (VRR) interface */
4835 zl3vni
->mac_vlan_if
= ifp
;
4837 /* process oper-up */
4838 if (is_l3vni_oper_up(zl3vni
))
4839 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4843 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
4844 char *err
, int err_str_sz
, int filter
,
4847 struct zebra_l3vni
*zl3vni
= NULL
;
4848 struct zebra_vrf
*zvrf_evpn
= NULL
;
4850 zvrf_evpn
= zebra_vrf_get_evpn();
4852 if (IS_ZEBRA_DEBUG_VXLAN
)
4853 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
4854 add
? "ADD" : "DEL");
4857 /* check if the vni is already present under zvrf */
4859 snprintf(err
, err_str_sz
,
4860 "VNI is already configured under the vrf");
4864 /* check if this VNI is already present in the system */
4865 zl3vni
= zl3vni_lookup(vni
);
4867 snprintf(err
, err_str_sz
,
4868 "VNI is already configured as L3-VNI");
4872 /* Remove L2VNI if present */
4873 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
4875 /* add the L3-VNI to the global table */
4876 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
4878 /* associate the vrf with vni */
4881 /* set the filter in l3vni to denote if we are using l3vni only
4885 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
4887 /* associate with vxlan-intf;
4888 * we need to associate with the vxlan-intf first
4890 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
4892 /* associate with corresponding SVI interface, we can associate
4893 * with svi-if only after vxlan interface association is
4896 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4898 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
4900 if (IS_ZEBRA_DEBUG_VXLAN
)
4902 "%s: l3vni %u svi_if %s mac_vlan_if %s",
4904 zl3vni
->svi_if
? zl3vni
->svi_if
->name
: "NIL",
4905 zl3vni
->mac_vlan_if
? zl3vni
->mac_vlan_if
->name
4908 /* formulate l2vni list */
4909 hash_iterate(zvrf_evpn
->evpn_table
, zevpn_add_to_l3vni_list
,
4912 if (is_l3vni_oper_up(zl3vni
))
4913 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4916 zl3vni
= zl3vni_lookup(vni
);
4918 snprintf(err
, err_str_sz
, "VNI doesn't exist");
4922 if (zvrf
->l3vni
!= vni
) {
4923 snprintf(err
, err_str_sz
,
4924 "VNI %d doesn't exist in VRF: %s",
4925 vni
, zvrf
->vrf
->name
);
4929 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
4930 snprintf(err
, ERR_STR_SZ
,
4931 "prefix-routes-only is not set for the vni");
4935 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4937 /* delete and uninstall all rmacs */
4938 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
4941 /* delete and uninstall all next-hops */
4942 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
4948 /* Add L2VNI for this VNI */
4949 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
4954 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
4956 struct zebra_l3vni
*zl3vni
= NULL
;
4959 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4963 zl3vni
->vrf_id
= zvrf_id(zvrf
);
4964 if (is_l3vni_oper_up(zl3vni
))
4965 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4969 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
4971 struct zebra_l3vni
*zl3vni
= NULL
;
4974 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4978 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4980 /* delete and uninstall all rmacs */
4981 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
, zl3vni
);
4982 /* delete and uninstall all next-hops */
4983 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
, zl3vni
);
4985 zl3vni
->vrf_id
= VRF_UNKNOWN
;
4990 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
4992 struct zebra_l3vni
*zl3vni
= NULL
;
4996 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5002 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
5008 * Handle message from client to specify the flooding mechanism for
5009 * BUM packets. The default is to do head-end (ingress) replication
5010 * and the other supported option is to disable it. This applies to
5011 * all BUM traffic and disabling it applies to both the transmit and
5012 * receive direction.
5014 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
5017 enum vxlan_flood_control flood_ctrl
;
5019 if (!EVPN_ENABLED(zvrf
)) {
5020 zlog_err("EVPN flood control for non-EVPN VRF %u",
5026 STREAM_GETC(s
, flood_ctrl
);
5028 if (IS_ZEBRA_DEBUG_VXLAN
)
5029 zlog_debug("EVPN flood control %u, currently %u",
5030 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
5032 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
5035 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
5037 /* Install or uninstall flood entries corresponding to
5040 hash_iterate(zvrf
->evpn_table
, zebra_evpn_handle_flooding_remote_vteps
,
5048 * Handle message from client to enable/disable advertisement of svi macip
5051 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
5056 struct zebra_evpn
*zevpn
= NULL
;
5057 struct interface
*ifp
= NULL
;
5059 if (!EVPN_ENABLED(zvrf
)) {
5060 zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u",
5066 STREAM_GETC(s
, advertise
);
5067 STREAM_GETL(s
, vni
);
5070 if (IS_ZEBRA_DEBUG_VXLAN
)
5071 zlog_debug("EVPN SVI-MACIP Adv %s, currently %s",
5072 advertise
? "enabled" : "disabled",
5073 advertise_svi_macip_enabled(NULL
)
5077 if (zvrf
->advertise_svi_macip
== advertise
)
5082 zvrf
->advertise_svi_macip
= advertise
;
5083 hash_iterate(zvrf
->evpn_table
,
5084 zebra_evpn_gw_macip_add_for_evpn_hash
,
5087 hash_iterate(zvrf
->evpn_table
,
5088 zebra_evpn_svi_macip_del_for_evpn_hash
,
5090 zvrf
->advertise_svi_macip
= advertise
;
5094 struct zebra_if
*zif
= NULL
;
5095 struct interface
*vlan_if
= NULL
;
5096 struct zebra_vxlan_vni
*zl2_info_vni
;
5099 zevpn
= zebra_evpn_lookup(vni
);
5103 if (IS_ZEBRA_DEBUG_VXLAN
)
5105 "EVPN SVI macip Adv %s on VNI %d, currently %s",
5106 advertise
? "enabled" : "disabled", vni
,
5107 advertise_svi_macip_enabled(zevpn
)
5111 old_advertise
= advertise_svi_macip_enabled(zevpn
);
5113 /* Store flag even though SVI is not present.
5114 * Once SVI comes up triggers self MAC-IP route add.
5116 zevpn
->advertise_svi_macip
= advertise
;
5117 if (advertise_svi_macip_enabled(zevpn
) == old_advertise
)
5120 ifp
= zevpn
->vxlan_if
;
5126 /* If down or not mapped to a bridge, we're done. */
5127 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5130 zl2_info_vni
= zebra_vxlan_if_vni_find(zif
, vni
);
5134 vlan_if
= zvni_map_to_svi(zl2_info_vni
->access_vlan
,
5135 zif
->brslave_info
.br_if
);
5140 /* Add primary SVI MAC-IP */
5141 zebra_evpn_add_macip_for_intf(vlan_if
, zevpn
);
5143 /* Del primary SVI MAC-IP */
5144 zebra_evpn_del_macip_for_intf(vlan_if
, zevpn
);
5153 * Handle message from client to enable/disable advertisement of g/w macip
5156 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
5161 struct zebra_evpn
*zevpn
= NULL
;
5162 struct interface
*ifp
= NULL
;
5163 struct zebra_if
*zif
= NULL
;
5164 struct interface
*vlan_if
= NULL
;
5165 struct zebra_vxlan_vni
*zl2_info_vni
= NULL
;
5167 if (!EVPN_ENABLED(zvrf
)) {
5168 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
5174 STREAM_GETC(s
, advertise
);
5175 STREAM_GET(&vni
, s
, 3);
5177 zevpn
= zebra_evpn_lookup(vni
);
5181 if (zevpn
->advertise_subnet
== advertise
)
5184 if (IS_ZEBRA_DEBUG_VXLAN
)
5185 zlog_debug("EVPN subnet Adv %s on VNI %d, currently %s",
5186 advertise
? "enabled" : "disabled", vni
,
5187 zevpn
->advertise_subnet
? "enabled" : "disabled");
5190 zevpn
->advertise_subnet
= advertise
;
5192 ifp
= zevpn
->vxlan_if
;
5198 /* If down or not mapped to a bridge, we're done. */
5199 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5202 zl2_info_vni
= zebra_vxlan_if_vni_find(zif
, vni
);
5206 vlan_if
= zvni_map_to_svi(zl2_info_vni
->access_vlan
,
5207 zif
->brslave_info
.br_if
);
5211 if (zevpn
->advertise_subnet
)
5212 zebra_evpn_advertise_subnet(zevpn
, vlan_if
, 1);
5214 zebra_evpn_advertise_subnet(zevpn
, vlan_if
, 0);
5221 * Handle message from client to enable/disable advertisement of g/w macip
5224 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
5229 struct zebra_evpn
*zevpn
= NULL
;
5230 struct interface
*ifp
= NULL
;
5232 if (!EVPN_ENABLED(zvrf
)) {
5233 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
5239 STREAM_GETC(s
, advertise
);
5240 STREAM_GETL(s
, vni
);
5243 if (IS_ZEBRA_DEBUG_VXLAN
)
5244 zlog_debug("EVPN gateway macip Adv %s, currently %s",
5245 advertise
? "enabled" : "disabled",
5246 advertise_gw_macip_enabled(NULL
)
5250 if (zvrf
->advertise_gw_macip
== advertise
)
5253 zvrf
->advertise_gw_macip
= advertise
;
5255 if (advertise_gw_macip_enabled(zevpn
))
5256 hash_iterate(zvrf
->evpn_table
,
5257 zebra_evpn_gw_macip_add_for_evpn_hash
,
5260 hash_iterate(zvrf
->evpn_table
,
5261 zebra_evpn_gw_macip_del_for_evpn_hash
,
5265 struct zebra_if
*zif
= NULL
;
5266 struct interface
*vlan_if
= NULL
;
5267 struct interface
*vrr_if
= NULL
;
5268 struct zebra_vxlan_vni
*zl2_info_vni
= NULL
;
5271 zevpn
= zebra_evpn_lookup(vni
);
5275 if (IS_ZEBRA_DEBUG_VXLAN
)
5277 "EVPN gateway macip Adv %s on VNI %d, currently %s",
5278 advertise
? "enabled" : "disabled", vni
,
5279 advertise_gw_macip_enabled(zevpn
) ? "enabled"
5282 old_advertise
= advertise_gw_macip_enabled(zevpn
);
5284 zevpn
->advertise_gw_macip
= advertise
;
5285 if (advertise_gw_macip_enabled(zevpn
) == old_advertise
)
5288 ifp
= zevpn
->vxlan_if
;
5294 /* If down or not mapped to a bridge, we're done. */
5295 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5298 zl2_info_vni
= zebra_vxlan_if_vni_find(zif
, vni
);
5302 vlan_if
= zvni_map_to_svi(zl2_info_vni
->access_vlan
,
5303 zif
->brslave_info
.br_if
);
5307 if (advertise_gw_macip_enabled(zevpn
)) {
5308 /* Add primary SVI MAC-IP */
5309 zebra_evpn_add_macip_for_intf(vlan_if
, zevpn
);
5311 /* Add VRR MAC-IP - if any*/
5312 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
5314 zebra_evpn_add_macip_for_intf(vrr_if
, zevpn
);
5316 /* Del primary MAC-IP */
5317 zebra_evpn_del_macip_for_intf(vlan_if
, zevpn
);
5319 /* Del VRR MAC-IP - if any*/
5320 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
5322 zebra_evpn_del_macip_for_intf(vrr_if
, zevpn
);
5330 static int macfdb_read_ns(struct ns
*ns
,
5331 void *_in_param
__attribute__((unused
)),
5332 void **out_param
__attribute__((unused
)))
5334 struct zebra_ns
*zns
= ns
->info
;
5337 return NS_WALK_CONTINUE
;
5340 static int neigh_read_ns(struct ns
*ns
,
5341 void *_in_param
__attribute__((unused
)),
5342 void **out_param
__attribute__((unused
)))
5344 struct zebra_ns
*zns
= ns
->info
;
5347 return NS_WALK_CONTINUE
;
5351 * Handle message from client to learn (or stop learning) about VNIs and MACs.
5352 * When enabled, the VNI hash table will be built and MAC FDB table read;
5353 * when disabled, the entries should be deleted and remote VTEPs and MACs
5354 * uninstalled from the kernel.
5355 * This also informs the setting for BUM handling at the time this change
5356 * occurs; it is relevant only when specifying "learn".
5358 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
5360 struct stream
*s
= NULL
;
5362 enum vxlan_flood_control flood_ctrl
;
5364 /* Mismatch between EVPN VRF and current VRF (should be prevented by
5366 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf
))
5370 STREAM_GETC(s
, advertise
);
5371 STREAM_GETC(s
, flood_ctrl
);
5373 if (IS_ZEBRA_DEBUG_VXLAN
)
5374 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
5375 zvrf_name(zvrf
), zvrf_id(zvrf
),
5376 advertise
? "enabled" : "disabled",
5377 is_evpn_enabled() ? "enabled" : "disabled",
5380 if (zvrf
->advertise_all_vni
== advertise
)
5383 zvrf
->advertise_all_vni
= advertise
;
5384 if (EVPN_ENABLED(zvrf
)) {
5385 zrouter
.evpn_vrf
= zvrf
;
5387 /* Note BUM handling */
5388 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
5390 /* Replay all ESs */
5391 zebra_evpn_es_send_all_to_client(true /* add */);
5393 /* Build EVPN hash table and inform BGP. */
5394 zevpn_build_hash_table();
5396 /* Add all SVI (L3 GW) MACs to BGP*/
5397 hash_iterate(zvrf
->evpn_table
,
5398 zebra_evpn_gw_macip_add_for_evpn_hash
, NULL
);
5400 /* Read the MAC FDB */
5401 ns_walk_func(macfdb_read_ns
, NULL
, NULL
);
5403 /* Read neighbors */
5404 ns_walk_func(neigh_read_ns
, NULL
, NULL
);
5406 /* Cleanup VTEPs for all EVPNs - uninstall from
5407 * kernel and free entries.
5409 hash_iterate(zvrf
->evpn_table
, zebra_evpn_vxlan_cleanup_all
,
5412 /* Delete all ESs in BGP */
5413 zebra_evpn_es_send_all_to_client(false /* add */);
5415 /* cleanup all l3vnis */
5416 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
5418 /* Mark as "no EVPN VRF" */
5419 zrouter
.evpn_vrf
= NULL
;
5427 * Allocate EVPN hash table for this VRF and do other initialization.
5428 * NOTE: Currently supported only for default VRF.
5430 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
5437 snprintf(buffer
, sizeof(buffer
), "Zebra VRF EVPN Table: %s",
5439 zvrf
->evpn_table
= hash_create_size(8, zebra_evpn_hash_keymake
,
5440 zebra_evpn_hash_cmp
, buffer
);
5442 snprintf(buffer
, sizeof(buffer
), "Zebra VxLAN SG Table: %s",
5444 zvrf
->vxlan_sg_table
= hash_create_size(8, zebra_vxlan_sg_hash_key_make
,
5445 zebra_vxlan_sg_hash_eq
, buffer
);
5448 /* Cleanup EVPN info, but don't free the table. */
5449 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
5451 struct zebra_vrf
*evpn_zvrf
= zebra_vrf_get_evpn();
5453 hash_iterate(zvrf
->evpn_table
, zebra_evpn_vxlan_cleanup_all
, zvrf
);
5454 zebra_vxlan_cleanup_sg_table(zvrf
);
5456 if (zvrf
== evpn_zvrf
)
5457 zebra_evpn_es_cleanup();
5460 /* Close all EVPN handling */
5461 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
5465 hash_iterate(zvrf
->evpn_table
, zebra_evpn_vxlan_cleanup_all
, zvrf
);
5466 hash_free(zvrf
->evpn_table
);
5467 if (zvrf
->vxlan_sg_table
) {
5468 zebra_vxlan_cleanup_sg_table(zvrf
);
5469 hash_free(zvrf
->vxlan_sg_table
);
5470 zvrf
->vxlan_sg_table
= NULL
;
5474 /* init the l3vni table */
5475 void zebra_vxlan_init(void)
5477 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
5478 "Zebra VRF L3 VNI table");
5479 zrouter
.evpn_vrf
= NULL
;
5480 zebra_evpn_mh_init();
5483 /* free l3vni table */
5484 void zebra_vxlan_disable(void)
5486 hash_free(zrouter
.l3vni_table
);
5487 zebra_evpn_mh_terminate();
5490 /* get the l3vni svi ifindex */
5491 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
5493 struct zebra_l3vni
*zl3vni
= NULL
;
5495 zl3vni
= zl3vni_from_vrf(vrf_id
);
5496 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5499 return zl3vni
->svi_if
->ifindex
;
5502 /************************** vxlan SG cache management ************************/
5503 /* Inform PIM about the mcast group */
5504 static int zebra_vxlan_sg_send(struct zebra_vrf
*zvrf
,
5505 struct prefix_sg
*sg
,
5506 char *sg_str
, uint16_t cmd
)
5508 struct zserv
*client
= NULL
;
5509 struct stream
*s
= NULL
;
5511 client
= zserv_find_client(ZEBRA_ROUTE_PIM
, 0);
5515 if (!CHECK_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
))
5518 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5520 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
5521 stream_putl(s
, IPV4_MAX_BYTELEN
);
5522 stream_put(s
, &sg
->src
.s_addr
, IPV4_MAX_BYTELEN
);
5523 stream_put(s
, &sg
->grp
.s_addr
, IPV4_MAX_BYTELEN
);
5525 /* Write packet size. */
5526 stream_putw_at(s
, 0, stream_get_endp(s
));
5528 if (IS_ZEBRA_DEBUG_VXLAN
)
5531 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", sg_str
,
5532 zebra_route_string(client
->proto
));
5534 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
5535 client
->vxlan_sg_add_cnt
++;
5537 client
->vxlan_sg_del_cnt
++;
5539 return zserv_send_message(client
, s
);
5542 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
)
5544 const struct zebra_vxlan_sg
*vxlan_sg
= p
;
5546 return (jhash_2words(vxlan_sg
->sg
.src
.s_addr
,
5547 vxlan_sg
->sg
.grp
.s_addr
, 0));
5550 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
)
5552 const struct zebra_vxlan_sg
*sg1
= p1
;
5553 const struct zebra_vxlan_sg
*sg2
= p2
;
5555 return ((sg1
->sg
.src
.s_addr
== sg2
->sg
.src
.s_addr
)
5556 && (sg1
->sg
.grp
.s_addr
== sg2
->sg
.grp
.s_addr
));
5559 static struct zebra_vxlan_sg
*zebra_vxlan_sg_new(struct zebra_vrf
*zvrf
,
5560 struct prefix_sg
*sg
)
5562 struct zebra_vxlan_sg
*vxlan_sg
;
5564 vxlan_sg
= XCALLOC(MTYPE_ZVXLAN_SG
, sizeof(*vxlan_sg
));
5566 vxlan_sg
->zvrf
= zvrf
;
5568 prefix_sg2str(sg
, vxlan_sg
->sg_str
);
5570 vxlan_sg
= hash_get(zvrf
->vxlan_sg_table
, vxlan_sg
, hash_alloc_intern
);
5572 if (IS_ZEBRA_DEBUG_VXLAN
)
5573 zlog_debug("vxlan SG %s created", vxlan_sg
->sg_str
);
5578 static struct zebra_vxlan_sg
*zebra_vxlan_sg_find(struct zebra_vrf
*zvrf
,
5579 struct prefix_sg
*sg
)
5581 struct zebra_vxlan_sg lookup
;
5584 return hash_lookup(zvrf
->vxlan_sg_table
, &lookup
);
5587 static struct zebra_vxlan_sg
*zebra_vxlan_sg_add(struct zebra_vrf
*zvrf
,
5588 struct prefix_sg
*sg
)
5590 struct zebra_vxlan_sg
*vxlan_sg
;
5591 struct zebra_vxlan_sg
*parent
= NULL
;
5594 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, sg
);
5598 /* create a *G entry for every BUM group implicitly -
5599 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
5600 * 2. the XG entry is used by pimd to setup the
5601 * vxlan-termination-mroute
5603 if (sg
->src
.s_addr
!= INADDR_ANY
) {
5604 memset(&sip
, 0, sizeof(sip
));
5605 parent
= zebra_vxlan_sg_do_ref(zvrf
, sip
, sg
->grp
);
5610 vxlan_sg
= zebra_vxlan_sg_new(zvrf
, sg
);
5612 zebra_vxlan_sg_send(zvrf
, sg
, vxlan_sg
->sg_str
,
5613 ZEBRA_VXLAN_SG_ADD
);
5618 static void zebra_vxlan_sg_del(struct zebra_vxlan_sg
*vxlan_sg
)
5621 struct zebra_vrf
*zvrf
;
5623 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
5627 /* On SG entry deletion remove the reference to its parent XG
5630 if (vxlan_sg
->sg
.src
.s_addr
!= INADDR_ANY
) {
5631 memset(&sip
, 0, sizeof(sip
));
5632 zebra_vxlan_sg_do_deref(zvrf
, sip
, vxlan_sg
->sg
.grp
);
5635 zebra_vxlan_sg_send(zvrf
, &vxlan_sg
->sg
,
5636 vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_DEL
);
5638 hash_release(vxlan_sg
->zvrf
->vxlan_sg_table
, vxlan_sg
);
5640 if (IS_ZEBRA_DEBUG_VXLAN
)
5641 zlog_debug("VXLAN SG %s deleted", vxlan_sg
->sg_str
);
5643 XFREE(MTYPE_ZVXLAN_SG
, vxlan_sg
);
5646 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
5647 struct in_addr sip
, struct in_addr mcast_grp
)
5649 struct zebra_vxlan_sg
*vxlan_sg
;
5650 struct prefix_sg sg
;
5652 sg
.family
= AF_INET
;
5653 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
5656 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, &sg
);
5660 if (vxlan_sg
->ref_cnt
)
5661 --vxlan_sg
->ref_cnt
;
5663 if (!vxlan_sg
->ref_cnt
)
5664 zebra_vxlan_sg_del(vxlan_sg
);
5667 static struct zebra_vxlan_sg
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*zvrf
,
5669 struct in_addr mcast_grp
)
5671 struct zebra_vxlan_sg
*vxlan_sg
;
5672 struct prefix_sg sg
;
5674 sg
.family
= AF_INET
;
5675 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
5678 vxlan_sg
= zebra_vxlan_sg_add(zvrf
, &sg
);
5680 ++vxlan_sg
->ref_cnt
;
5685 void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
5686 struct in_addr mcast_grp
)
5688 struct zebra_vrf
*zvrf
;
5690 if (local_vtep_ip
.s_addr
== INADDR_ANY
5691 || mcast_grp
.s_addr
== INADDR_ANY
)
5694 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
5698 zebra_vxlan_sg_do_deref(zvrf
, local_vtep_ip
, mcast_grp
);
5701 void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
, struct in_addr mcast_grp
)
5703 struct zebra_vrf
*zvrf
;
5705 if (local_vtep_ip
.s_addr
== INADDR_ANY
5706 || mcast_grp
.s_addr
== INADDR_ANY
)
5709 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
5712 zebra_vxlan_sg_do_ref(zvrf
, local_vtep_ip
, mcast_grp
);
5715 static void zebra_vxlan_xg_pre_cleanup(struct hash_bucket
*bucket
, void *arg
)
5717 struct zebra_vxlan_sg
*vxlan_sg
= (struct zebra_vxlan_sg
*)bucket
->data
;
5719 /* increment the ref count against (*,G) to prevent them from being
5722 if (vxlan_sg
->sg
.src
.s_addr
== INADDR_ANY
)
5723 ++vxlan_sg
->ref_cnt
;
5726 static void zebra_vxlan_xg_post_cleanup(struct hash_bucket
*bucket
, void *arg
)
5728 struct zebra_vxlan_sg
*vxlan_sg
= (struct zebra_vxlan_sg
*)bucket
->data
;
5730 /* decrement the dummy ref count against (*,G) to delete them */
5731 if (vxlan_sg
->sg
.src
.s_addr
== INADDR_ANY
) {
5732 if (vxlan_sg
->ref_cnt
)
5733 --vxlan_sg
->ref_cnt
;
5734 if (!vxlan_sg
->ref_cnt
)
5735 zebra_vxlan_sg_del(vxlan_sg
);
5739 static void zebra_vxlan_sg_cleanup(struct hash_bucket
*bucket
, void *arg
)
5741 struct zebra_vxlan_sg
*vxlan_sg
= (struct zebra_vxlan_sg
*)bucket
->data
;
5743 zebra_vxlan_sg_del(vxlan_sg
);
5746 static void zebra_vxlan_cleanup_sg_table(struct zebra_vrf
*zvrf
)
5748 /* increment the ref count against (*,G) to prevent them from being
5751 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_xg_pre_cleanup
, NULL
);
5753 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_cleanup
, NULL
);
5755 /* decrement the dummy ref count against the XG entries */
5756 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_xg_post_cleanup
, NULL
);
5759 static void zebra_vxlan_sg_replay_send(struct hash_bucket
*bucket
, void *arg
)
5761 struct zebra_vxlan_sg
*vxlan_sg
= (struct zebra_vxlan_sg
*)bucket
->data
;
5763 zebra_vxlan_sg_send(vxlan_sg
->zvrf
, &vxlan_sg
->sg
,
5764 vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_ADD
);
5767 /* Handle message from client to replay vxlan SG entries */
5768 void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS
)
5770 if (IS_ZEBRA_DEBUG_VXLAN
)
5771 zlog_debug("VxLAN SG updates to PIM, start");
5773 SET_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
);
5775 if (!EVPN_ENABLED(zvrf
)) {
5776 if (IS_ZEBRA_DEBUG_VXLAN
)
5777 zlog_debug("VxLAN SG replay request on unexpected vrf %d",
5782 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_replay_send
, NULL
);
5786 /* Cleanup EVPN configuration of a specific VRF */
5787 static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf
*zvrf
)
5789 struct zebra_l3vni
*zl3vni
= NULL
;
5791 zvrf
->advertise_all_vni
= 0;
5792 zvrf
->advertise_gw_macip
= 0;
5793 zvrf
->advertise_svi_macip
= 0;
5794 zvrf
->vxlan_flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
5796 hash_iterate(zvrf
->evpn_table
, zebra_evpn_cfg_cleanup
, NULL
);
5799 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5801 /* delete and uninstall all rmacs */
5802 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
5804 /* delete and uninstall all next-hops */
5805 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
5810 /* Cleanup BGP EVPN configuration upon client disconnect */
5811 static int zebra_evpn_bgp_cfg_clean_up(struct zserv
*client
)
5814 struct zebra_vrf
*zvrf
;
5816 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
5819 zebra_evpn_vrf_cfg_cleanup(zvrf
);
5825 static int zebra_evpn_pim_cfg_clean_up(struct zserv
*client
)
5827 struct zebra_vrf
*zvrf
= zebra_vrf_get_evpn();
5829 if (CHECK_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
)) {
5830 if (IS_ZEBRA_DEBUG_VXLAN
)
5831 zlog_debug("VxLAN SG updates to PIM, stop");
5832 UNSET_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
);
5838 static int zebra_evpn_cfg_clean_up(struct zserv
*client
)
5840 if (client
->proto
== ZEBRA_ROUTE_BGP
)
5841 return zebra_evpn_bgp_cfg_clean_up(client
);
5843 if (client
->proto
== ZEBRA_ROUTE_PIM
)
5844 return zebra_evpn_pim_cfg_clean_up(client
);
5850 * Handle results for vxlan dataplane operations.
5852 extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx
*ctx
)
5857 /* Config knob for accepting lower sequence numbers */
5858 void zebra_vxlan_set_accept_bgp_seq(bool set
)
5860 accept_bgp_seq
= set
;
5863 bool zebra_vxlan_get_accept_bgp_seq(void)
5865 return accept_bgp_seq
;
5868 /* Cleanup BGP EVPN configuration upon client disconnect */
5869 extern void zebra_evpn_init(void)
5871 hook_register(zserv_client_close
, zebra_evpn_cfg_clean_up
);