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 /* Single VXlan Device Global Neigh Table */
77 struct hash
*svd_nh_table
;
79 /* static function declarations */
80 static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket
*bucket
,
82 static void zl3vni_print_nh(struct zebra_neigh
*n
, struct vty
*vty
,
84 static void zl3vni_print_rmac(struct zebra_mac
*zrmac
, struct vty
*vty
,
86 static void zevpn_print_mac_hash_all_evpn(struct hash_bucket
*bucket
, void *ctxt
);
88 /* l3-vni next-hop neigh related APIs */
89 static struct zebra_neigh
*zl3vni_nh_lookup(struct zebra_l3vni
*zl3vni
,
90 const struct ipaddr
*ip
);
91 static void *zl3vni_nh_alloc(void *p
);
92 static struct zebra_neigh
*zl3vni_nh_add(struct zebra_l3vni
*zl3vni
,
93 const struct ipaddr
*vtep_ip
,
94 const struct ethaddr
*rmac
);
95 static int zl3vni_nh_del(struct zebra_l3vni
*zl3vni
, struct zebra_neigh
*n
);
96 static int zl3vni_nh_install(struct zebra_l3vni
*zl3vni
, struct zebra_neigh
*n
);
97 static int zl3vni_nh_uninstall(struct zebra_l3vni
*zl3vni
,
98 struct zebra_neigh
*n
);
99 static struct zebra_neigh
*svd_nh_add(const struct ipaddr
*vtep_ip
,
100 const struct ethaddr
*rmac
);
101 static int svd_nh_del(struct zebra_neigh
*n
);
102 static int svd_nh_install(struct zebra_l3vni
*zl3vni
, struct zebra_neigh
*n
);
103 static int svd_nh_uninstall(struct zebra_l3vni
*zl3vni
, struct zebra_neigh
*n
);
105 /* l3-vni rmac related APIs */
106 static void zl3vni_print_rmac_hash(struct hash_bucket
*, void *);
107 static struct zebra_mac
*zl3vni_rmac_lookup(struct zebra_l3vni
*zl3vni
,
108 const struct ethaddr
*rmac
);
109 static void *zl3vni_rmac_alloc(void *p
);
110 static struct zebra_mac
*zl3vni_rmac_add(struct zebra_l3vni
*zl3vni
,
111 const struct ethaddr
*rmac
);
112 static int zl3vni_rmac_del(struct zebra_l3vni
*zl3vni
, struct zebra_mac
*zrmac
);
113 static int zl3vni_rmac_install(struct zebra_l3vni
*zl3vni
,
114 struct zebra_mac
*zrmac
);
115 static int zl3vni_rmac_uninstall(struct zebra_l3vni
*zl3vni
,
116 struct zebra_mac
*zrmac
);
118 /* l3-vni related APIs*/
119 static void *zl3vni_alloc(void *p
);
120 static struct zebra_l3vni
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
121 static int zl3vni_del(struct zebra_l3vni
*zl3vni
);
123 static void zevpn_build_hash_table(void);
124 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
);
125 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
);
126 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
127 struct in_addr sip
, struct in_addr mcast_grp
);
128 static struct zebra_vxlan_sg
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*vrf
,
130 struct in_addr mcast_grp
);
131 static void zebra_vxlan_cleanup_sg_table(struct zebra_vrf
*zvrf
);
133 bool zebra_evpn_do_dup_addr_detect(struct zebra_vrf
*zvrf
)
135 return zvrf
->dup_addr_detect
&& zebra_evpn_mh_do_dup_addr_detect();
138 /* Private functions */
139 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
140 const struct host_rb_entry
*hle2
)
142 if (hle1
->p
.family
< hle2
->p
.family
)
145 if (hle1
->p
.family
> hle2
->p
.family
)
148 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
151 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
154 if (hle1
->p
.family
== AF_INET
) {
155 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
158 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
162 } else if (hle1
->p
.family
== AF_INET6
) {
163 return memcmp(&hle1
->p
.u
.prefix6
, &hle2
->p
.u
.prefix6
,
165 } else if (hle1
->p
.family
== AF_EVPN
) {
169 /* two (v4/v6) dummy prefixes of route_type BGP_EVPN_AD_ROUTE
170 * are used for all nexthops associated with a non-zero ESI
172 family1
= is_evpn_prefix_ipaddr_v4(
173 (const struct prefix_evpn
*)&hle1
->p
)
176 family2
= is_evpn_prefix_ipaddr_v4(
177 (const struct prefix_evpn
*)&hle2
->p
)
182 if (family1
< family2
)
185 if (family1
> family2
)
190 zlog_debug("%s: Unexpected family type: %d", __func__
,
195 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
197 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
199 struct host_rb_entry
*hle
;
202 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
208 static int l3vni_rmac_nh_list_cmp(void *p1
, void *p2
)
210 const struct ipaddr
*vtep_ip1
= p1
;
211 const struct ipaddr
*vtep_ip2
= p2
;
213 return !ipaddr_cmp(vtep_ip1
, vtep_ip2
);
216 static void l3vni_rmac_nh_free(struct ipaddr
*vtep_ip
)
218 XFREE(MTYPE_EVPN_VTEP
, vtep_ip
);
221 static void l3vni_rmac_nh_list_nh_delete(struct zebra_l3vni
*zl3vni
,
222 struct zebra_mac
*zrmac
,
223 struct ipaddr
*vtep_ip
)
225 struct listnode
*node
= NULL
, *nnode
= NULL
;
226 struct ipaddr
*vtep
= NULL
;
228 for (ALL_LIST_ELEMENTS(zrmac
->nh_list
, node
, nnode
, vtep
)) {
229 if (ipaddr_cmp(vtep
, vtep_ip
) == 0)
234 l3vni_rmac_nh_free(vtep
);
235 list_delete_node(zrmac
->nh_list
, node
);
240 * Print neighbors for all EVPN.
242 static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket
*bucket
,
246 json_object
*json
= NULL
, *json_evpn
= NULL
;
247 struct zebra_evpn
*zevpn
;
249 struct neigh_walk_ctx wctx
;
250 char vni_str
[VNI_STR_LEN
];
253 vty
= (struct vty
*)args
[0];
254 json
= (json_object
*)args
[1];
255 print_dup
= (uint32_t)(uintptr_t)args
[2];
257 zevpn
= (struct zebra_evpn
*)bucket
->data
;
259 num_neigh
= hashcount(zevpn
->neigh_table
);
262 num_neigh
= num_dup_detected_neighs(zevpn
);
266 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
267 zevpn
->vni
, num_neigh
);
269 json_evpn
= json_object_new_object();
270 json_object_int_add(json_evpn
, "numArpNd", num_neigh
);
271 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
276 json_object_object_add(json
, vni_str
, json_evpn
);
280 /* Since we have IPv6 addresses to deal with which can vary widely in
281 * size, we try to be a bit more elegant in display by first computing
284 memset(&wctx
, 0, sizeof(wctx
));
287 wctx
.addr_width
= 15;
288 wctx
.json
= json_evpn
;
289 hash_iterate(zevpn
->neigh_table
, zebra_evpn_find_neigh_addr_width
,
293 zebra_evpn_print_neigh_hdr(vty
, &wctx
);
296 hash_iterate(zevpn
->neigh_table
,
297 zebra_evpn_print_dad_neigh_hash
, &wctx
);
299 hash_iterate(zevpn
->neigh_table
, zebra_evpn_print_neigh_hash
,
303 json_object_object_add(json
, vni_str
, json_evpn
);
307 * Print neighbors for all EVPNs in detail.
309 static void zevpn_print_neigh_hash_all_evpn_detail(struct hash_bucket
*bucket
,
313 json_object
*json
= NULL
, *json_evpn
= NULL
;
314 struct zebra_evpn
*zevpn
;
316 struct neigh_walk_ctx wctx
;
317 char vni_str
[VNI_STR_LEN
];
320 vty
= (struct vty
*)args
[0];
321 json
= (json_object
*)args
[1];
322 print_dup
= (uint32_t)(uintptr_t)args
[2];
324 zevpn
= (struct zebra_evpn
*)bucket
->data
;
327 vty_out(vty
, "{}\n");
330 num_neigh
= hashcount(zevpn
->neigh_table
);
332 if (print_dup
&& num_dup_detected_neighs(zevpn
) == 0)
337 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
338 zevpn
->vni
, num_neigh
);
340 json_evpn
= json_object_new_object();
341 json_object_int_add(json_evpn
, "numArpNd", num_neigh
);
342 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
346 json_object_object_add(json
, vni_str
, json_evpn
);
350 memset(&wctx
, 0, sizeof(wctx
));
353 wctx
.addr_width
= 15;
354 wctx
.json
= json_evpn
;
357 hash_iterate(zevpn
->neigh_table
,
358 zebra_evpn_print_dad_neigh_hash_detail
, &wctx
);
360 hash_iterate(zevpn
->neigh_table
,
361 zebra_evpn_print_neigh_hash_detail
, &wctx
);
364 json_object_object_add(json
, vni_str
, json_evpn
);
367 /* print a specific next hop for an l3vni */
368 static void zl3vni_print_nh(struct zebra_neigh
*n
, struct vty
*vty
,
371 char buf1
[ETHER_ADDR_STRLEN
];
372 char buf2
[INET6_ADDRSTRLEN
];
373 json_object
*json_hosts
= NULL
;
374 struct host_rb_entry
*hle
;
377 vty_out(vty
, "Ip: %s\n",
378 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
379 vty_out(vty
, " RMAC: %s\n",
380 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
381 vty_out(vty
, " Refcount: %d\n",
382 rb_host_count(&n
->host_rb
));
383 vty_out(vty
, " Prefixes:\n");
384 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
385 vty_out(vty
, " %pFX\n", &hle
->p
);
387 json_hosts
= json_object_new_array();
388 json_object_string_add(
389 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
390 json_object_string_add(
392 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
393 json_object_int_add(json
, "refCount",
394 rb_host_count(&n
->host_rb
));
395 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
396 json_object_array_add(json_hosts
,
397 json_object_new_string(prefix2str(
398 &hle
->p
, buf2
, sizeof(buf2
))));
399 json_object_object_add(json
, "prefixList", json_hosts
);
403 /* Print a specific RMAC entry */
404 static void zl3vni_print_rmac(struct zebra_mac
*zrmac
, struct vty
*vty
,
407 struct listnode
*node
= NULL
;
408 struct ipaddr
*vtep
= NULL
;
409 json_object
*json_nhs
= NULL
;
412 vty_out(vty
, "MAC: %pEA\n", &zrmac
->macaddr
);
413 vty_out(vty
, " Remote VTEP: %pI4\n",
414 &zrmac
->fwd_info
.r_vtep_ip
);
416 json_nhs
= json_object_new_array();
417 json_object_string_addf(json
, "routerMac", "%pEA",
419 json_object_string_addf(json
, "vtepIp", "%pI4",
420 &zrmac
->fwd_info
.r_vtep_ip
);
421 for (ALL_LIST_ELEMENTS_RO(zrmac
->nh_list
, node
, vtep
)) {
422 json_object_array_add(json_nhs
, json_object_new_stringf(
425 json_object_object_add(json
, "nexthops", json_nhs
);
430 * Print MACs for all EVPNs.
432 static void zevpn_print_mac_hash_all_evpn(struct hash_bucket
*bucket
, void *ctxt
)
435 json_object
*json
= NULL
, *json_evpn
= NULL
;
436 json_object
*json_mac
= NULL
;
437 struct zebra_evpn
*zevpn
;
439 struct mac_walk_ctx
*wctx
= ctxt
;
440 char vni_str
[VNI_STR_LEN
];
445 zevpn
= (struct zebra_evpn
*)bucket
->data
;
448 /*We are iterating over a new VNI, set the count to 0*/
451 num_macs
= num_valid_macs(zevpn
);
456 num_macs
= num_dup_detected_macs(zevpn
);
459 json_evpn
= json_object_new_object();
460 json_mac
= json_object_new_object();
461 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
464 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
466 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
467 zevpn
->vni
, num_macs
);
469 "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
470 vty_out(vty
, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC",
471 "Type", "Flags", "Intf/Remote ES/VTEP",
474 json_object_int_add(json_evpn
, "numMacs", num_macs
);
479 json_object_int_add(json_evpn
, "numMacs", num_macs
);
480 json_object_object_add(json
, vni_str
, json_evpn
);
485 /* assign per-evpn to wctx->json object to fill macs
486 * under the evpn. Re-assign primary json object to fill
487 * next evpn information.
489 wctx
->json
= json_mac
;
491 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_dad_mac_hash
,
494 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_mac_hash
, wctx
);
498 json_object_object_add(json_evpn
, "macs", json_mac
);
499 json_object_object_add(json
, vni_str
, json_evpn
);
504 * Print MACs in detail for all EVPNs.
506 static void zevpn_print_mac_hash_all_evpn_detail(struct hash_bucket
*bucket
,
510 json_object
*json
= NULL
, *json_evpn
= NULL
;
511 json_object
*json_mac
= NULL
;
512 struct zebra_evpn
*zevpn
;
514 struct mac_walk_ctx
*wctx
= ctxt
;
515 char vni_str
[VNI_STR_LEN
];
520 zevpn
= (struct zebra_evpn
*)bucket
->data
;
523 vty_out(vty
, "{}\n");
528 /*We are iterating over a new EVPN, set the count to 0*/
531 num_macs
= num_valid_macs(zevpn
);
535 if (wctx
->print_dup
&& (num_dup_detected_macs(zevpn
) == 0))
539 json_evpn
= json_object_new_object();
540 json_mac
= json_object_new_object();
541 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
544 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
546 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
547 zevpn
->vni
, num_macs
);
549 json_object_int_add(json_evpn
, "numMacs", num_macs
);
551 /* assign per-evpn to wctx->json object to fill macs
552 * under the evpn. Re-assign primary json object to fill
553 * next evpn information.
555 wctx
->json
= json_mac
;
557 hash_iterate(zevpn
->mac_table
,
558 zebra_evpn_print_dad_mac_hash_detail
, wctx
);
560 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_mac_hash_detail
,
565 json_object_object_add(json_evpn
, "macs", json_mac
);
566 json_object_object_add(json
, vni_str
, json_evpn
);
570 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
572 struct nh_walk_ctx
*wctx
= NULL
;
573 struct vty
*vty
= NULL
;
574 struct json_object
*json_evpn
= NULL
;
575 struct json_object
*json_nh
= NULL
;
576 struct zebra_neigh
*n
= NULL
;
577 char buf1
[ETHER_ADDR_STRLEN
];
578 char buf2
[INET6_ADDRSTRLEN
];
580 wctx
= (struct nh_walk_ctx
*)ctx
;
582 json_evpn
= wctx
->json
;
584 json_nh
= json_object_new_object();
585 n
= (struct zebra_neigh
*)bucket
->data
;
588 vty_out(vty
, "%-15s %-17s\n",
589 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
590 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
592 json_object_string_add(json_nh
, "nexthopIp",
593 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
594 json_object_string_add(
595 json_nh
, "routerMac",
596 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
597 json_object_object_add(json_evpn
,
598 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
603 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
606 struct vty
*vty
= NULL
;
607 json_object
*json
= NULL
;
608 json_object
*json_evpn
= NULL
;
609 struct zebra_l3vni
*zl3vni
= NULL
;
611 struct nh_walk_ctx wctx
;
612 char vni_str
[VNI_STR_LEN
];
614 vty
= (struct vty
*)args
[0];
615 json
= (struct json_object
*)args
[1];
617 zl3vni
= (struct zebra_l3vni
*)bucket
->data
;
619 num_nh
= hashcount(zl3vni
->nh_table
);
624 json_evpn
= json_object_new_object();
625 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
629 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
630 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
632 json_object_int_add(json_evpn
, "numNextHops", num_nh
);
634 memset(&wctx
, 0, sizeof(wctx
));
636 wctx
.json
= json_evpn
;
637 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
639 json_object_object_add(json
, vni_str
, json_evpn
);
642 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
645 struct vty
*vty
= NULL
;
646 json_object
*json
= NULL
;
647 json_object
*json_evpn
= NULL
;
648 struct zebra_l3vni
*zl3vni
= NULL
;
650 struct rmac_walk_ctx wctx
;
651 char vni_str
[VNI_STR_LEN
];
653 vty
= (struct vty
*)args
[0];
654 json
= (struct json_object
*)args
[1];
656 zl3vni
= (struct zebra_l3vni
*)bucket
->data
;
658 num_rmacs
= hashcount(zl3vni
->rmac_table
);
663 json_evpn
= json_object_new_object();
664 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
668 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
669 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
671 json_object_int_add(json_evpn
, "numRmacs", num_rmacs
);
673 /* assign per-vni to wctx->json object to fill macs
674 * under the vni. Re-assign primary json object to fill
675 * next vni information.
677 memset(&wctx
, 0, sizeof(wctx
));
679 wctx
.json
= json_evpn
;
680 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
682 json_object_object_add(json
, vni_str
, json_evpn
);
685 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
687 struct zebra_mac
*zrmac
= NULL
;
688 struct rmac_walk_ctx
*wctx
= NULL
;
689 struct vty
*vty
= NULL
;
690 struct json_object
*json
= NULL
;
691 struct json_object
*json_rmac
= NULL
;
692 char buf
[PREFIX_STRLEN
];
694 wctx
= (struct rmac_walk_ctx
*)ctx
;
698 json_rmac
= json_object_new_object();
699 zrmac
= (struct zebra_mac
*)bucket
->data
;
702 vty_out(vty
, "%-17s %-21pI4\n",
703 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
704 &zrmac
->fwd_info
.r_vtep_ip
);
706 json_object_string_add(
707 json_rmac
, "routerMac",
708 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
709 json_object_string_addf(json_rmac
, "vtepIp", "%pI4",
710 &zrmac
->fwd_info
.r_vtep_ip
);
711 json_object_object_add(
712 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
717 /* print a specific L3 VNI entry */
718 static void zl3vni_print(struct zebra_l3vni
*zl3vni
, void **ctx
)
720 char buf
[PREFIX_STRLEN
];
721 struct vty
*vty
= NULL
;
722 json_object
*json
= NULL
;
723 struct zebra_evpn
*zevpn
= NULL
;
724 json_object
*json_evpn_list
= NULL
;
725 struct listnode
*node
= NULL
, *nnode
= NULL
;
731 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
732 vty_out(vty
, " Type: %s\n", "L3");
733 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
734 vty_out(vty
, " Vlan: %u\n", zl3vni
->vid
);
735 vty_out(vty
, " Bridge: %s\n",
736 zl3vni
->bridge_if
? zl3vni
->bridge_if
->name
: "-");
737 vty_out(vty
, " Local Vtep Ip: %pI4\n",
738 &zl3vni
->local_vtep_ip
);
739 vty_out(vty
, " Vxlan-Intf: %s\n",
740 zl3vni_vxlan_if_name(zl3vni
));
741 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
742 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
743 vty_out(vty
, " VNI Filter: %s\n",
744 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
745 ? "prefix-routes-only"
747 vty_out(vty
, " System MAC: %s\n",
748 zl3vni_sysmac2str(zl3vni
, buf
, sizeof(buf
)));
749 vty_out(vty
, " Router MAC: %s\n",
750 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
751 vty_out(vty
, " L2 VNIs: ");
752 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zevpn
))
753 vty_out(vty
, "%u ", zevpn
->vni
);
756 json_evpn_list
= json_object_new_array();
757 json_object_int_add(json
, "vni", zl3vni
->vni
);
758 json_object_string_add(json
, "type", "L3");
759 #if CONFDATE > 20240210
760 CPP_NOTICE("Drop `vrf` from JSON outputs")
762 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
763 json_object_string_add(json
, "tenantVrf",
764 zl3vni_vrf_name(zl3vni
));
765 json_object_string_addf(json
, "localVtepIp", "%pI4",
766 &zl3vni
->local_vtep_ip
);
767 json_object_string_add(json
, "vxlanIntf",
768 zl3vni_vxlan_if_name(zl3vni
));
769 json_object_string_add(json
, "sviIntf",
770 zl3vni_svi_if_name(zl3vni
));
771 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
772 json_object_string_add(
774 zl3vni_sysmac2str(zl3vni
, buf
, sizeof(buf
)));
775 json_object_string_add(
777 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
778 json_object_string_add(
780 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
781 ? "prefix-routes-only"
783 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zevpn
)) {
784 json_object_array_add(json_evpn_list
,
785 json_object_new_int(zevpn
->vni
));
787 json_object_object_add(json
, "l2Vnis", json_evpn_list
);
791 /* print a L3 VNI hash entry */
792 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
794 struct vty
*vty
= NULL
;
795 json_object
*json
= NULL
;
796 json_object
*json_evpn
= NULL
;
797 struct zebra_l3vni
*zl3vni
= NULL
;
799 vty
= (struct vty
*)ctx
[0];
800 json
= (json_object
*)ctx
[1];
802 zl3vni
= (struct zebra_l3vni
*)bucket
->data
;
805 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
806 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
807 hashcount(zl3vni
->rmac_table
),
808 hashcount(zl3vni
->nh_table
), "n/a",
809 zl3vni_vrf_name(zl3vni
));
811 char vni_str
[VNI_STR_LEN
];
813 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
814 json_evpn
= json_object_new_object();
815 json_object_int_add(json_evpn
, "vni", zl3vni
->vni
);
816 json_object_string_add(json_evpn
, "vxlanIf",
817 zl3vni_vxlan_if_name(zl3vni
));
818 json_object_int_add(json_evpn
, "numMacs",
819 hashcount(zl3vni
->rmac_table
));
820 json_object_int_add(json_evpn
, "numArpNd",
821 hashcount(zl3vni
->nh_table
));
822 json_object_string_add(json_evpn
, "numRemoteVteps", "n/a");
823 json_object_string_add(json_evpn
, "type", "L3");
824 json_object_string_add(json_evpn
, "tenantVrf",
825 zl3vni_vrf_name(zl3vni
));
826 json_object_object_add(json
, vni_str
, json_evpn
);
830 /* print a L3 VNI hash entry in detail*/
831 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
833 struct vty
*vty
= NULL
;
834 struct zebra_l3vni
*zl3vni
= NULL
;
835 json_object
*json_array
= NULL
;
836 bool use_json
= false;
837 struct zebra_evpn_show
*zes
= data
;
840 json_array
= zes
->json
;
841 use_json
= zes
->use_json
;
843 zl3vni
= (struct zebra_l3vni
*)bucket
->data
;
845 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
,
846 use_json
, json_array
);
852 static int zvni_map_to_svi_ns(struct ns
*ns
,
856 struct zebra_ns
*zns
= ns
->info
;
857 struct route_node
*rn
;
858 struct zebra_from_svi_param
*in_param
=
859 (struct zebra_from_svi_param
*)_in_param
;
860 struct zebra_l2info_vlan
*vl
;
861 struct interface
*tmp_if
= NULL
;
862 struct interface
**p_ifp
= (struct interface
**)_p_ifp
;
863 struct zebra_if
*zif
;
865 assert(in_param
&& p_ifp
);
867 /* TODO: Optimize with a hash. */
868 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
869 tmp_if
= (struct interface
*)rn
->info
;
870 /* Check oper status of the SVI. */
871 if (!tmp_if
|| !if_is_operative(tmp_if
))
874 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
875 || zif
->link
!= in_param
->br_if
)
877 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
879 if (vl
->vid
== in_param
->vid
) {
884 return NS_WALK_CONTINUE
;
887 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
889 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
890 * linked to the bridge
891 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge interface
894 struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
896 struct interface
*tmp_if
= NULL
;
897 struct zebra_if
*zif
;
898 struct zebra_from_svi_param in_param
;
899 struct interface
**p_ifp
;
900 /* Defensive check, caller expected to invoke only with valid bridge. */
904 /* Determine if bridge is VLAN-aware or not */
907 in_param
.bridge_vlan_aware
= IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zif
);
908 /* Check oper status of the SVI. */
909 if (!in_param
.bridge_vlan_aware
)
910 return if_is_operative(br_if
) ? br_if
: NULL
;
913 in_param
.br_if
= br_if
;
916 /* Identify corresponding VLAN interface. */
917 ns_walk_func(zvni_map_to_svi_ns
, (void *)&in_param
,
922 int zebra_evpn_vxlan_del(struct zebra_evpn
*zevpn
)
925 zevpn_vxlan_if_set(zevpn
, zevpn
->vxlan_if
, false /* set */);
926 zevpn_bridge_if_set(zevpn
, zevpn
->bridge_if
, false /* set */);
928 /* Remove references to the BUM mcast grp */
929 zebra_vxlan_sg_deref(zevpn
->local_vtep_ip
, zevpn
->mcast_grp
);
931 return zebra_evpn_del(zevpn
);
934 static int zevpn_build_vni_hash_table(struct zebra_if
*zif
,
935 struct zebra_vxlan_vni
*vnip
, void *arg
)
938 struct zebra_evpn
*zevpn
;
939 struct zebra_l3vni
*zl3vni
;
940 struct interface
*ifp
;
941 struct zebra_l2info_vxlan
*vxl
;
942 struct interface
*br_if
;
945 vxl
= &zif
->l2info
.vxl
;
948 if (IS_ZEBRA_DEBUG_VXLAN
)
949 zlog_debug("Build vni table for vni %u for Intf %s", vni
,
952 /* L3-VNI and L2-VNI are handled seperately */
953 zl3vni
= zl3vni_lookup(vni
);
956 if (IS_ZEBRA_DEBUG_VXLAN
)
958 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
959 ifp
->name
, ifp
->ifindex
, vni
);
961 /* associate with vxlan_if */
962 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
963 zl3vni
->vxlan_if
= ifp
;
966 * we need to associate with SVI.
967 * we can associate with svi-if only after association
968 * with vxlan-intf is complete
970 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
972 /* Associate l3vni to mac-vlan and extract VRR MAC */
973 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
975 if (IS_ZEBRA_DEBUG_VXLAN
)
977 "create l3vni %u svi_if %s mac_vlan_if %s", vni
,
978 zl3vni
->svi_if
? zl3vni
->svi_if
->name
: "NIL",
979 zl3vni
->mac_vlan_if
? zl3vni
->mac_vlan_if
->name
982 if (is_l3vni_oper_up(zl3vni
))
983 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
986 struct interface
*vlan_if
= NULL
;
988 if (IS_ZEBRA_DEBUG_VXLAN
)
990 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %pI4",
991 ifp
->name
, ifp
->ifindex
, vni
, &vxl
->vtep_ip
);
994 * EVPN hash entry is expected to exist, if the BGP process is
997 zevpn
= zebra_evpn_lookup(vni
);
1000 "EVPN hash already present for IF %s(%u) L2-VNI %u",
1001 ifp
->name
, ifp
->ifindex
, vni
);
1004 * Inform BGP if intf is up and mapped to
1007 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
1008 zebra_evpn_send_add_to_client(zevpn
);
1010 /* Send Local MAC-entries to client */
1011 zebra_evpn_send_mac_list_to_client(zevpn
);
1013 /* Send Loval Neighbor entries to client */
1014 zebra_evpn_send_neigh_to_client(zevpn
);
1016 zevpn
= zebra_evpn_add(vni
);
1019 "Failed to add EVPN hash, IF %s(%u) L2-VNI %u",
1020 ifp
->name
, ifp
->ifindex
, vni
);
1024 if (zevpn
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
1025 || zevpn
->mcast_grp
.s_addr
1026 != vnip
->mcast_grp
.s_addr
) {
1027 zebra_vxlan_sg_deref(zevpn
->local_vtep_ip
,
1029 zebra_vxlan_sg_ref(vxl
->vtep_ip
,
1031 zevpn
->local_vtep_ip
= vxl
->vtep_ip
;
1032 zevpn
->mcast_grp
= vnip
->mcast_grp
;
1033 /* on local vtep-ip check if ES
1034 * orig-ip needs to be updated
1036 zebra_evpn_es_set_base_evpn(zevpn
);
1038 zevpn_vxlan_if_set(zevpn
, ifp
, true /* set */);
1039 br_if
= zif
->brslave_info
.br_if
;
1040 zevpn_bridge_if_set(zevpn
, br_if
, true /* set */);
1041 vlan_if
= zvni_map_to_svi(vnip
->access_vlan
, br_if
);
1043 zevpn
->vid
= vnip
->access_vlan
;
1044 zevpn
->svi_if
= vlan_if
;
1045 zevpn
->vrf_id
= vlan_if
->vrf
->vrf_id
;
1046 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf
->vrf_id
);
1048 listnode_add_sort(zl3vni
->l2vnis
,
1053 * Inform BGP if intf is up and mapped to
1056 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
1057 zebra_evpn_send_add_to_client(zevpn
);
1064 static int zevpn_build_hash_table_zns(struct ns
*ns
,
1065 void *param_in
__attribute__((unused
)),
1066 void **param_out
__attribute__((unused
)))
1068 struct zebra_ns
*zns
= ns
->info
;
1069 struct route_node
*rn
;
1070 struct interface
*ifp
;
1071 struct zebra_vrf
*zvrf
;
1073 zvrf
= zebra_vrf_get_evpn();
1075 /* Walk VxLAN interfaces and create EVPN hash. */
1076 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
1077 struct zebra_if
*zif
;
1078 struct zebra_l2info_vxlan
*vxl
;
1080 ifp
= (struct interface
*)rn
->info
;
1084 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
1087 vxl
= &zif
->l2info
.vxl
;
1088 /* link of VXLAN interface should be in zebra_evpn_vrf */
1089 if (zvrf
->zns
->ns_id
!= vxl
->link_nsid
) {
1090 if (IS_ZEBRA_DEBUG_VXLAN
)
1092 "Intf %s(%u) link not in same "
1093 "namespace than BGP EVPN core instance ",
1094 ifp
->name
, ifp
->ifindex
);
1098 if (IS_ZEBRA_DEBUG_VXLAN
)
1099 zlog_debug("Building vni table for %s-if %s",
1100 IS_ZEBRA_VXLAN_IF_VNI(zif
) ? "vni" : "svd",
1103 zebra_vxlan_if_vni_iterate(zif
, zevpn_build_vni_hash_table
,
1106 return NS_WALK_CONTINUE
;
1110 * Build the VNI hash table by going over the VxLAN interfaces. This
1111 * is called when EVPN (advertise-all-vni) is enabled.
1114 static void zevpn_build_hash_table(void)
1116 ns_walk_func(zevpn_build_hash_table_zns
, NULL
, NULL
);
1120 * Cleanup EVPN/VTEP and update kernel
1122 static void zebra_evpn_vxlan_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
1124 struct zebra_evpn
*zevpn
= NULL
;
1125 struct zebra_l3vni
*zl3vni
= NULL
;
1127 zevpn
= (struct zebra_evpn
*)bucket
->data
;
1129 /* remove l2vni from l2vni's tenant-vrf l3-vni list */
1130 zl3vni
= zl3vni_from_vrf(zevpn
->vrf_id
);
1132 listnode_delete(zl3vni
->l2vnis
, zevpn
);
1134 zebra_evpn_cleanup_all(bucket
, arg
);
1138 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
1140 struct zebra_l3vni
*zl3vni
= NULL
;
1142 zl3vni
= (struct zebra_l3vni
*)bucket
->data
;
1144 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
1147 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
1148 const struct prefix
*host
)
1150 struct host_rb_entry lookup
;
1151 struct host_rb_entry
*hle
;
1153 memset(&lookup
, 0, sizeof(lookup
));
1154 memcpy(&lookup
.p
, host
, sizeof(*host
));
1156 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
1160 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
1161 memcpy(hle
, &lookup
, sizeof(lookup
));
1163 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
1166 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
1168 struct host_rb_entry lookup
;
1169 struct host_rb_entry
*hle
;
1171 memset(&lookup
, 0, sizeof(lookup
));
1172 memcpy(&lookup
.p
, host
, sizeof(*host
));
1174 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
1176 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
1177 XFREE(MTYPE_HOST_PREFIX
, hle
);
1184 * Look up MAC hash entry.
1186 static struct zebra_mac
*zl3vni_rmac_lookup(struct zebra_l3vni
*zl3vni
,
1187 const struct ethaddr
*rmac
)
1189 struct zebra_mac tmp
;
1190 struct zebra_mac
*pmac
;
1192 memset(&tmp
, 0, sizeof(tmp
));
1193 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
1194 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
1200 * Callback to allocate RMAC hash entry.
1202 static void *zl3vni_rmac_alloc(void *p
)
1204 const struct zebra_mac
*tmp_rmac
= p
;
1205 struct zebra_mac
*zrmac
;
1207 zrmac
= XCALLOC(MTYPE_L3VNI_MAC
, sizeof(struct zebra_mac
));
1210 return ((void *)zrmac
);
1214 * Add RMAC entry to l3-vni
1216 static struct zebra_mac
*zl3vni_rmac_add(struct zebra_l3vni
*zl3vni
,
1217 const struct ethaddr
*rmac
)
1219 struct zebra_mac tmp_rmac
;
1220 struct zebra_mac
*zrmac
= NULL
;
1222 memset(&tmp_rmac
, 0, sizeof(tmp_rmac
));
1223 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
1224 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
1225 zrmac
->nh_list
= list_new();
1226 zrmac
->nh_list
->cmp
= (int (*)(void *, void *))l3vni_rmac_nh_list_cmp
;
1227 zrmac
->nh_list
->del
= (void (*)(void *))l3vni_rmac_nh_free
;
1229 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
1230 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
1238 static int zl3vni_rmac_del(struct zebra_l3vni
*zl3vni
, struct zebra_mac
*zrmac
)
1240 struct zebra_mac
*tmp_rmac
;
1242 /* free the list of nh list*/
1243 list_delete(&zrmac
->nh_list
);
1245 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
1246 XFREE(MTYPE_L3VNI_MAC
, tmp_rmac
);
1252 * Install remote RMAC into the forwarding plane.
1254 static int zl3vni_rmac_install(struct zebra_l3vni
*zl3vni
,
1255 struct zebra_mac
*zrmac
)
1257 const struct zebra_if
*zif
= NULL
, *br_zif
= NULL
;
1258 const struct zebra_vxlan_vni
*vni
;
1259 const struct interface
*br_ifp
;
1260 enum zebra_dplane_result res
;
1263 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
1264 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
1267 zif
= zl3vni
->vxlan_if
->info
;
1271 br_ifp
= zif
->brslave_info
.br_if
;
1275 vni
= zebra_vxlan_if_vni_find(zif
, zl3vni
->vni
);
1277 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
1279 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
1280 vid
= vni
->access_vlan
;
1284 res
= dplane_rem_mac_add(zl3vni
->vxlan_if
, br_ifp
, vid
, &zrmac
->macaddr
,
1285 vni
->vni
, zrmac
->fwd_info
.r_vtep_ip
, 0, 0,
1286 false /*was_static*/);
1287 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
1294 * Uninstall remote RMAC from the forwarding plane.
1296 static int zl3vni_rmac_uninstall(struct zebra_l3vni
*zl3vni
,
1297 struct zebra_mac
*zrmac
)
1299 const struct zebra_if
*zif
= NULL
, *br_zif
;
1300 const struct zebra_vxlan_vni
*vni
;
1301 const struct interface
*br_ifp
;
1303 enum zebra_dplane_result res
;
1305 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
1306 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
1309 if (!zl3vni
->vxlan_if
) {
1310 if (IS_ZEBRA_DEBUG_VXLAN
)
1312 "RMAC %pEA on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
1313 &zrmac
->macaddr
, zl3vni
->vni
, zl3vni
);
1317 zif
= zl3vni
->vxlan_if
->info
;
1321 br_ifp
= zif
->brslave_info
.br_if
;
1325 vni
= zebra_vxlan_if_vni_find(zif
, zl3vni
->vni
);
1327 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
1328 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
1329 vid
= vni
->access_vlan
;
1333 res
= dplane_rem_mac_del(zl3vni
->vxlan_if
, br_ifp
, vid
, &zrmac
->macaddr
,
1334 vni
->vni
, zrmac
->fwd_info
.r_vtep_ip
);
1335 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
1341 /* handle rmac add */
1342 static int zl3vni_remote_rmac_add(struct zebra_l3vni
*zl3vni
,
1343 const struct ethaddr
*rmac
,
1344 const struct ipaddr
*vtep_ip
)
1346 struct zebra_mac
*zrmac
= NULL
;
1347 struct ipaddr
*vtep
= NULL
;
1349 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
1352 /* Create the RMAC entry, or update its vtep, if necessary. */
1353 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
1356 "Failed to add RMAC %pEA L3VNI %u Remote VTEP %pIA",
1357 rmac
, zl3vni
->vni
, vtep_ip
);
1360 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
1361 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
1363 vtep
= XCALLOC(MTYPE_EVPN_VTEP
, sizeof(struct ipaddr
));
1364 memcpy(vtep
, vtep_ip
, sizeof(struct ipaddr
));
1365 if (!listnode_add_sort_nodup(zrmac
->nh_list
, (void *)vtep
))
1366 XFREE(MTYPE_EVPN_VTEP
, vtep
);
1368 /* Send RMAC for FPM processing */
1369 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, false,
1372 /* install rmac in kernel */
1373 zl3vni_rmac_install(zl3vni
, zrmac
);
1374 } else if (!IPV4_ADDR_SAME(&zrmac
->fwd_info
.r_vtep_ip
,
1375 &vtep_ip
->ipaddr_v4
)) {
1376 if (IS_ZEBRA_DEBUG_VXLAN
)
1378 "L3VNI %u Remote VTEP change(%pI4 -> %pIA) for RMAC %pEA",
1379 zl3vni
->vni
, &zrmac
->fwd_info
.r_vtep_ip
,
1382 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
1384 vtep
= XCALLOC(MTYPE_EVPN_VTEP
, sizeof(struct ipaddr
));
1385 memcpy(vtep
, vtep_ip
, sizeof(struct ipaddr
));
1386 if (!listnode_add_sort_nodup(zrmac
->nh_list
, (void *)vtep
))
1387 XFREE(MTYPE_EVPN_VTEP
, vtep
);
1389 /* install rmac in kernel */
1390 zl3vni_rmac_install(zl3vni
, zrmac
);
1397 /* handle rmac delete */
1398 static void zl3vni_remote_rmac_del(struct zebra_l3vni
*zl3vni
,
1399 struct zebra_mac
*zrmac
,
1400 struct ipaddr
*vtep_ip
)
1402 struct ipaddr ipv4_vtep
;
1404 if (!zl3vni_nh_lookup(zl3vni
, vtep_ip
)) {
1405 memset(&ipv4_vtep
, 0, sizeof(ipv4_vtep
));
1406 ipv4_vtep
.ipa_type
= IPADDR_V4
;
1407 if (vtep_ip
->ipa_type
== IPADDR_V6
)
1408 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
1409 &ipv4_vtep
.ipaddr_v4
);
1411 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
1412 sizeof(struct in_addr
));
1414 /* remove nh from rmac's list */
1415 l3vni_rmac_nh_list_nh_delete(zl3vni
, zrmac
, &ipv4_vtep
);
1416 /* delete nh is same as current selected, fall back to
1417 * one present in the list
1419 if (IPV4_ADDR_SAME(&zrmac
->fwd_info
.r_vtep_ip
,
1420 &ipv4_vtep
.ipaddr_v4
) &&
1421 listcount(zrmac
->nh_list
)) {
1422 struct ipaddr
*vtep
;
1424 vtep
= listgetdata(listhead(zrmac
->nh_list
));
1425 zrmac
->fwd_info
.r_vtep_ip
= vtep
->ipaddr_v4
;
1426 if (IS_ZEBRA_DEBUG_VXLAN
)
1428 "L3VNI %u Remote VTEP nh change(%pIA -> %pI4) for RMAC %pEA",
1429 zl3vni
->vni
, &ipv4_vtep
,
1430 &zrmac
->fwd_info
.r_vtep_ip
,
1433 /* install rmac in kernel */
1434 zl3vni_rmac_install(zl3vni
, zrmac
);
1437 if (!listcount(zrmac
->nh_list
)) {
1438 /* uninstall from kernel */
1439 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
1441 /* Send RMAC for FPM processing */
1442 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true,
1445 if (IS_ZEBRA_DEBUG_VXLAN
)
1447 "L3VNI %u RMAC %pEA vtep_ip %pIA delete",
1448 zl3vni
->vni
, &zrmac
->macaddr
, vtep_ip
);
1450 /* del the rmac entry */
1451 zl3vni_rmac_del(zl3vni
, zrmac
);
1457 * Common code for look up of nh hash entry.
1459 static struct zebra_neigh
*_nh_lookup(struct zebra_l3vni
*zl3vni
,
1460 const struct ipaddr
*ip
)
1462 struct zebra_neigh tmp
;
1463 struct zebra_neigh
*n
;
1465 memset(&tmp
, 0, sizeof(tmp
));
1466 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
1469 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
1471 n
= hash_lookup(svd_nh_table
, &tmp
);
1477 * Look up nh hash entry on a l3-vni.
1479 static struct zebra_neigh
*zl3vni_nh_lookup(struct zebra_l3vni
*zl3vni
,
1480 const struct ipaddr
*ip
)
1482 return _nh_lookup(zl3vni
, ip
);
1486 * Look up nh hash entry on a SVD.
1488 static struct zebra_neigh
*svd_nh_lookup(const struct ipaddr
*ip
)
1490 return _nh_lookup(NULL
, ip
);
1494 * Callback to allocate NH hash entry on L3-VNI.
1496 static void *zl3vni_nh_alloc(void *p
)
1498 const struct zebra_neigh
*tmp_n
= p
;
1499 struct zebra_neigh
*n
;
1501 n
= XCALLOC(MTYPE_L3NEIGH
, sizeof(struct zebra_neigh
));
1508 * Common code for neigh add.
1510 static struct zebra_neigh
*_nh_add(struct zebra_l3vni
*zl3vni
,
1511 const struct ipaddr
*ip
,
1512 const struct ethaddr
*mac
)
1514 struct zebra_neigh tmp_n
;
1515 struct zebra_neigh
*n
= NULL
;
1517 memset(&tmp_n
, 0, sizeof(tmp_n
));
1518 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1521 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
1523 n
= hash_get(svd_nh_table
, &tmp_n
, zl3vni_nh_alloc
);
1527 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
1529 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1530 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
1531 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
1537 * Add neighbor entry.
1539 static struct zebra_neigh
*zl3vni_nh_add(struct zebra_l3vni
*zl3vni
,
1540 const struct ipaddr
*ip
,
1541 const struct ethaddr
*mac
)
1543 return _nh_add(zl3vni
, ip
, mac
);
1547 * Delete neighbor entry.
1549 static int zl3vni_nh_del(struct zebra_l3vni
*zl3vni
, struct zebra_neigh
*n
)
1551 struct zebra_neigh
*tmp_n
;
1552 struct host_rb_entry
*hle
;
1554 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
1555 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
1557 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
1558 XFREE(MTYPE_HOST_PREFIX
, hle
);
1561 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
1562 XFREE(MTYPE_L3NEIGH
, tmp_n
);
1568 * Add Single VXlan Device neighbor entry.
1570 static struct zebra_neigh
*svd_nh_add(const struct ipaddr
*ip
,
1571 const struct ethaddr
*mac
)
1573 return _nh_add(NULL
, ip
, mac
);
1577 * Del Single VXlan Device neighbor entry.
1579 static int svd_nh_del(struct zebra_neigh
*n
)
1584 hash_release(svd_nh_table
, n
);
1585 XFREE(MTYPE_L3NEIGH
, n
);
1591 * Common code to install remote nh as neigh into the kernel.
1593 static int _nh_install(struct zebra_l3vni
*zl3vni
, struct interface
*ifp
,
1594 struct zebra_neigh
*n
)
1599 if (zl3vni
&& !is_l3vni_oper_up(zl3vni
))
1602 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
1603 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
1606 flags
= DPLANE_NTF_EXT_LEARNED
;
1607 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
1608 flags
|= DPLANE_NTF_ROUTER
;
1610 dplane_rem_neigh_add(ifp
, &n
->ip
, &n
->emac
, flags
,
1611 false /*was_static*/);
1617 * Common code to uninstall remote nh from the kernel.
1619 static int _nh_uninstall(struct interface
*ifp
, struct zebra_neigh
*n
)
1621 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
1622 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
1625 if (!ifp
|| !if_is_operative(ifp
))
1628 dplane_rem_neigh_delete(ifp
, &n
->ip
);
1634 * Install remote nh as neigh into the kernel.
1636 static int zl3vni_nh_install(struct zebra_l3vni
*zl3vni
, struct zebra_neigh
*n
)
1638 return _nh_install(zl3vni
, zl3vni
->svi_if
, n
);
1642 * Uninstall remote nh from the kernel.
1644 static int zl3vni_nh_uninstall(struct zebra_l3vni
*zl3vni
,
1645 struct zebra_neigh
*n
)
1647 return _nh_uninstall(zl3vni
->svi_if
, n
);
1651 * Install SVD remote nh as neigh into the kernel.
1653 static int svd_nh_install(struct zebra_l3vni
*zl3vni
, struct zebra_neigh
*n
)
1655 return _nh_install(zl3vni
, zl3vni
->vxlan_if
, n
);
1659 * Uninstall SVD remote nh from the kernel.
1661 static int svd_nh_uninstall(struct zebra_l3vni
*zl3vni
, struct zebra_neigh
*n
)
1663 return _nh_uninstall(zl3vni
->vxlan_if
, n
);
1666 /* Add remote vtep as a neigh entry */
1667 static int zl3vni_remote_nh_add(struct zebra_l3vni
*zl3vni
,
1668 const struct ipaddr
*vtep_ip
,
1669 const struct ethaddr
*rmac
,
1670 const struct prefix
*host_prefix
)
1672 struct zebra_neigh
*nh
= NULL
;
1674 /* Create the next hop entry, or update its mac, if necessary. */
1675 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
1677 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
1680 "Failed to add NH %pIA as Neigh (RMAC %pEA L3-VNI %u prefix %pFX)",
1681 vtep_ip
, rmac
, zl3vni
->vni
, host_prefix
);
1685 /* install the nh neigh in kernel */
1686 zl3vni_nh_install(zl3vni
, nh
);
1687 } else if (memcmp(&nh
->emac
, rmac
, ETH_ALEN
) != 0) {
1688 if (IS_ZEBRA_DEBUG_VXLAN
)
1690 "L3VNI %u RMAC change(%pEA --> %pEA) for nexthop %pIA, prefix %pFX",
1691 zl3vni
->vni
, &nh
->emac
, rmac
, vtep_ip
,
1694 memcpy(&nh
->emac
, rmac
, ETH_ALEN
);
1695 /* install (update) the nh neigh in kernel */
1696 zl3vni_nh_install(zl3vni
, nh
);
1699 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
1704 /* Del remote vtep as a neigh entry */
1705 static void zl3vni_remote_nh_del(struct zebra_l3vni
*zl3vni
,
1706 struct zebra_neigh
*nh
,
1707 struct prefix
*host_prefix
)
1709 rb_delete_host(&nh
->host_rb
, host_prefix
);
1711 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
1712 /* uninstall from kernel */
1713 zl3vni_nh_uninstall(zl3vni
, nh
);
1715 /* delete the nh entry */
1716 zl3vni_nh_del(zl3vni
, nh
);
1720 /* Add remote vtep as a SVD neigh entry */
1721 static int svd_remote_nh_add(struct zebra_l3vni
*zl3vni
,
1722 const struct ipaddr
*vtep_ip
,
1723 const struct ethaddr
*rmac
,
1724 const struct prefix
*host_prefix
)
1726 struct zebra_neigh
*nh
= NULL
;
1728 /* SVD backed VNI check */
1729 if (!IS_ZL3VNI_SVD_BACKED(zl3vni
))
1732 /* Create the SVD next hop entry, or update its mac, if necessary. */
1733 nh
= svd_nh_lookup(vtep_ip
);
1735 nh
= svd_nh_add(vtep_ip
, rmac
);
1738 "Failed to add NH %pIA as SVD Neigh (RMAC %pEA prefix %pFX)",
1739 vtep_ip
, rmac
, host_prefix
);
1743 } else if (memcmp(&nh
->emac
, rmac
, ETH_ALEN
) != 0) {
1744 if (IS_ZEBRA_DEBUG_VXLAN
)
1746 "SVD RMAC change(%pEA --> %pEA) for nexthop %pIA, prefix %pFX",
1747 &nh
->emac
, rmac
, vtep_ip
, host_prefix
);
1749 memcpy(&nh
->emac
, rmac
, ETH_ALEN
);
1750 /* install (update) the nh neigh in kernel */
1751 svd_nh_install(zl3vni
, nh
);
1753 /* Don't increment refcnt change */
1759 if (IS_ZEBRA_DEBUG_VXLAN
)
1760 zlog_debug("SVD NH ADD refcnt (%u) for nexthop %pIA",
1761 nh
->refcnt
, vtep_ip
);
1764 * Install the nh neigh in kernel if this is the first time we
1767 if (nh
->refcnt
== 1)
1768 svd_nh_install(zl3vni
, nh
);
1773 /* Del remote vtep as a SVD neigh entry */
1774 static int svd_remote_nh_del(struct zebra_l3vni
*zl3vni
,
1775 const struct ipaddr
*vtep_ip
)
1777 struct zebra_neigh
*nh
;
1779 /* SVD backed VNI check */
1780 if (!IS_ZL3VNI_SVD_BACKED(zl3vni
))
1783 nh
= svd_nh_lookup(vtep_ip
);
1785 zlog_debug("Failed to del NH %pIA as SVD Neigh", vtep_ip
);
1792 if (IS_ZEBRA_DEBUG_VXLAN
)
1793 zlog_debug("SVD NH Del refcnt (%u) for nexthop %pIA",
1794 nh
->refcnt
, vtep_ip
);
1796 /* Last refcnt on NH, remove it completely. */
1797 if (nh
->refcnt
== 0) {
1798 svd_nh_uninstall(zl3vni
, nh
);
1805 /* handle neigh update from kernel - the only thing of interest is to
1806 * readd stale entries.
1808 static int zl3vni_local_nh_add_update(struct zebra_l3vni
*zl3vni
,
1809 struct ipaddr
*ip
, uint16_t state
)
1812 struct zebra_neigh
*n
= NULL
;
1814 n
= zl3vni_nh_lookup(zl3vni
, ip
);
1818 /* all next hop neigh are remote and installed by frr.
1819 * If the kernel has aged this entry, re-install.
1821 if (state
& NUD_STALE
)
1822 zl3vni_nh_install(zl3vni
, n
);
1827 /* handle neigh delete from kernel */
1828 static int zl3vni_local_nh_del(struct zebra_l3vni
*zl3vni
, struct ipaddr
*ip
)
1830 struct zebra_neigh
*n
= NULL
;
1832 n
= zl3vni_nh_lookup(zl3vni
, ip
);
1836 /* all next hop neigh are remote and installed by frr.
1837 * If we get an age out notification for these neigh entries, we have to
1840 zl3vni_nh_install(zl3vni
, n
);
1846 * Hash function for L3 VNI.
1848 static unsigned int l3vni_hash_keymake(const void *p
)
1850 const struct zebra_l3vni
*zl3vni
= p
;
1852 return jhash_1word(zl3vni
->vni
, 0);
1856 * Compare 2 L3 VNI hash entries.
1858 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
1860 const struct zebra_l3vni
*zl3vni1
= p1
;
1861 const struct zebra_l3vni
*zl3vni2
= p2
;
1863 return (zl3vni1
->vni
== zl3vni2
->vni
);
1867 * Callback to allocate L3 VNI hash entry.
1869 static void *zl3vni_alloc(void *p
)
1871 struct zebra_l3vni
*zl3vni
= NULL
;
1872 const struct zebra_l3vni
*tmp_l3vni
= p
;
1874 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(struct zebra_l3vni
));
1875 zl3vni
->vni
= tmp_l3vni
->vni
;
1876 return ((void *)zl3vni
);
1880 * Look up L3 VNI hash entry.
1882 struct zebra_l3vni
*zl3vni_lookup(vni_t vni
)
1884 struct zebra_l3vni tmp_l3vni
;
1885 struct zebra_l3vni
*zl3vni
= NULL
;
1887 memset(&tmp_l3vni
, 0, sizeof(tmp_l3vni
));
1888 tmp_l3vni
.vni
= vni
;
1889 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
1895 * Add L3 VNI hash entry.
1897 static struct zebra_l3vni
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
1899 struct zebra_l3vni tmp_zl3vni
;
1900 struct zebra_l3vni
*zl3vni
= NULL
;
1902 memset(&tmp_zl3vni
, 0, sizeof(tmp_zl3vni
));
1903 tmp_zl3vni
.vni
= vni
;
1905 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
1907 zl3vni
->vrf_id
= vrf_id
;
1908 zl3vni
->svi_if
= NULL
;
1909 zl3vni
->vxlan_if
= NULL
;
1910 zl3vni
->l2vnis
= list_new();
1911 zl3vni
->l2vnis
->cmp
= zebra_evpn_list_cmp
;
1913 /* Create hash table for remote RMAC */
1914 zl3vni
->rmac_table
= zebra_mac_db_create("Zebra L3-VNI RMAC-Table");
1916 /* Create hash table for neighbors */
1917 zl3vni
->nh_table
= zebra_neigh_db_create("Zebra L3-VNI next-hop table");
1923 * Delete L3 VNI hash entry.
1925 static int zl3vni_del(struct zebra_l3vni
*zl3vni
)
1927 struct zebra_l3vni
*tmp_zl3vni
;
1929 /* free the list of l2vnis */
1930 list_delete(&zl3vni
->l2vnis
);
1931 zl3vni
->l2vnis
= NULL
;
1933 /* Free the rmac table */
1934 hash_free(zl3vni
->rmac_table
);
1935 zl3vni
->rmac_table
= NULL
;
1937 /* Free the nh table */
1938 hash_free(zl3vni
->nh_table
);
1939 zl3vni
->nh_table
= NULL
;
1941 /* Free the VNI hash entry and allocated memory. */
1942 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
1943 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
1948 static int zl3vni_map_to_vxlan_if_ns(struct ns
*ns
,
1952 struct zebra_ns
*zns
= ns
->info
;
1953 struct zebra_l3vni
*zl3vni
= (struct zebra_l3vni
*)_zl3vni
;
1954 struct route_node
*rn
= NULL
;
1955 struct interface
*ifp
= NULL
;
1956 struct zebra_vrf
*zvrf
;
1958 zvrf
= zebra_vrf_get_evpn();
1962 /* loop through all vxlan-interface */
1963 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
1965 struct zebra_if
*zif
= NULL
;
1966 struct zebra_l2info_vxlan
*vxl
;
1967 struct zebra_vxlan_vni
*vni
= NULL
;
1969 ifp
= (struct interface
*)rn
->info
;
1974 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
1977 vxl
= &zif
->l2info
.vxl
;
1978 vni
= zebra_vxlan_if_vni_find(zif
, zl3vni
->vni
);
1979 if (!vni
|| vni
->vni
!= zl3vni
->vni
)
1982 /* link of VXLAN interface should be in zebra_evpn_vrf */
1983 if (zvrf
->zns
->ns_id
!= vxl
->link_nsid
) {
1984 if (IS_ZEBRA_DEBUG_VXLAN
)
1986 "Intf %s(%u) VNI %u, link not in same "
1987 "namespace than BGP EVPN core instance ",
1988 ifp
->name
, ifp
->ifindex
, vni
->vni
);
1993 zl3vni
->local_vtep_ip
= zif
->l2info
.vxl
.vtep_ip
;
1994 *_pifp
= (void *)ifp
;
1995 return NS_WALK_STOP
;
1998 return NS_WALK_CONTINUE
;
2001 struct interface
*zl3vni_map_to_vxlan_if(struct zebra_l3vni
*zl3vni
)
2003 struct interface
**p_ifp
;
2004 struct interface
*ifp
= NULL
;
2008 ns_walk_func(zl3vni_map_to_vxlan_if_ns
,
2009 (void *)zl3vni
, (void **)p_ifp
);
2013 struct interface
*zl3vni_map_to_svi_if(struct zebra_l3vni
*zl3vni
)
2015 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
2016 struct zebra_vxlan_vni
*vni
= NULL
; /* vni info in vxlan_if */
2021 if (!zl3vni
->vxlan_if
)
2024 zif
= zl3vni
->vxlan_if
->info
;
2028 vni
= zebra_vxlan_if_vni_find(zif
, zl3vni
->vni
);
2032 return zvni_map_to_svi(vni
->access_vlan
, zif
->brslave_info
.br_if
);
2035 struct interface
*zl3vni_map_to_mac_vlan_if(struct zebra_l3vni
*zl3vni
)
2037 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
2042 if (!zl3vni
->vxlan_if
)
2045 zif
= zl3vni
->vxlan_if
->info
;
2049 return zebra_evpn_map_to_macvlan(zif
->brslave_info
.br_if
,
2054 struct zebra_l3vni
*zl3vni_from_vrf(vrf_id_t vrf_id
)
2056 struct zebra_vrf
*zvrf
= NULL
;
2058 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
2062 return zl3vni_lookup(zvrf
->l3vni
);
2065 static int zl3vni_from_svi_ns(struct ns
*ns
, void *_in_param
, void **_p_zl3vni
)
2069 struct zebra_ns
*zns
= ns
->info
;
2070 struct zebra_l3vni
**p_zl3vni
= (struct zebra_l3vni
**)_p_zl3vni
;
2071 struct zebra_from_svi_param
*in_param
=
2072 (struct zebra_from_svi_param
*)_in_param
;
2073 struct route_node
*rn
= NULL
;
2074 struct interface
*tmp_if
= NULL
;
2075 struct zebra_if
*zif
= NULL
;
2076 struct zebra_if
*br_zif
= NULL
;
2078 assert(in_param
&& p_zl3vni
);
2080 br_zif
= in_param
->br_if
->info
;
2083 if (in_param
->bridge_vlan_aware
) {
2084 vni_id
= zebra_l2_bridge_if_vni_find(br_zif
, in_param
->vid
);
2088 /* loop through all vxlan-interface */
2089 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2090 tmp_if
= (struct interface
*)rn
->info
;
2094 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2096 if (!if_is_operative(tmp_if
))
2099 if (zif
->brslave_info
.br_if
!= in_param
->br_if
)
2102 vni_id
= zebra_vxlan_if_access_vlan_vni_find(
2103 zif
, in_param
->br_if
);
2112 return NS_WALK_CONTINUE
;
2114 *p_zl3vni
= zl3vni_lookup(vni_id
);
2115 return NS_WALK_STOP
;
2119 * Map SVI and associated bridge to a VNI. This is invoked upon getting
2120 * neighbor notifications, to see if they are of interest.
2122 static struct zebra_l3vni
*zl3vni_from_svi(struct interface
*ifp
,
2123 struct interface
*br_if
)
2125 struct zebra_l3vni
*zl3vni
= NULL
;
2126 struct zebra_if
*zif
= NULL
;
2127 struct zebra_from_svi_param in_param
= {};
2128 struct zebra_l3vni
**p_zl3vni
;
2133 /* Make sure the linked interface is a bridge. */
2134 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
2136 in_param
.br_if
= br_if
;
2138 /* Determine if bridge is VLAN-aware or not */
2141 in_param
.bridge_vlan_aware
= IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zif
);
2142 if (in_param
.bridge_vlan_aware
) {
2143 struct zebra_l2info_vlan
*vl
;
2145 if (!IS_ZEBRA_IF_VLAN(ifp
))
2150 vl
= &zif
->l2info
.vl
;
2151 in_param
.vid
= vl
->vid
;
2154 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
2155 /* TODO: Optimize with a hash. */
2159 ns_walk_func(zl3vni_from_svi_ns
, (void *)&in_param
, (void **)p_zl3vni
);
2163 vni_t
vni_id_from_svi(struct interface
*ifp
, struct interface
*br_if
)
2166 struct zebra_evpn
*zevpn
= NULL
;
2167 struct zebra_l3vni
*zl3vni
= NULL
;
2169 /* Check if an L3VNI belongs to this SVI interface.
2170 * If not, check if an L2VNI belongs to this SVI interface.
2172 zl3vni
= zl3vni_from_svi(ifp
, br_if
);
2176 zevpn
= zebra_evpn_from_svi(ifp
, br_if
);
2184 static inline void zl3vni_get_vrr_rmac(struct zebra_l3vni
*zl3vni
,
2185 struct ethaddr
*rmac
)
2190 if (!is_l3vni_oper_up(zl3vni
))
2193 if (zl3vni
->mac_vlan_if
&& if_is_operative(zl3vni
->mac_vlan_if
))
2194 memcpy(rmac
->octet
, zl3vni
->mac_vlan_if
->hw_addr
, ETH_ALEN
);
2198 * Inform BGP about l3-vni.
2200 static int zl3vni_send_add_to_client(struct zebra_l3vni
*zl3vni
)
2202 struct stream
*s
= NULL
;
2203 struct zserv
*client
= NULL
;
2204 struct ethaddr svi_rmac
, vrr_rmac
= {.octet
= {0} };
2205 struct zebra_vrf
*zvrf
;
2206 bool is_anycast_mac
= true;
2208 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2209 /* BGP may not be running. */
2213 zvrf
= zebra_vrf_lookup_by_id(zl3vni
->vrf_id
);
2216 /* get the svi and vrr rmac values */
2217 memset(&svi_rmac
, 0, sizeof(svi_rmac
));
2218 zl3vni_get_svi_rmac(zl3vni
, &svi_rmac
);
2219 zl3vni_get_vrr_rmac(zl3vni
, &vrr_rmac
);
2221 /* In absence of vrr mac use svi mac as anycast MAC value */
2222 if (is_zero_mac(&vrr_rmac
)) {
2223 memcpy(&vrr_rmac
, &svi_rmac
, ETH_ALEN
);
2224 is_anycast_mac
= false;
2227 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2229 /* The message is used for both vni add and/or update like
2230 * vrr mac is added for l3vni SVI.
2232 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
2233 stream_putl(s
, zl3vni
->vni
);
2234 stream_put(s
, &svi_rmac
, sizeof(struct ethaddr
));
2235 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
2236 stream_put(s
, &zl3vni
->filter
, sizeof(int));
2237 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
2238 stream_put(s
, &vrr_rmac
, sizeof(struct ethaddr
));
2239 stream_putl(s
, is_anycast_mac
);
2241 /* Write packet size. */
2242 stream_putw_at(s
, 0, stream_get_endp(s
));
2244 if (IS_ZEBRA_DEBUG_VXLAN
)
2246 "Send L3_VNI_ADD %u VRF %s RMAC %pEA VRR %pEA local-ip %pI4 filter %s to %s",
2247 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
2248 &svi_rmac
, &vrr_rmac
, &zl3vni
->local_vtep_ip
,
2249 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
2250 ? "prefix-routes-only"
2252 zebra_route_string(client
->proto
));
2254 client
->l3vniadd_cnt
++;
2255 return zserv_send_message(client
, s
);
2259 * Inform BGP about local l3-VNI deletion.
2261 static int zl3vni_send_del_to_client(struct zebra_l3vni
*zl3vni
)
2263 struct stream
*s
= NULL
;
2264 struct zserv
*client
= NULL
;
2266 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2267 /* BGP may not be running. */
2271 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2273 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
2274 stream_putl(s
, zl3vni
->vni
);
2276 /* Write packet size. */
2277 stream_putw_at(s
, 0, stream_get_endp(s
));
2279 if (IS_ZEBRA_DEBUG_VXLAN
)
2280 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
2281 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
2282 zebra_route_string(client
->proto
));
2284 client
->l3vnidel_cnt
++;
2285 return zserv_send_message(client
, s
);
2288 void zebra_vxlan_process_l3vni_oper_up(struct zebra_l3vni
*zl3vni
)
2293 /* send l3vni add to BGP */
2294 zl3vni_send_add_to_client(zl3vni
);
2297 void zebra_vxlan_process_l3vni_oper_down(struct zebra_l3vni
*zl3vni
)
2302 /* send l3-vni del to BGP*/
2303 zl3vni_send_del_to_client(zl3vni
);
2306 static void zevpn_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
2308 struct zebra_evpn
*zevpn
= (struct zebra_evpn
*)bucket
->data
;
2309 struct zebra_l3vni
*zl3vni
= (struct zebra_l3vni
*)ctxt
;
2311 if (zevpn
->vrf_id
== zl3vni_vrf_id(zl3vni
))
2312 listnode_add_sort(zl3vni
->l2vnis
, zevpn
);
2316 * Handle transition of vni from l2 to l3 and vice versa.
2317 * This function handles only the L2VNI add/delete part of
2318 * the above transition.
2319 * L3VNI add/delete is handled by the calling functions.
2321 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
2324 struct zebra_evpn
*zevpn
= NULL
;
2325 struct zebra_l3vni
*zl3vni
= NULL
;
2327 /* There is a possibility that VNI notification was already received
2328 * from kernel and we programmed it as L2-VNI
2329 * In such a case we need to delete this L2-VNI first, so
2330 * that it can be reprogrammed as L3-VNI in the system. It is also
2331 * possible that the vrf-vni mapping is removed from FRR while the vxlan
2332 * interface is still present in kernel. In this case to keep it
2333 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
2336 /* Locate hash entry */
2337 zevpn
= zebra_evpn_lookup(vni
);
2341 if (IS_ZEBRA_DEBUG_VXLAN
)
2342 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
2344 /* Delete EVPN from BGP. */
2345 zebra_evpn_send_del_to_client(zevpn
);
2347 zebra_evpn_neigh_del_all(zevpn
, 0, 0, DEL_ALL_NEIGH
);
2348 zebra_evpn_mac_del_all(zevpn
, 0, 0, DEL_ALL_MAC
);
2350 /* Free up all remote VTEPs, if any. */
2351 zebra_evpn_vtep_del_all(zevpn
, 1);
2353 zl3vni
= zl3vni_from_vrf(zevpn
->vrf_id
);
2355 listnode_delete(zl3vni
->l2vnis
, zevpn
);
2357 /* Delete the hash entry. */
2358 if (zebra_evpn_vxlan_del(zevpn
)) {
2359 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
2360 "Failed to del EVPN hash %p, VNI %u", zevpn
,
2365 struct zebra_ns
*zns
;
2366 struct route_node
*rn
;
2367 struct interface
*ifp
;
2368 struct zebra_if
*zif
;
2369 struct zebra_vxlan_vni
*vnip
;
2370 struct zebra_l2info_vxlan
*vxl
;
2371 struct interface
*vlan_if
;
2374 if (IS_ZEBRA_DEBUG_VXLAN
)
2375 zlog_debug("Adding L2-VNI %u - transition from L3-VNI",
2378 /* Find VxLAN interface for this VNI. */
2379 zns
= zebra_ns_lookup(NS_DEFAULT
);
2380 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
2381 ifp
= (struct interface
*)rn
->info
;
2385 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
2388 vxl
= &zif
->l2info
.vxl
;
2389 vnip
= zebra_vxlan_if_vni_find(zif
, vni
);
2397 if (IS_ZEBRA_DEBUG_VXLAN
)
2399 "Adding L2-VNI - Failed to find VxLAN interface for VNI %u",
2404 /* Create VNI hash entry for L2VNI */
2405 zevpn
= zebra_evpn_lookup(vni
);
2409 zevpn
= zebra_evpn_add(vni
);
2411 /* Find bridge interface for the VNI */
2412 vlan_if
= zvni_map_to_svi(vnip
->access_vlan
,
2413 zif
->brslave_info
.br_if
);
2415 zevpn
->vrf_id
= vlan_if
->vrf
->vrf_id
;
2416 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf
->vrf_id
);
2418 listnode_add_sort_nodup(zl3vni
->l2vnis
, zevpn
);
2421 zevpn
->vxlan_if
= ifp
;
2422 zevpn
->local_vtep_ip
= vxl
->vtep_ip
;
2424 /* Inform BGP if the VNI is up and mapped to a bridge. */
2425 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
) {
2426 zebra_evpn_send_add_to_client(zevpn
);
2427 zebra_evpn_read_mac_neigh(zevpn
, ifp
);
2434 /* delete and uninstall rmac hash entry */
2435 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
2437 struct zebra_mac
*zrmac
= NULL
;
2438 struct zebra_l3vni
*zl3vni
= NULL
;
2440 zrmac
= (struct zebra_mac
*)bucket
->data
;
2441 zl3vni
= (struct zebra_l3vni
*)ctx
;
2442 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
2444 /* Send RMAC for FPM processing */
2445 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true, "RMAC deleted");
2447 zl3vni_rmac_del(zl3vni
, zrmac
);
2450 /* delete and uninstall nh hash entry */
2451 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
2453 struct zebra_neigh
*n
= NULL
;
2454 struct zebra_l3vni
*zl3vni
= NULL
;
2456 n
= (struct zebra_neigh
*)bucket
->data
;
2457 zl3vni
= (struct zebra_l3vni
*)ctx
;
2458 zl3vni_nh_uninstall(zl3vni
, n
);
2459 zl3vni_nh_del(zl3vni
, n
);
2462 /* re-add remote rmac if needed */
2463 static int zebra_vxlan_readd_remote_rmac(struct zebra_l3vni
*zl3vni
,
2464 struct ethaddr
*rmac
)
2466 struct zebra_mac
*zrmac
= NULL
;
2468 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
2472 if (IS_ZEBRA_DEBUG_VXLAN
)
2473 zlog_debug("Del remote RMAC %pEA L3VNI %u - readd",
2476 zl3vni_rmac_install(zl3vni
, zrmac
);
2480 /* Public functions */
2482 int is_l3vni_for_prefix_routes_only(vni_t vni
)
2484 struct zebra_l3vni
*zl3vni
= NULL
;
2486 zl3vni
= zl3vni_lookup(vni
);
2490 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
2493 /* handle evpn route in vrf table */
2494 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, const struct ethaddr
*rmac
,
2495 const struct ipaddr
*vtep_ip
,
2496 const struct prefix
*host_prefix
)
2498 struct zebra_l3vni
*zl3vni
= NULL
;
2499 struct ipaddr ipv4_vtep
;
2501 zl3vni
= zl3vni_from_vrf(vrf_id
);
2502 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
2506 * add the next hop neighbor -
2507 * neigh to be installed is the ipv6 nexthop neigh
2509 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
2511 /* Add SVD next hop neighbor */
2512 svd_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
2515 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
2516 * address. Rmac is programmed against the ipv4 vtep because we only
2517 * support ipv4 tunnels in the h/w right now
2519 memset(&ipv4_vtep
, 0, sizeof(ipv4_vtep
));
2520 ipv4_vtep
.ipa_type
= IPADDR_V4
;
2521 if (vtep_ip
->ipa_type
== IPADDR_V6
)
2522 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
2523 &(ipv4_vtep
.ipaddr_v4
));
2525 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
2526 sizeof(struct in_addr
));
2529 * add the rmac - remote rmac to be installed is against the ipv4
2532 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
);
2535 /* handle evpn vrf route delete */
2536 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
2537 struct ipaddr
*vtep_ip
,
2538 struct prefix
*host_prefix
)
2540 struct zebra_l3vni
*zl3vni
= NULL
;
2541 struct zebra_neigh
*nh
= NULL
;
2542 struct zebra_mac
*zrmac
= NULL
;
2544 zl3vni
= zl3vni_from_vrf(vrf_id
);
2548 /* find the next hop entry and rmac entry */
2549 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
2552 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
2554 /* delete the next hop entry */
2555 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
2557 /* Delete SVD next hop entry */
2558 svd_remote_nh_del(zl3vni
, vtep_ip
);
2560 /* delete the rmac entry */
2562 zl3vni_remote_rmac_del(zl3vni
, zrmac
, vtep_ip
);
2565 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
2566 struct ethaddr
*rmac
, bool use_json
)
2568 struct zebra_l3vni
*zl3vni
= NULL
;
2569 struct zebra_mac
*zrmac
= NULL
;
2570 json_object
*json
= NULL
;
2572 if (!is_evpn_enabled()) {
2574 vty_out(vty
, "{}\n");
2579 json
= json_object_new_object();
2581 zl3vni
= zl3vni_lookup(l3vni
);
2584 vty_out(vty
, "{}\n");
2586 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
2590 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
2593 vty_out(vty
, "{}\n");
2596 "%% Requested RMAC doesn't exist in L3-VNI %u\n",
2601 zl3vni_print_rmac(zrmac
, vty
, json
);
2604 vty_json(vty
, json
);
2607 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
2609 struct zebra_l3vni
*zl3vni
;
2611 struct rmac_walk_ctx wctx
;
2612 json_object
*json
= NULL
;
2614 if (!is_evpn_enabled())
2617 zl3vni
= zl3vni_lookup(l3vni
);
2620 vty_out(vty
, "{}\n");
2622 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
2625 num_rmacs
= hashcount(zl3vni
->rmac_table
);
2630 json
= json_object_new_object();
2632 memset(&wctx
, 0, sizeof(wctx
));
2636 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
2638 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
2640 json_object_int_add(json
, "numRmacs", num_rmacs
);
2642 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
2645 vty_json(vty
, json
);
2648 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
2650 json_object
*json
= NULL
;
2653 if (!is_evpn_enabled()) {
2655 vty_out(vty
, "{}\n");
2660 json
= json_object_new_object();
2664 hash_iterate(zrouter
.l3vni_table
,
2665 (void (*)(struct hash_bucket
*,
2666 void *))zl3vni_print_rmac_hash_all_vni
,
2670 vty_json(vty
, json
);
2673 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
2674 struct ipaddr
*ip
, bool use_json
)
2676 struct zebra_l3vni
*zl3vni
= NULL
;
2677 struct zebra_neigh
*n
= NULL
;
2678 json_object
*json
= NULL
;
2680 if (!is_evpn_enabled()) {
2682 vty_out(vty
, "{}\n");
2687 json
= json_object_new_object();
2689 zl3vni
= zl3vni_lookup(l3vni
);
2692 vty_out(vty
, "{}\n");
2694 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
2698 n
= zl3vni_nh_lookup(zl3vni
, ip
);
2701 vty_out(vty
, "{}\n");
2704 "%% Requested next-hop not present for L3-VNI %u",
2709 zl3vni_print_nh(n
, vty
, json
);
2712 vty_json(vty
, json
);
2715 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
2718 struct nh_walk_ctx wctx
;
2719 json_object
*json
= NULL
;
2720 struct zebra_l3vni
*zl3vni
= NULL
;
2722 if (!is_evpn_enabled())
2725 zl3vni
= zl3vni_lookup(l3vni
);
2728 vty_out(vty
, "{}\n");
2730 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
2734 num_nh
= hashcount(zl3vni
->nh_table
);
2739 json
= json_object_new_object();
2744 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
2746 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
2748 json_object_int_add(json
, "numNextHops", num_nh
);
2750 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
2753 vty_json(vty
, json
);
2756 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
2758 json_object
*json
= NULL
;
2761 if (!is_evpn_enabled()) {
2763 vty_out(vty
, "{}\n");
2768 json
= json_object_new_object();
2772 hash_iterate(zrouter
.l3vni_table
,
2773 (void (*)(struct hash_bucket
*,
2774 void *))zl3vni_print_nh_hash_all_vni
,
2778 vty_json(vty
, json
);
2782 * Display L3 VNI information (VTY command handler).
2784 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
2787 json_object
*json
= NULL
;
2788 struct zebra_l3vni
*zl3vni
= NULL
;
2790 if (!is_evpn_enabled()) {
2792 vty_out(vty
, "{}\n");
2796 zl3vni
= zl3vni_lookup(vni
);
2799 vty_out(vty
, "{}\n");
2801 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2806 json
= json_object_new_object();
2810 zl3vni_print(zl3vni
, (void *)args
);
2813 vty_json(vty
, json
);
2816 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2817 json_object
*json_vrfs
)
2819 char buf
[ETHER_ADDR_STRLEN
];
2820 struct zebra_l3vni
*zl3vni
= NULL
;
2822 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
2827 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
2828 zvrf_name(zvrf
), zl3vni
->vni
,
2829 zl3vni_vxlan_if_name(zl3vni
),
2830 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
2831 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
2833 json_object
*json_vrf
= NULL
;
2835 json_vrf
= json_object_new_object();
2836 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
2837 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
2838 json_object_string_add(json_vrf
, "vxlanIntf",
2839 zl3vni_vxlan_if_name(zl3vni
));
2840 json_object_string_add(json_vrf
, "sviIntf",
2841 zl3vni_svi_if_name(zl3vni
));
2842 json_object_string_add(json_vrf
, "state",
2843 zl3vni_state2str(zl3vni
));
2844 json_object_string_add(
2845 json_vrf
, "routerMac",
2846 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
2847 json_object_array_add(json_vrfs
, json_vrf
);
2852 * Display Neighbors for a VNI (VTY command handler).
2854 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2855 vni_t vni
, bool use_json
)
2857 struct zebra_evpn
*zevpn
;
2859 struct neigh_walk_ctx wctx
;
2860 json_object
*json
= NULL
;
2862 if (!is_evpn_enabled())
2864 zevpn
= zebra_evpn_lookup(vni
);
2867 vty_out(vty
, "{}\n");
2869 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2872 num_neigh
= hashcount(zevpn
->neigh_table
);
2877 json
= json_object_new_object();
2879 /* Since we have IPv6 addresses to deal with which can vary widely in
2880 * size, we try to be a bit more elegant in display by first computing
2881 * the maximum width.
2883 memset(&wctx
, 0, sizeof(wctx
));
2886 wctx
.addr_width
= 15;
2888 hash_iterate(zevpn
->neigh_table
, zebra_evpn_find_neigh_addr_width
,
2893 "Number of ARPs (local and remote) known for this VNI: %u\n",
2895 zebra_evpn_print_neigh_hdr(vty
, &wctx
);
2897 json_object_int_add(json
, "numArpNd", num_neigh
);
2899 hash_iterate(zevpn
->neigh_table
, zebra_evpn_print_neigh_hash
, &wctx
);
2901 vty_json(vty
, json
);
2905 * Display neighbors across all VNIs (VTY command handler).
2907 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2908 bool print_dup
, bool use_json
)
2910 json_object
*json
= NULL
;
2913 if (!is_evpn_enabled())
2917 json
= json_object_new_object();
2921 args
[2] = (void *)(ptrdiff_t)print_dup
;
2923 hash_iterate(zvrf
->evpn_table
,
2924 (void (*)(struct hash_bucket
*,
2925 void *))zevpn_print_neigh_hash_all_evpn
,
2928 vty_json(vty
, json
);
2932 * Display neighbors across all VNIs in detail(VTY command handler).
2934 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
2935 struct zebra_vrf
*zvrf
,
2936 bool print_dup
, bool use_json
)
2938 json_object
*json
= NULL
;
2941 if (!is_evpn_enabled())
2945 json
= json_object_new_object();
2949 args
[2] = (void *)(ptrdiff_t)print_dup
;
2951 hash_iterate(zvrf
->evpn_table
,
2952 (void (*)(struct hash_bucket
*,
2953 void *))zevpn_print_neigh_hash_all_evpn_detail
,
2956 vty_json(vty
, json
);
2960 * Display specific neighbor for a VNI, if present (VTY command handler).
2962 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
2963 struct zebra_vrf
*zvrf
, vni_t vni
,
2964 struct ipaddr
*ip
, bool use_json
)
2966 struct zebra_evpn
*zevpn
;
2967 struct zebra_neigh
*n
;
2968 json_object
*json
= NULL
;
2970 if (!is_evpn_enabled())
2972 zevpn
= zebra_evpn_lookup(vni
);
2975 vty_out(vty
, "{}\n");
2977 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2980 n
= zebra_evpn_neigh_lookup(zevpn
, ip
);
2984 "%% Requested neighbor does not exist in VNI %u\n",
2989 json
= json_object_new_object();
2991 zebra_evpn_print_neigh(n
, vty
, json
);
2994 vty_json(vty
, json
);
2998 * Display neighbors for a VNI from specific VTEP (VTY command handler).
2999 * By definition, these are remote neighbors.
3001 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
3002 vni_t vni
, struct in_addr vtep_ip
,
3005 struct zebra_evpn
*zevpn
;
3007 struct neigh_walk_ctx wctx
;
3008 json_object
*json
= NULL
;
3010 if (!is_evpn_enabled())
3012 zevpn
= zebra_evpn_lookup(vni
);
3015 vty_out(vty
, "{}\n");
3017 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
3020 num_neigh
= hashcount(zevpn
->neigh_table
);
3025 json
= json_object_new_object();
3027 memset(&wctx
, 0, sizeof(wctx
));
3030 wctx
.addr_width
= 15;
3031 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
3032 wctx
.r_vtep_ip
= vtep_ip
;
3034 hash_iterate(zevpn
->neigh_table
, zebra_evpn_find_neigh_addr_width
,
3036 hash_iterate(zevpn
->neigh_table
, zebra_evpn_print_neigh_hash
, &wctx
);
3039 vty_json(vty
, json
);
3043 * Display Duplicate detected Neighbors for a VNI
3044 * (VTY command handler).
3046 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
3047 struct zebra_vrf
*zvrf
,
3051 struct zebra_evpn
*zevpn
;
3053 struct neigh_walk_ctx wctx
;
3054 json_object
*json
= NULL
;
3056 if (!is_evpn_enabled())
3059 zevpn
= zebra_evpn_lookup(vni
);
3061 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
3065 num_neigh
= hashcount(zevpn
->neigh_table
);
3069 num_neigh
= num_dup_detected_neighs(zevpn
);
3074 json
= json_object_new_object();
3076 /* Since we have IPv6 addresses to deal with which can vary widely in
3077 * size, we try to be a bit more elegant in display by first computing
3078 * the maximum width.
3080 memset(&wctx
, 0, sizeof(wctx
));
3083 wctx
.addr_width
= 15;
3085 hash_iterate(zevpn
->neigh_table
, zebra_evpn_find_neigh_addr_width
,
3090 "Number of ARPs (local and remote) known for this VNI: %u\n",
3092 vty_out(vty
, "%*s %-6s %-8s %-17s %-30s\n",
3093 -wctx
.addr_width
, "IP", "Type",
3094 "State", "MAC", "Remote ES/VTEP");
3096 json_object_int_add(json
, "numArpNd", num_neigh
);
3098 hash_iterate(zevpn
->neigh_table
, zebra_evpn_print_dad_neigh_hash
,
3102 vty_json(vty
, json
);
3106 * Display MACs for a VNI (VTY command handler).
3108 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
3109 vni_t vni
, bool use_json
, bool detail
)
3111 struct zebra_evpn
*zevpn
;
3113 struct mac_walk_ctx wctx
;
3114 json_object
*json
= NULL
;
3115 json_object
*json_mac
= NULL
;
3117 if (!is_evpn_enabled())
3119 zevpn
= zebra_evpn_lookup(vni
);
3122 vty_out(vty
, "{}\n");
3124 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
3127 num_macs
= num_valid_macs(zevpn
);
3132 json
= json_object_new_object();
3133 json_mac
= json_object_new_object();
3136 memset(&wctx
, 0, sizeof(wctx
));
3139 wctx
.json
= json_mac
;
3143 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
3144 zevpn
->vni
, num_macs
);
3147 "Number of MACs (local and remote) known for this VNI: %u\n",
3150 "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
3151 vty_out(vty
, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC",
3152 "Type", "Flags", "Intf/Remote ES/VTEP", "VLAN",
3156 json_object_int_add(json
, "numMacs", num_macs
);
3159 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_mac_hash_detail
,
3162 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_mac_hash
,
3166 json_object_object_add(json
, "macs", json_mac
);
3167 vty_json(vty
, json
);
3172 * Display MACs for all VNIs (VTY command handler).
3174 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
3175 bool print_dup
, bool use_json
)
3177 struct mac_walk_ctx wctx
;
3178 json_object
*json
= NULL
;
3180 if (!is_evpn_enabled()) {
3182 vty_out(vty
, "{}\n");
3186 json
= json_object_new_object();
3188 memset(&wctx
, 0, sizeof(wctx
));
3191 wctx
.print_dup
= print_dup
;
3192 hash_iterate(zvrf
->evpn_table
, zevpn_print_mac_hash_all_evpn
, &wctx
);
3195 vty_json(vty
, json
);
3199 * Display MACs in detail for all VNIs (VTY command handler).
3201 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
3202 struct zebra_vrf
*zvrf
,
3203 bool print_dup
, bool use_json
)
3205 struct mac_walk_ctx wctx
;
3206 json_object
*json
= NULL
;
3208 if (!is_evpn_enabled()) {
3210 vty_out(vty
, "{}\n");
3214 json
= json_object_new_object();
3216 memset(&wctx
, 0, sizeof(wctx
));
3219 wctx
.print_dup
= print_dup
;
3220 hash_iterate(zvrf
->evpn_table
, zevpn_print_mac_hash_all_evpn_detail
,
3224 vty_json(vty
, json
);
3228 * Display MACs for all VNIs (VTY command handler).
3230 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
3231 struct zebra_vrf
*zvrf
,
3232 struct in_addr vtep_ip
, bool use_json
)
3234 struct mac_walk_ctx wctx
;
3235 json_object
*json
= NULL
;
3237 if (!is_evpn_enabled())
3241 json
= json_object_new_object();
3243 memset(&wctx
, 0, sizeof(wctx
));
3245 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
3246 wctx
.r_vtep_ip
= vtep_ip
;
3248 hash_iterate(zvrf
->evpn_table
, zevpn_print_mac_hash_all_evpn
, &wctx
);
3251 vty_json(vty
, json
);
3255 * Display specific MAC for a VNI, if present (VTY command handler).
3257 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
3258 vni_t vni
, struct ethaddr
*macaddr
,
3261 struct zebra_evpn
*zevpn
;
3262 struct zebra_mac
*mac
;
3263 json_object
*json
= NULL
;
3265 if (!is_evpn_enabled())
3268 zevpn
= zebra_evpn_lookup(vni
);
3271 vty_out(vty
, "{}\n");
3273 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
3276 mac
= zebra_evpn_mac_lookup(zevpn
, macaddr
);
3279 vty_out(vty
, "{}\n");
3282 "%% Requested MAC does not exist in VNI %u\n",
3288 json
= json_object_new_object();
3290 zebra_evpn_print_mac(mac
, vty
, json
);
3292 vty_json(vty
, json
);
3295 /* Print Duplicate MACs per VNI */
3296 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
3297 struct zebra_vrf
*zvrf
,
3298 vni_t vni
, bool use_json
)
3300 struct zebra_evpn
*zevpn
;
3301 struct mac_walk_ctx wctx
;
3303 json_object
*json
= NULL
;
3304 json_object
*json_mac
= NULL
;
3306 if (!is_evpn_enabled())
3309 zevpn
= zebra_evpn_lookup(vni
);
3311 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
3315 num_macs
= num_valid_macs(zevpn
);
3319 num_macs
= num_dup_detected_macs(zevpn
);
3324 json
= json_object_new_object();
3325 json_mac
= json_object_new_object();
3328 memset(&wctx
, 0, sizeof(wctx
));
3331 wctx
.json
= json_mac
;
3335 "Number of MACs (local and remote) known for this VNI: %u\n",
3337 vty_out(vty
, "%-17s %-6s %-5s %-30s %-5s\n", "MAC", "Type",
3338 "Flags", "Intf/Remote ES/VTEP", "VLAN");
3340 json_object_int_add(json
, "numMacs", num_macs
);
3342 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_dad_mac_hash
, &wctx
);
3345 json_object_object_add(json
, "macs", json_mac
);
3346 vty_json(vty
, json
);
3351 int zebra_vxlan_clear_dup_detect_vni_mac(struct zebra_vrf
*zvrf
, vni_t vni
,
3352 struct ethaddr
*macaddr
, char *errmsg
,
3355 struct zebra_evpn
*zevpn
;
3356 struct zebra_mac
*mac
;
3357 struct listnode
*node
= NULL
;
3358 struct zebra_neigh
*nbr
= NULL
;
3360 if (!is_evpn_enabled())
3363 zevpn
= zebra_evpn_lookup(vni
);
3365 snprintfrr(errmsg
, errmsg_len
, "VNI %u does not exist", vni
);
3369 mac
= zebra_evpn_mac_lookup(zevpn
, macaddr
);
3371 snprintf(errmsg
, errmsg_len
,
3372 "Requested MAC does not exist in VNI %u\n", vni
);
3376 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
3377 snprintfrr(errmsg
, errmsg_len
,
3378 "Requested MAC is not duplicate detected\n");
3382 /* Remove all IPs as duplicate associcated with this MAC */
3383 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
3384 /* For local neigh mark inactive so MACIP update is generated
3385 * to BGP. This is a scenario where MAC update received
3386 * and detected as duplicate which marked neigh as duplicate.
3387 * Later local neigh update did not get a chance to relay
3388 * to BGP. Similarly remote macip update, neigh needs to be
3389 * installed locally.
3391 if (zvrf
->dad_freeze
&&
3392 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
3393 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
3394 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
3395 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
3396 zebra_evpn_rem_neigh_install(
3397 zevpn
, nbr
, false /*was_static*/);
3400 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
3402 nbr
->detect_start_time
.tv_sec
= 0;
3403 nbr
->dad_dup_detect_time
= 0;
3406 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
3408 mac
->detect_start_time
.tv_sec
= 0;
3409 mac
->detect_start_time
.tv_usec
= 0;
3410 mac
->dad_dup_detect_time
= 0;
3411 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3413 /* warn-only action return */
3414 if (!zvrf
->dad_freeze
)
3417 /* Local: Notify Peer VTEPs, Remote: Install the entry */
3418 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
3420 if (zebra_evpn_mac_send_add_to_client(zevpn
->vni
, &mac
->macaddr
,
3421 mac
->flags
, mac
->loc_seq
,
3425 /* Process all neighbors associated with this MAC. */
3426 zebra_evpn_process_neigh_on_local_mac_change(zevpn
, mac
, 0,
3429 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
3430 zebra_evpn_process_neigh_on_remote_mac_add(zevpn
, mac
);
3432 /* Install the entry. */
3433 zebra_evpn_rem_mac_install(zevpn
, mac
, false /* was_static */);
3439 int zebra_vxlan_clear_dup_detect_vni_ip(struct zebra_vrf
*zvrf
, vni_t vni
,
3440 struct ipaddr
*ip
, char *errmsg
,
3443 struct zebra_evpn
*zevpn
;
3444 struct zebra_neigh
*nbr
;
3445 struct zebra_mac
*mac
;
3446 char buf
[INET6_ADDRSTRLEN
];
3447 char buf2
[ETHER_ADDR_STRLEN
];
3449 if (!is_evpn_enabled())
3452 zevpn
= zebra_evpn_lookup(vni
);
3454 snprintfrr(errmsg
, errmsg_len
, "VNI %u does not exist\n", vni
);
3458 nbr
= zebra_evpn_neigh_lookup(zevpn
, ip
);
3460 snprintfrr(errmsg
, errmsg_len
,
3461 "Requested host IP does not exist in VNI %u\n", vni
);
3465 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
3467 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
3468 snprintfrr(errmsg
, errmsg_len
,
3469 "Requested host IP %s is not duplicate detected\n",
3474 mac
= zebra_evpn_mac_lookup(zevpn
, &nbr
->emac
);
3476 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
3479 "Requested IP's associated MAC %s is still in duplicate state\n",
3480 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
3484 if (IS_ZEBRA_DEBUG_VXLAN
)
3485 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
3486 __func__
, buf
, nbr
->flags
, nbr
->loc_seq
);
3488 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
3490 nbr
->detect_start_time
.tv_sec
= 0;
3491 nbr
->detect_start_time
.tv_usec
= 0;
3492 nbr
->dad_dup_detect_time
= 0;
3493 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
3495 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3496 zebra_evpn_neigh_send_add_to_client(zevpn
->vni
, ip
, &nbr
->emac
,
3497 nbr
->mac
, nbr
->flags
,
3499 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3500 zebra_evpn_rem_neigh_install(zevpn
, nbr
, false /*was_static*/);
3506 static void zevpn_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3508 struct mac_walk_ctx
*wctx
= ctxt
;
3509 struct zebra_mac
*mac
;
3510 struct zebra_evpn
*zevpn
;
3511 struct listnode
*node
= NULL
;
3512 struct zebra_neigh
*nbr
= NULL
;
3514 mac
= (struct zebra_mac
*)bucket
->data
;
3518 zevpn
= wctx
->zevpn
;
3520 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
3523 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
3525 mac
->detect_start_time
.tv_sec
= 0;
3526 mac
->detect_start_time
.tv_usec
= 0;
3527 mac
->dad_dup_detect_time
= 0;
3528 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3530 /* Remove all IPs as duplicate associcated with this MAC */
3531 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
3532 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
3534 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
3536 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
3538 nbr
->detect_start_time
.tv_sec
= 0;
3539 nbr
->dad_dup_detect_time
= 0;
3542 /* Local: Notify Peer VTEPs, Remote: Install the entry */
3543 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
3545 if (zebra_evpn_mac_send_add_to_client(zevpn
->vni
, &mac
->macaddr
,
3546 mac
->flags
, mac
->loc_seq
,
3550 /* Process all neighbors associated with this MAC. */
3551 zebra_evpn_process_neigh_on_local_mac_change(zevpn
, mac
, 0,
3554 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
3555 zebra_evpn_process_neigh_on_remote_mac_add(zevpn
, mac
);
3557 /* Install the entry. */
3558 zebra_evpn_rem_mac_install(zevpn
, mac
, false /* was_static */);
3562 static void zevpn_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
3565 struct zebra_evpn
*zevpn
;
3566 struct zebra_vrf
*zvrf
;
3567 struct mac_walk_ctx m_wctx
;
3568 struct neigh_walk_ctx n_wctx
;
3570 zevpn
= (struct zebra_evpn
*)bucket
->data
;
3574 zvrf
= (struct zebra_vrf
*)args
[0];
3576 if (hashcount(zevpn
->neigh_table
)) {
3577 memset(&n_wctx
, 0, sizeof(n_wctx
));
3578 n_wctx
.zevpn
= zevpn
;
3580 hash_iterate(zevpn
->neigh_table
,
3581 zebra_evpn_clear_dup_neigh_hash
, &n_wctx
);
3584 if (num_valid_macs(zevpn
)) {
3585 memset(&m_wctx
, 0, sizeof(m_wctx
));
3586 m_wctx
.zevpn
= zevpn
;
3588 hash_iterate(zevpn
->mac_table
, zevpn_clear_dup_mac_hash
, &m_wctx
);
3593 int zebra_vxlan_clear_dup_detect_vni_all(struct zebra_vrf
*zvrf
)
3597 if (!is_evpn_enabled())
3602 hash_iterate(zvrf
->evpn_table
,
3603 (void (*)(struct hash_bucket
*, void *))
3604 zevpn_clear_dup_detect_hash_vni_all
, args
);
3609 int zebra_vxlan_clear_dup_detect_vni(struct zebra_vrf
*zvrf
, vni_t vni
)
3611 struct zebra_evpn
*zevpn
;
3612 struct mac_walk_ctx m_wctx
;
3613 struct neigh_walk_ctx n_wctx
;
3615 if (!is_evpn_enabled())
3618 zevpn
= zebra_evpn_lookup(vni
);
3620 zlog_warn("VNI %u does not exist", vni
);
3624 if (hashcount(zevpn
->neigh_table
)) {
3625 memset(&n_wctx
, 0, sizeof(n_wctx
));
3626 n_wctx
.zevpn
= zevpn
;
3628 hash_iterate(zevpn
->neigh_table
,
3629 zebra_evpn_clear_dup_neigh_hash
, &n_wctx
);
3632 if (num_valid_macs(zevpn
)) {
3633 memset(&m_wctx
, 0, sizeof(m_wctx
));
3634 m_wctx
.zevpn
= zevpn
;
3636 hash_iterate(zevpn
->mac_table
, zevpn_clear_dup_mac_hash
, &m_wctx
);
3643 * Display MACs for a VNI from specific VTEP (VTY command handler).
3645 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
3646 vni_t vni
, struct in_addr vtep_ip
,
3649 struct zebra_evpn
*zevpn
;
3651 struct mac_walk_ctx wctx
;
3652 json_object
*json
= NULL
;
3653 json_object
*json_mac
= NULL
;
3655 if (!is_evpn_enabled())
3657 zevpn
= zebra_evpn_lookup(vni
);
3660 vty_out(vty
, "{}\n");
3662 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
3665 num_macs
= num_valid_macs(zevpn
);
3670 json
= json_object_new_object();
3671 json_mac
= json_object_new_object();
3674 memset(&wctx
, 0, sizeof(wctx
));
3677 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
3678 wctx
.r_vtep_ip
= vtep_ip
;
3679 wctx
.json
= json_mac
;
3680 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_mac_hash
, &wctx
);
3683 json_object_int_add(json
, "numMacs", wctx
.count
);
3685 json_object_object_add(json
, "macs", json_mac
);
3686 vty_json(vty
, json
);
3692 * Display VNI information (VTY command handler).
3694 * use_json flag indicates that output should be in JSON format.
3695 * json_array is non NULL when JSON output needs to be aggregated (by the
3696 * caller) and then printed, otherwise, JSON evpn vni info is printed
3699 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
3700 bool use_json
, json_object
*json_array
)
3702 json_object
*json
= NULL
;
3704 struct zebra_l3vni
*zl3vni
= NULL
;
3705 struct zebra_evpn
*zevpn
= NULL
;
3707 if (!is_evpn_enabled())
3711 json
= json_object_new_object();
3716 zl3vni
= zl3vni_lookup(vni
);
3718 zl3vni_print(zl3vni
, (void *)args
);
3720 zevpn
= zebra_evpn_lookup(vni
);
3722 zebra_evpn_print(zevpn
, (void *)args
);
3724 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
3729 * Each "json" object contains info about 1 VNI.
3730 * When "json_array" is non-null, we aggreggate the json output
3731 * into json_array and print it as a JSON array.
3734 json_object_array_add(json_array
, json
);
3736 vty_json(vty
, json
);
3740 /* Display all global details for EVPN */
3741 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
3746 json_object
*json
= NULL
;
3747 struct zebra_vrf
*zvrf
= NULL
;
3749 if (!is_evpn_enabled())
3752 zvrf
= zebra_vrf_get_evpn();
3754 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
3755 num_l2vnis
= hashcount(zvrf
->evpn_table
);
3756 num_vnis
= num_l2vnis
+ num_l3vnis
;
3759 json
= json_object_new_object();
3760 json_object_string_add(json
, "advertiseGatewayMacip",
3761 zvrf
->advertise_gw_macip
? "Yes" : "No");
3762 json_object_string_add(json
, "advertiseSviMacip",
3763 zvrf
->advertise_svi_macip
? "Yes"
3765 json_object_string_add(json
, "advertiseSviMac",
3766 zebra_evpn_mh_do_adv_svi_mac() ? "Yes"
3768 json_object_int_add(json
, "numVnis", num_vnis
);
3769 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3770 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3771 if (zebra_evpn_do_dup_addr_detect(zvrf
))
3772 json_object_boolean_true_add(json
,
3773 "isDuplicateAddrDetection");
3775 json_object_boolean_false_add(json
,
3776 "isDuplicateAddrDetection");
3777 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
3778 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
3779 json_object_int_add(json
, "detectionFreezeTime",
3780 zvrf
->dad_freeze_time
);
3781 zebra_evpn_mh_json(json
);
3783 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
3784 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
3785 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
3786 zvrf
->advertise_gw_macip
? "Yes" : "No");
3787 vty_out(vty
, "Advertise svi mac-ip: %s\n",
3788 zvrf
->advertise_svi_macip
? "Yes" : "No");
3789 vty_out(vty
, "Advertise svi mac: %s\n",
3790 zebra_evpn_mh_do_adv_svi_mac() ? "Yes" : "No");
3791 vty_out(vty
, "Duplicate address detection: %s\n",
3792 zebra_evpn_do_dup_addr_detect(zvrf
) ? "Enable"
3794 vty_out(vty
, " Detection max-moves %u, time %d\n",
3795 zvrf
->dad_max_moves
, zvrf
->dad_time
);
3796 if (zvrf
->dad_freeze
) {
3797 if (zvrf
->dad_freeze_time
)
3798 vty_out(vty
, " Detection freeze %u\n",
3799 zvrf
->dad_freeze_time
);
3801 vty_out(vty
, " Detection freeze %s\n",
3804 zebra_evpn_mh_print(vty
);
3808 vty_json(vty
, json
);
3812 * Display VNI hash table (VTY command handler).
3814 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
3817 json_object
*json
= NULL
;
3820 if (!is_evpn_enabled())
3824 json
= json_object_new_object();
3826 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
3827 "Type", "VxLAN IF", "# MACs", "# ARPs",
3828 "# Remote VTEPs", "Tenant VRF");
3833 /* Display all L2-VNIs */
3836 (void (*)(struct hash_bucket
*, void *))zebra_evpn_print_hash
,
3839 /* Display all L3-VNIs */
3840 hash_iterate(zrouter
.l3vni_table
,
3841 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
3845 vty_json(vty
, json
);
3848 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
3852 uint32_t max_moves
= 0;
3853 uint32_t freeze_time
= 0;
3854 bool dup_addr_detect
= false;
3855 bool freeze
= false;
3856 bool old_addr_detect
;
3859 STREAM_GETL(s
, dup_addr_detect
);
3860 STREAM_GETL(s
, time
);
3861 STREAM_GETL(s
, max_moves
);
3862 STREAM_GETL(s
, freeze
);
3863 STREAM_GETL(s
, freeze_time
);
3865 old_addr_detect
= zebra_evpn_do_dup_addr_detect(zvrf
);
3866 zvrf
->dup_addr_detect
= dup_addr_detect
;
3867 dup_addr_detect
= zebra_evpn_do_dup_addr_detect(zvrf
);
3869 /* DAD previous state was enabled, and new state is disable,
3870 * clear all duplicate detected addresses.
3872 if (old_addr_detect
&& !dup_addr_detect
)
3873 zebra_vxlan_clear_dup_detect_vni_all(zvrf
);
3875 zvrf
->dad_time
= time
;
3876 zvrf
->dad_max_moves
= max_moves
;
3877 zvrf
->dad_freeze
= freeze
;
3878 zvrf
->dad_freeze_time
= freeze_time
;
3880 if (IS_ZEBRA_DEBUG_VXLAN
)
3882 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
3883 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
3884 dup_addr_detect
? "enable" : "disable",
3885 zvrf
->dad_max_moves
, zvrf
->dad_time
,
3886 zvrf
->dad_freeze
? "enable" : "disable",
3887 zvrf
->dad_freeze_time
);
3894 * Display VNI hash table in detail(VTY command handler).
3896 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
3899 json_object
*json_array
= NULL
;
3900 struct zebra_ns
*zns
= NULL
;
3901 struct zebra_evpn_show zes
;
3903 if (!is_evpn_enabled())
3906 zns
= zebra_ns_lookup(NS_DEFAULT
);
3911 json_array
= json_object_new_array();
3914 zes
.json
= json_array
;
3916 zes
.use_json
= use_json
;
3918 /* Display all L2-VNIs */
3919 hash_iterate(zvrf
->evpn_table
,
3920 (void (*)(struct hash_bucket
*,
3921 void *))zebra_evpn_print_hash_detail
,
3924 /* Display all L3-VNIs */
3925 hash_iterate(zrouter
.l3vni_table
,
3926 (void (*)(struct hash_bucket
*,
3927 void *))zl3vni_print_hash_detail
,
3931 vty_json(vty
, json_array
);
3935 * Handle neighbor delete notification from the kernel (on a VLAN device
3936 * / L3 interface). This may result in either the neighbor getting deleted
3937 * from our database or being re-added to the kernel (if it is a valid
3940 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
3941 struct interface
*link_if
,
3944 struct zebra_evpn
*zevpn
= NULL
;
3945 struct zebra_l3vni
*zl3vni
= NULL
;
3947 /* check if this is a remote neigh entry corresponding to remote
3950 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
3952 return zl3vni_local_nh_del(zl3vni
, ip
);
3954 /* We are only interested in neighbors on an SVI that resides on top
3955 * of a VxLAN bridge.
3957 zevpn
= zebra_evpn_from_svi(ifp
, link_if
);
3959 if (IS_ZEBRA_DEBUG_VXLAN
)
3961 "%s: Del neighbor %pIA EVPN is not present for interface %s",
3962 __func__
, ip
, ifp
->name
);
3966 if (!zevpn
->vxlan_if
) {
3968 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
3973 if (IS_ZEBRA_DEBUG_VXLAN
)
3974 zlog_debug("Del neighbor %pIA intf %s(%u) -> L2-VNI %u",
3975 ip
, ifp
->name
, ifp
->ifindex
, zevpn
->vni
);
3977 return zebra_evpn_neigh_del_ip(zevpn
, ip
);
3981 * Handle neighbor add or update notification from the kernel (on a VLAN
3982 * device / L3 interface). This is typically for a local neighbor but can
3983 * also be for a remote neighbor (e.g., ageout notification). It could
3984 * also be a "move" scenario.
3986 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
3987 struct interface
*link_if
,
3989 struct ethaddr
*macaddr
,
3993 bool local_inactive
, bool dp_static
)
3995 struct zebra_evpn
*zevpn
= NULL
;
3996 struct zebra_l3vni
*zl3vni
= NULL
;
3998 /* check if this is a remote neigh entry corresponding to remote
4001 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4003 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
4005 /* We are only interested in neighbors on an SVI that resides on top
4006 * of a VxLAN bridge.
4008 zevpn
= zebra_evpn_from_svi(ifp
, link_if
);
4012 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
4014 "Add/Update neighbor %pIA MAC %pEA intf %s(%u) state 0x%x %s%s%s%s-> L2-VNI %u",
4015 ip
, macaddr
, ifp
->name
,
4016 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
4017 is_router
? "router " : "",
4018 local_inactive
? "local_inactive " : "",
4019 dp_static
? "peer_sync " : "", zevpn
->vni
);
4021 /* Is this about a local neighbor or a remote one? */
4023 return zebra_evpn_local_neigh_update(zevpn
, ifp
, ip
, macaddr
,
4024 is_router
, local_inactive
,
4027 return zebra_evpn_remote_neigh_update(zevpn
, ifp
, ip
, macaddr
, state
);
4031 zebra_vxlan_remote_macip_helper(bool add
, struct stream
*s
, vni_t
*vni
,
4032 struct ethaddr
*macaddr
, uint16_t *ipa_len
,
4033 struct ipaddr
*ip
, struct in_addr
*vtep_ip
,
4034 uint8_t *flags
, uint32_t *seq
, esi_t
*esi
)
4039 * Obtain each remote MACIP and process.
4040 * Message contains VNI, followed by MAC followed by IP (if any)
4041 * followed by remote VTEP IP.
4043 memset(ip
, 0, sizeof(*ip
));
4044 STREAM_GETL(s
, *vni
);
4045 STREAM_GET(macaddr
->octet
, s
, ETH_ALEN
);
4046 STREAM_GETW(s
, *ipa_len
);
4049 if (*ipa_len
== IPV4_MAX_BYTELEN
)
4050 ip
->ipa_type
= IPADDR_V4
;
4051 else if (*ipa_len
== IPV6_MAX_BYTELEN
)
4052 ip
->ipa_type
= IPADDR_V6
;
4054 if (IS_ZEBRA_DEBUG_VXLAN
)
4056 "ipa_len *must* be %d or %d bytes in length not %d",
4057 IPV4_MAX_BYTELEN
, IPV6_MAX_BYTELEN
,
4059 goto stream_failure
;
4062 STREAM_GET(&ip
->ip
.addr
, s
, *ipa_len
);
4064 l
+= 4 + ETH_ALEN
+ 4 + *ipa_len
;
4065 STREAM_GET(&vtep_ip
->s_addr
, s
, IPV4_MAX_BYTELEN
);
4066 l
+= IPV4_MAX_BYTELEN
;
4069 STREAM_GETC(s
, *flags
);
4070 STREAM_GETL(s
, *seq
);
4072 STREAM_GET(esi
, s
, sizeof(esi_t
));
4083 * Handle message from client to delete a remote MACIP for a VNI.
4085 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
4089 struct ethaddr macaddr
;
4091 struct in_addr vtep_ip
;
4092 uint16_t l
= 0, ipa_len
;
4093 char buf1
[INET6_ADDRSTRLEN
];
4097 while (l
< hdr
->length
) {
4098 int res_length
= zebra_vxlan_remote_macip_helper(
4099 false, s
, &vni
, &macaddr
, &ipa_len
, &ip
, &vtep_ip
, NULL
,
4102 if (res_length
== -1)
4103 goto stream_failure
;
4106 if (IS_ZEBRA_DEBUG_VXLAN
)
4108 "Recv MACIP DEL VNI %u MAC %pEA%s%s Remote VTEP %pI4 from %s",
4110 ipa_len
? " IP " : "",
4112 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
4113 &vtep_ip
, zebra_route_string(client
->proto
));
4115 /* Enqueue to workqueue for processing */
4116 zebra_rib_queue_evpn_rem_macip_del(vni
, &macaddr
, &ip
, vtep_ip
);
4124 * Handle message from client to add a remote MACIP for a VNI. This
4125 * could be just the add of a MAC address or the add of a neighbor
4128 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
4132 struct ethaddr macaddr
;
4134 struct in_addr vtep_ip
;
4135 uint16_t l
= 0, ipa_len
;
4138 char buf1
[INET6_ADDRSTRLEN
];
4140 char esi_buf
[ESI_STR_LEN
];
4142 if (!EVPN_ENABLED(zvrf
)) {
4143 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
4149 while (l
< hdr
->length
) {
4151 int res_length
= zebra_vxlan_remote_macip_helper(
4152 true, s
, &vni
, &macaddr
, &ipa_len
, &ip
, &vtep_ip
,
4153 &flags
, &seq
, &esi
);
4155 if (res_length
== -1)
4156 goto stream_failure
;
4159 if (IS_ZEBRA_DEBUG_VXLAN
) {
4160 if (memcmp(&esi
, zero_esi
, sizeof(esi_t
)))
4161 esi_to_str(&esi
, esi_buf
, sizeof(esi_buf
));
4163 strlcpy(esi_buf
, "-", ESI_STR_LEN
);
4165 "Recv %sMACIP ADD VNI %u MAC %pEA%s%s flags 0x%x seq %u VTEP %pI4 ESI %s from %s",
4166 (flags
& ZEBRA_MACIP_TYPE_SYNC_PATH
) ?
4169 ipa_len
? " IP " : "",
4171 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
4172 flags
, seq
, &vtep_ip
, esi_buf
,
4173 zebra_route_string(client
->proto
));
4176 /* Enqueue to workqueue for processing */
4177 zebra_rib_queue_evpn_rem_macip_add(vni
, &macaddr
, &ip
, flags
,
4178 seq
, vtep_ip
, &esi
);
4186 * Handle remote vtep delete by kernel; re-add the vtep if we have it
4188 int zebra_vxlan_check_readd_vtep(struct interface
*ifp
, vni_t vni
,
4189 struct in_addr vtep_ip
)
4191 struct zebra_if
*zif
;
4192 struct zebra_vrf
*zvrf
= NULL
;
4193 struct zebra_evpn
*zevpn
= NULL
;
4194 struct zebra_vtep
*zvtep
= NULL
;
4195 struct zebra_vxlan_vni
*vnip
;
4200 /* If EVPN is not enabled, nothing to do. */
4201 if (!is_evpn_enabled())
4204 /* Locate VRF corresponding to interface. */
4205 zvrf
= ifp
->vrf
->info
;
4209 vnip
= zebra_vxlan_if_vni_find(zif
, vni
);
4213 /* Locate hash entry; it is expected to exist. */
4214 zevpn
= zebra_evpn_lookup(vni
);
4218 /* If the remote vtep entry doesn't exists nothing to do */
4219 zvtep
= zebra_evpn_vtep_find(zevpn
, &vtep_ip
);
4223 if (IS_ZEBRA_DEBUG_VXLAN
)
4225 "Del MAC for remote VTEP %pI4 intf %s(%u) VNI %u - readd",
4226 &vtep_ip
, ifp
->name
, ifp
->ifindex
, vni
);
4228 zebra_evpn_vtep_install(zevpn
, zvtep
);
4233 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
4234 * us, this must involve a multihoming scenario. Treat this as implicit delete
4235 * of any prior local MAC.
4237 static int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
4238 struct interface
*br_if
,
4239 struct ethaddr
*macaddr
,
4240 vlanid_t vid
, vni_t vni
)
4242 struct zebra_if
*zif
;
4243 struct zebra_evpn
*zevpn
;
4244 struct zebra_mac
*mac
;
4249 /* Check if EVPN is enabled. */
4250 if (!is_evpn_enabled())
4253 /* Locate hash entry; it is expected to exist. */
4254 zevpn
= zebra_evpn_lookup(vni
);
4258 /* If entry doesn't exist, nothing to do. */
4259 mac
= zebra_evpn_mac_lookup(zevpn
, macaddr
);
4263 /* Is it a local entry? */
4264 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
4267 if (IS_ZEBRA_DEBUG_VXLAN
)
4269 "Add/update remote MAC %pEA intf %s(%u) VNI %u flags 0x%x - del local",
4270 macaddr
, ifp
->name
, ifp
->ifindex
, vni
, mac
->flags
);
4272 /* Remove MAC from BGP. */
4273 zebra_evpn_mac_send_del_to_client(zevpn
->vni
, macaddr
, mac
->flags
,
4277 * If there are no neigh associated with the mac delete the mac
4278 * else mark it as AUTO for forward reference
4280 if (!listcount(mac
->neigh_list
)) {
4281 zebra_evpn_mac_del(zevpn
, mac
);
4283 zebra_evpn_mac_clear_fwd_info(mac
);
4284 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_ALL_LOCAL_FLAGS
);
4285 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
4286 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
4292 /* MAC notification from the dataplane with a network dest port -
4293 * 1. This can be a local MAC on a down ES (if fast-failover is not possible
4294 * 2. Or it can be a remote MAC
4296 int zebra_vxlan_dp_network_mac_add(struct interface
*ifp
,
4297 struct interface
*br_if
,
4298 struct ethaddr
*macaddr
, vlanid_t vid
,
4299 vni_t vni
, uint32_t nhg_id
, bool sticky
,
4302 struct zebra_evpn_es
*es
;
4303 struct interface
*acc_ifp
;
4305 /* If netlink message is with vid, it will have no nexthop.
4309 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
4310 zlog_debug("dpAdd MAC %pEA VID %u - ignore as no nhid",
4315 /* Get vxlan's vid for netlink message has no it. */
4316 vid
= ((struct zebra_if
*)ifp
->info
)->l2info
.vxl
.access_vlan
;
4318 /* if remote mac delete the local entry */
4319 if (!nhg_id
|| !zebra_evpn_nhg_is_local_es(nhg_id
, &es
)
4320 || !zebra_evpn_es_local_mac_via_network_port(es
)) {
4321 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
4322 zlog_debug("dpAdd remote MAC %pEA VID %u", macaddr
,
4324 return zebra_vxlan_check_del_local_mac(ifp
, br_if
, macaddr
, vid
,
4328 /* If local MAC on a down local ES translate the network-mac-add
4329 * to a local-active-mac-add
4331 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
4332 zlog_debug("dpAdd local-nw-MAC %pEA VID %u", macaddr
, vid
);
4333 acc_ifp
= es
->zif
->ifp
;
4334 return zebra_vxlan_local_mac_add_update(
4335 acc_ifp
, br_if
, macaddr
, vid
, sticky
,
4336 false /* local_inactive */, dp_static
);
4340 * Handle network MAC delete by kernel -
4341 * 1. readd the remote MAC if we have it
4342 * 2. local MAC with does ES may also need to be re-installed
4344 int zebra_vxlan_dp_network_mac_del(struct interface
*ifp
,
4345 struct interface
*br_if
,
4346 struct ethaddr
*macaddr
, vlanid_t vid
,
4349 struct zebra_if
*zif
= NULL
;
4350 struct zebra_evpn
*zevpn
= NULL
;
4351 struct zebra_l3vni
*zl3vni
= NULL
;
4352 struct zebra_mac
*mac
= NULL
;
4357 /* Check if EVPN is enabled. */
4358 if (!is_evpn_enabled())
4361 /* check if this is a remote RMAC and readd simillar to remote macs */
4362 zl3vni
= zl3vni_lookup(vni
);
4364 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
4366 /* Locate hash entry; it is expected to exist. */
4367 zevpn
= zebra_evpn_lookup(vni
);
4371 /* If entry doesn't exist, nothing to do. */
4372 mac
= zebra_evpn_mac_lookup(zevpn
, macaddr
);
4376 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
4377 /* If remote entry simply re-install */
4378 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
4380 "dpDel remote MAC %pEA intf %s(%u) VNI %u - readd",
4381 macaddr
, ifp
->name
, ifp
->ifindex
, vni
);
4382 zebra_evpn_rem_mac_install(zevpn
, mac
, false /* was_static */);
4383 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
) && mac
->es
4384 && zebra_evpn_es_local_mac_via_network_port(mac
->es
)) {
4385 /* If local entry via nw-port call local-del which will
4386 * re-install entry in the dataplane is needed
4388 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
4389 zlog_debug("dpDel local-nw-MAC %pEA VNI %u", macaddr
,
4392 zebra_evpn_del_local_mac(zevpn
, mac
, false);
4399 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
4401 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
4402 struct ethaddr
*macaddr
, vlanid_t vid
)
4404 struct zebra_evpn
*zevpn
;
4405 struct zebra_mac
*mac
;
4407 /* We are interested in MACs only on ports or (port, VLAN) that
4410 zevpn
= zebra_evpn_map_vlan(ifp
, br_if
, vid
);
4413 if (!zevpn
->vxlan_if
) {
4415 "VNI %u hash %p doesn't have intf upon local MAC DEL",
4420 /* If entry doesn't exist, nothing to do. */
4421 mac
= zebra_evpn_mac_lookup(zevpn
, macaddr
);
4425 /* Is it a local entry? */
4426 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
4429 return zebra_evpn_del_local_mac(zevpn
, mac
, false);
4433 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
4435 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
4436 struct interface
*br_if
,
4437 struct ethaddr
*macaddr
, vlanid_t vid
,
4438 bool sticky
, bool local_inactive
,
4441 struct zebra_evpn
*zevpn
;
4442 struct zebra_vrf
*zvrf
;
4446 /* We are interested in MACs only on ports or (port, VLAN) that
4449 zevpn
= zebra_evpn_map_vlan(ifp
, br_if
, vid
);
4451 if (IS_ZEBRA_DEBUG_VXLAN
)
4453 " Add/Update %sMAC %pEA intf %s(%u) VID %u, could not find EVPN",
4454 sticky
? "sticky " : "", macaddr
,
4455 ifp
->name
, ifp
->ifindex
, vid
);
4459 if (!zevpn
->vxlan_if
) {
4460 if (IS_ZEBRA_DEBUG_VXLAN
)
4462 " VNI %u hash %p doesn't have intf upon local MAC ADD",
4467 zvrf
= zebra_vrf_get_evpn();
4468 return zebra_evpn_add_update_local_mac(zvrf
, zevpn
, ifp
, macaddr
, vid
,
4469 sticky
, local_inactive
,
4474 * Handle message from client to delete a remote VTEP for an EVPN.
4476 void zebra_vxlan_remote_vtep_del_zapi(ZAPI_HANDLER_ARGS
)
4479 unsigned short l
= 0;
4481 struct in_addr vtep_ip
;
4483 if (!is_evpn_enabled()) {
4485 "%s: EVPN is not enabled yet we have received a VTEP DEL msg",
4490 if (!EVPN_ENABLED(zvrf
)) {
4491 zlog_debug("Recv VTEP DEL zapi for non-EVPN VRF %u",
4498 while (l
< hdr
->length
) {
4499 int flood_control
__attribute__((unused
));
4501 /* Obtain each remote VTEP and process. */
4502 STREAM_GETL(s
, vni
);
4504 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
4505 l
+= IPV4_MAX_BYTELEN
;
4507 /* Flood control is intentionally ignored right now */
4508 STREAM_GETL(s
, flood_control
);
4511 if (IS_ZEBRA_DEBUG_VXLAN
)
4512 zlog_debug("Recv VTEP DEL %pI4 VNI %u from %s",
4514 zebra_route_string(client
->proto
));
4516 /* Enqueue for processing */
4517 zebra_rib_queue_evpn_rem_vtep_del(zvrf_id(zvrf
), vni
, vtep_ip
);
4525 * Handle message from client to delete a remote VTEP for an EVPN.
4527 void zebra_vxlan_remote_vtep_del(vrf_id_t vrf_id
, vni_t vni
,
4528 struct in_addr vtep_ip
)
4530 struct zebra_evpn
*zevpn
;
4531 struct zebra_vtep
*zvtep
;
4532 struct interface
*ifp
;
4533 struct zebra_if
*zif
;
4534 struct zebra_vrf
*zvrf
;
4536 if (!is_evpn_enabled()) {
4537 zlog_debug("%s: Can't process vtep del: EVPN is not enabled",
4542 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4546 if (!EVPN_ENABLED(zvrf
)) {
4547 zlog_debug("Can't process VTEP DEL for non-EVPN VRF %u",
4552 /* Locate VNI hash entry - expected to exist. */
4553 zevpn
= zebra_evpn_lookup(vni
);
4555 if (IS_ZEBRA_DEBUG_VXLAN
)
4557 "Failed to locate VNI hash for remote VTEP DEL, VNI %u",
4562 ifp
= zevpn
->vxlan_if
;
4565 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
4571 /* If down or not mapped to a bridge, we're done. */
4572 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
4575 /* If the remote VTEP does not exist, there's nothing more to
4577 * Otherwise, uninstall any remote MACs pointing to this VTEP
4578 * and then, the VTEP entry itself and remove it.
4580 zvtep
= zebra_evpn_vtep_find(zevpn
, &vtep_ip
);
4584 zebra_evpn_vtep_uninstall(zevpn
, &vtep_ip
);
4585 zebra_evpn_vtep_del(zevpn
, zvtep
);
4589 * Handle message from client to add a remote VTEP for an EVPN.
4591 void zebra_vxlan_remote_vtep_add(vrf_id_t vrf_id
, vni_t vni
,
4592 struct in_addr vtep_ip
, int flood_control
)
4594 struct zebra_evpn
*zevpn
;
4595 struct interface
*ifp
;
4596 struct zebra_if
*zif
;
4597 struct zebra_vtep
*zvtep
;
4598 struct zebra_vrf
*zvrf
;
4600 if (!is_evpn_enabled()) {
4601 zlog_debug("%s: EVPN not enabled: can't process a VTEP ADD",
4606 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4610 if (!EVPN_ENABLED(zvrf
)) {
4611 zlog_debug("Can't process VTEP ADD for non-EVPN VRF %u",
4616 /* Locate VNI hash entry - expected to exist. */
4617 zevpn
= zebra_evpn_lookup(vni
);
4620 EC_ZEBRA_VTEP_ADD_FAILED
,
4621 "Failed to locate EVPN hash upon remote VTEP ADD, VNI %u",
4626 ifp
= zevpn
->vxlan_if
;
4629 EC_ZEBRA_VTEP_ADD_FAILED
,
4630 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
4637 /* If down or not mapped to a bridge, we're done. */
4638 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
4641 zvtep
= zebra_evpn_vtep_find(zevpn
, &vtep_ip
);
4643 /* If the remote VTEP already exists check if
4644 * the flood mode has changed
4646 if (zvtep
->flood_control
!= flood_control
) {
4647 if (zvtep
->flood_control
== VXLAN_FLOOD_DISABLED
)
4648 /* old mode was head-end-replication but
4649 * is no longer; get rid of the HER fdb
4650 * entry installed before
4652 zebra_evpn_vtep_uninstall(zevpn
, &vtep_ip
);
4653 zvtep
->flood_control
= flood_control
;
4654 zebra_evpn_vtep_install(zevpn
, zvtep
);
4657 zvtep
= zebra_evpn_vtep_add(zevpn
, &vtep_ip
, flood_control
);
4659 zebra_evpn_vtep_install(zevpn
, zvtep
);
4661 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
4662 "Failed to add remote VTEP, VNI %u zevpn %p",
4668 * Handle message from client to add a remote VTEP for an EVPN.
4670 void zebra_vxlan_remote_vtep_add_zapi(ZAPI_HANDLER_ARGS
)
4673 unsigned short l
= 0;
4675 struct in_addr vtep_ip
;
4678 if (!is_evpn_enabled()) {
4680 "%s: EVPN not enabled yet we received a VTEP ADD zapi msg",
4685 if (!EVPN_ENABLED(zvrf
)) {
4686 zlog_debug("Recv VTEP ADD zapi for non-EVPN VRF %u",
4693 while (l
< hdr
->length
) {
4694 /* Obtain each remote VTEP and process. */
4695 STREAM_GETL(s
, vni
);
4697 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
4698 STREAM_GETL(s
, flood_control
);
4699 l
+= IPV4_MAX_BYTELEN
+ 4;
4701 if (IS_ZEBRA_DEBUG_VXLAN
)
4702 zlog_debug("Recv VTEP ADD %pI4 VNI %u flood %d from %s",
4703 &vtep_ip
, vni
, flood_control
,
4704 zebra_route_string(client
->proto
));
4706 /* Enqueue for processing */
4707 zebra_rib_queue_evpn_rem_vtep_add(zvrf_id(zvrf
), vni
, vtep_ip
,
4716 * Add/Del gateway macip to evpn
4718 * 1. SVI interface on a vlan aware bridge
4719 * 2. SVI interface on a vlan unaware bridge
4720 * 3. vrr interface (MACVLAN) associated to a SVI
4721 * We advertise macip routes for an interface if it is associated to VxLan vlan
4723 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, const struct prefix
*p
,
4727 struct ethaddr macaddr
;
4728 struct zebra_evpn
*zevpn
= NULL
;
4730 memset(&ip
, 0, sizeof(ip
));
4731 memset(&macaddr
, 0, sizeof(macaddr
));
4733 /* Check if EVPN is enabled. */
4734 if (!is_evpn_enabled())
4737 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
4738 struct interface
*svi_if
=
4739 NULL
; /* SVI corresponding to the MACVLAN */
4740 struct zebra_if
*ifp_zif
=
4741 NULL
; /* Zebra daemon specific info for MACVLAN */
4742 struct zebra_if
*svi_if_zif
=
4743 NULL
; /* Zebra daemon specific info for SVI*/
4745 ifp_zif
= ifp
->info
;
4750 * for a MACVLAN interface the link represents the svi_if
4752 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
4753 ifp_zif
->link_ifindex
);
4755 zlog_debug("MACVLAN %s(%u) without link information",
4756 ifp
->name
, ifp
->ifindex
);
4760 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
4762 * If it is a vlan aware bridge then the link gives the
4763 * bridge information
4765 struct interface
*svi_if_link
= NULL
;
4767 svi_if_zif
= svi_if
->info
;
4769 svi_if_link
= if_lookup_by_index_per_ns(
4770 zebra_ns_lookup(NS_DEFAULT
),
4771 svi_if_zif
->link_ifindex
);
4772 zevpn
= zebra_evpn_from_svi(svi_if
,
4775 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
4777 * If it is a vlan unaware bridge then svi is the bridge
4780 zevpn
= zebra_evpn_from_svi(svi_if
, svi_if
);
4782 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
4783 struct zebra_if
*svi_if_zif
=
4784 NULL
; /* Zebra daemon specific info for SVI */
4785 struct interface
*svi_if_link
=
4786 NULL
; /* link info for the SVI = bridge info */
4788 svi_if_zif
= ifp
->info
;
4790 svi_if_link
= if_lookup_by_index_per_ns(
4791 zebra_ns_lookup(NS_DEFAULT
),
4792 svi_if_zif
->link_ifindex
);
4794 zevpn
= zebra_evpn_from_svi(ifp
, svi_if_link
);
4796 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
4797 zevpn
= zebra_evpn_from_svi(ifp
, ifp
);
4803 if (!zevpn
->vxlan_if
) {
4804 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
4809 /* VRR IP is advertised only if gw-macip-adv-enabled */
4810 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
4811 if (!advertise_gw_macip_enabled(zevpn
))
4814 /* SVI IP is advertised if gw or svi macip-adv-enabled */
4815 if (!advertise_svi_macip_enabled(zevpn
)
4816 && !advertise_gw_macip_enabled(zevpn
))
4820 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
4822 if (p
->family
== AF_INET
) {
4823 ip
.ipa_type
= IPADDR_V4
;
4824 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
4825 sizeof(struct in_addr
));
4826 } else if (p
->family
== AF_INET6
) {
4827 ip
.ipa_type
= IPADDR_V6
;
4828 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
4829 sizeof(struct in6_addr
));
4834 zebra_evpn_gw_macip_add(ifp
, zevpn
, &macaddr
, &ip
);
4836 zebra_evpn_gw_macip_del(ifp
, zevpn
, &ip
);
4842 * Handle SVI interface going down.
4843 * SVI can be associated to either L3-VNI or L2-VNI.
4844 * For L2-VNI: At this point, this is a NOP since
4845 * the kernel deletes the neighbor entries on this SVI (if any).
4846 * We only need to update the vrf corresponding to zevpn.
4847 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
4850 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
4852 struct zebra_l3vni
*zl3vni
= NULL
;
4854 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4857 /* process l3-vni down */
4858 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4860 /* remove association with svi-if */
4861 zl3vni
->svi_if
= NULL
;
4863 struct zebra_evpn
*zevpn
= NULL
;
4865 /* Unlink the SVI from the access VLAN */
4866 zebra_evpn_acc_bd_svi_set(ifp
->info
, link_if
->info
, false);
4868 /* since we dont have svi corresponding to zevpn, we associate it
4869 * to default vrf. Note: the corresponding neigh entries on the
4870 * SVI would have already been deleted */
4871 zevpn
= zebra_evpn_from_svi(ifp
, link_if
);
4874 /* remove from l3-vni list */
4875 zl3vni
= zl3vni_from_vrf(zevpn
->vrf_id
);
4877 listnode_delete(zl3vni
->l2vnis
, zevpn
);
4879 zevpn
->svi_if
= NULL
;
4880 zevpn
->vrf_id
= VRF_DEFAULT
;
4882 /* update the tenant vrf in BGP */
4883 if (if_is_operative(zevpn
->vxlan_if
))
4884 zebra_evpn_send_add_to_client(zevpn
);
4891 * Handle SVI interface coming up.
4892 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
4894 * For L2-VNI: we need to install any remote neighbors entried (used for
4896 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
4898 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
4900 struct zebra_evpn
*zevpn
= NULL
;
4901 struct zebra_l3vni
*zl3vni
= NULL
;
4903 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4906 /* associate with svi */
4907 zl3vni
->svi_if
= ifp
;
4909 /* process oper-up */
4910 if (is_l3vni_oper_up(zl3vni
))
4911 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4914 /* process SVI up for l2-vni */
4915 struct neigh_walk_ctx n_wctx
;
4917 zevpn
= zebra_evpn_from_svi(ifp
, link_if
);
4921 if (!zevpn
->vxlan_if
) {
4923 "VNI %u hash %p doesn't have intf upon SVI up",
4928 if (IS_ZEBRA_DEBUG_VXLAN
)
4930 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
4931 ifp
->name
, ifp
->ifindex
, zevpn
->vni
,
4934 /* update the vrf information for l2-vni and inform bgp */
4935 zevpn
->svi_if
= ifp
;
4936 zevpn
->vrf_id
= ifp
->vrf
->vrf_id
;
4938 zl3vni
= zl3vni_from_vrf(zevpn
->vrf_id
);
4940 listnode_add_sort_nodup(zl3vni
->l2vnis
, zevpn
);
4942 if (if_is_operative(zevpn
->vxlan_if
))
4943 zebra_evpn_send_add_to_client(zevpn
);
4945 /* Install any remote neighbors for this VNI. */
4946 memset(&n_wctx
, 0, sizeof(n_wctx
));
4947 n_wctx
.zevpn
= zevpn
;
4948 hash_iterate(zevpn
->neigh_table
, zebra_evpn_install_neigh_hash
,
4951 /* Link the SVI from the access VLAN */
4952 zebra_evpn_acc_bd_svi_set(ifp
->info
, link_if
->info
, true);
4954 /* Update MACIP routes created by advertise-svi-ip */
4955 if (advertise_svi_macip_enabled(zevpn
)) {
4956 zebra_evpn_del_macip_for_intf(ifp
, zevpn
);
4957 zebra_evpn_add_macip_for_intf(ifp
, zevpn
);
4965 * Handle MAC-VLAN interface going down.
4966 * L3VNI: When MAC-VLAN interface goes down,
4967 * find its associated SVI and update type2/type-5 routes
4970 void zebra_vxlan_macvlan_down(struct interface
*ifp
)
4972 struct zebra_l3vni
*zl3vni
= NULL
;
4973 struct zebra_if
*zif
, *link_zif
;
4974 struct interface
*link_ifp
, *link_if
;
4978 link_ifp
= zif
->link
;
4980 if (IS_ZEBRA_DEBUG_VXLAN
)
4982 "macvlan parent link is not found. Parent index %d ifp %s",
4984 ifindex2ifname(zif
->link_ifindex
,
4988 link_zif
= link_ifp
->info
;
4991 link_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
4992 link_zif
->link_ifindex
);
4994 zl3vni
= zl3vni_from_svi(link_ifp
, link_if
);
4996 zl3vni
->mac_vlan_if
= NULL
;
4997 if (is_l3vni_oper_up(zl3vni
))
4998 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
5003 * Handle MAC-VLAN interface going up.
5004 * L3VNI: When MAC-VLAN interface comes up,
5005 * find its associated SVI and update type-2 routes
5006 * with MAC-VLAN's MAC as RMAC and for type-5 routes
5007 * use SVI's MAC as RMAC.
5009 void zebra_vxlan_macvlan_up(struct interface
*ifp
)
5011 struct zebra_l3vni
*zl3vni
= NULL
;
5012 struct zebra_if
*zif
, *link_zif
;
5013 struct interface
*link_ifp
, *link_if
;
5017 link_ifp
= zif
->link
;
5018 link_zif
= link_ifp
->info
;
5021 link_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
5022 link_zif
->link_ifindex
);
5023 zl3vni
= zl3vni_from_svi(link_ifp
, link_if
);
5025 /* associate with macvlan (VRR) interface */
5026 zl3vni
->mac_vlan_if
= ifp
;
5028 /* process oper-up */
5029 if (is_l3vni_oper_up(zl3vni
))
5030 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
5034 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
5035 char *err
, int err_str_sz
, int filter
,
5038 struct zebra_l3vni
*zl3vni
= NULL
;
5039 struct zebra_vrf
*zvrf_evpn
= NULL
;
5041 zvrf_evpn
= zebra_vrf_get_evpn();
5043 if (IS_ZEBRA_DEBUG_VXLAN
)
5044 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
5045 add
? "ADD" : "DEL");
5048 /* check if the vni is already present under zvrf */
5050 snprintf(err
, err_str_sz
,
5051 "VNI is already configured under the vrf");
5055 /* check if this VNI is already present in the system */
5056 zl3vni
= zl3vni_lookup(vni
);
5058 snprintf(err
, err_str_sz
,
5059 "VNI is already configured as L3-VNI");
5063 /* Remove L2VNI if present */
5064 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
5066 /* add the L3-VNI to the global table */
5067 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
5069 /* associate the vrf with vni */
5072 /* set the filter in l3vni to denote if we are using l3vni only
5076 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
5078 /* associate with vxlan-intf;
5079 * we need to associate with the vxlan-intf first
5081 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
5083 /* associate with corresponding SVI interface, we can associate
5084 * with svi-if only after vxlan interface association is
5087 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
5089 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
5091 if (IS_ZEBRA_DEBUG_VXLAN
)
5093 "%s: l3vni %u svi_if %s mac_vlan_if %s",
5095 zl3vni
->svi_if
? zl3vni
->svi_if
->name
: "NIL",
5096 zl3vni
->mac_vlan_if
? zl3vni
->mac_vlan_if
->name
5099 /* formulate l2vni list */
5100 hash_iterate(zvrf_evpn
->evpn_table
, zevpn_add_to_l3vni_list
,
5103 if (is_l3vni_oper_up(zl3vni
))
5104 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
5107 zl3vni
= zl3vni_lookup(vni
);
5109 snprintf(err
, err_str_sz
, "VNI doesn't exist");
5113 if (zvrf
->l3vni
!= vni
) {
5114 snprintf(err
, err_str_sz
,
5115 "VNI %d doesn't exist in VRF: %s",
5116 vni
, zvrf
->vrf
->name
);
5120 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
5121 snprintf(err
, ERR_STR_SZ
,
5122 "prefix-routes-only is not set for the vni");
5126 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
5128 /* delete and uninstall all rmacs */
5129 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
5132 /* delete and uninstall all next-hops */
5133 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
5139 /* Add L2VNI for this VNI */
5140 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
5145 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
5147 struct zebra_l3vni
*zl3vni
= NULL
;
5150 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5154 zl3vni
->vrf_id
= zvrf_id(zvrf
);
5155 if (is_l3vni_oper_up(zl3vni
))
5156 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
5160 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
5162 struct zebra_l3vni
*zl3vni
= NULL
;
5165 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5169 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
5171 /* delete and uninstall all rmacs */
5172 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
, zl3vni
);
5173 /* delete and uninstall all next-hops */
5174 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
, zl3vni
);
5176 zl3vni
->vrf_id
= VRF_UNKNOWN
;
5181 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
5183 struct zebra_l3vni
*zl3vni
= NULL
;
5187 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5193 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
5199 * Handle message from client to specify the flooding mechanism for
5200 * BUM packets. The default is to do head-end (ingress) replication
5201 * and the other supported option is to disable it. This applies to
5202 * all BUM traffic and disabling it applies to both the transmit and
5203 * receive direction.
5205 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
5208 enum vxlan_flood_control flood_ctrl
;
5210 if (!EVPN_ENABLED(zvrf
)) {
5211 zlog_err("EVPN flood control for non-EVPN VRF %u",
5217 STREAM_GETC(s
, flood_ctrl
);
5219 if (IS_ZEBRA_DEBUG_VXLAN
)
5220 zlog_debug("EVPN flood control %u, currently %u",
5221 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
5223 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
5226 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
5228 /* Install or uninstall flood entries corresponding to
5231 hash_iterate(zvrf
->evpn_table
, zebra_evpn_handle_flooding_remote_vteps
,
5239 * Handle message from client to enable/disable advertisement of svi macip
5242 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
5247 struct zebra_evpn
*zevpn
= NULL
;
5248 struct interface
*ifp
= NULL
;
5250 if (!EVPN_ENABLED(zvrf
)) {
5251 zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u",
5257 STREAM_GETC(s
, advertise
);
5258 STREAM_GETL(s
, vni
);
5261 if (IS_ZEBRA_DEBUG_VXLAN
)
5262 zlog_debug("EVPN SVI-MACIP Adv %s, currently %s",
5263 advertise
? "enabled" : "disabled",
5264 advertise_svi_macip_enabled(NULL
)
5268 if (zvrf
->advertise_svi_macip
== advertise
)
5273 zvrf
->advertise_svi_macip
= advertise
;
5274 hash_iterate(zvrf
->evpn_table
,
5275 zebra_evpn_gw_macip_add_for_evpn_hash
,
5278 hash_iterate(zvrf
->evpn_table
,
5279 zebra_evpn_svi_macip_del_for_evpn_hash
,
5281 zvrf
->advertise_svi_macip
= advertise
;
5285 struct zebra_if
*zif
= NULL
;
5286 struct interface
*vlan_if
= NULL
;
5287 struct zebra_vxlan_vni
*zl2_info_vni
;
5290 zevpn
= zebra_evpn_lookup(vni
);
5294 if (IS_ZEBRA_DEBUG_VXLAN
)
5296 "EVPN SVI macip Adv %s on VNI %d, currently %s",
5297 advertise
? "enabled" : "disabled", vni
,
5298 advertise_svi_macip_enabled(zevpn
)
5302 old_advertise
= advertise_svi_macip_enabled(zevpn
);
5304 /* Store flag even though SVI is not present.
5305 * Once SVI comes up triggers self MAC-IP route add.
5307 zevpn
->advertise_svi_macip
= advertise
;
5308 if (advertise_svi_macip_enabled(zevpn
) == old_advertise
)
5311 ifp
= zevpn
->vxlan_if
;
5317 /* If down or not mapped to a bridge, we're done. */
5318 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5321 zl2_info_vni
= zebra_vxlan_if_vni_find(zif
, vni
);
5325 vlan_if
= zvni_map_to_svi(zl2_info_vni
->access_vlan
,
5326 zif
->brslave_info
.br_if
);
5331 /* Add primary SVI MAC-IP */
5332 zebra_evpn_add_macip_for_intf(vlan_if
, zevpn
);
5334 /* Del primary SVI MAC-IP */
5335 zebra_evpn_del_macip_for_intf(vlan_if
, zevpn
);
5344 * Handle message from client to enable/disable advertisement of g/w macip
5347 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
5352 struct zebra_evpn
*zevpn
= NULL
;
5353 struct interface
*ifp
= NULL
;
5354 struct zebra_if
*zif
= NULL
;
5355 struct interface
*vlan_if
= NULL
;
5356 struct zebra_vxlan_vni
*zl2_info_vni
= NULL
;
5358 if (!EVPN_ENABLED(zvrf
)) {
5359 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
5365 STREAM_GETC(s
, advertise
);
5366 STREAM_GET(&vni
, s
, 3);
5368 zevpn
= zebra_evpn_lookup(vni
);
5372 if (zevpn
->advertise_subnet
== advertise
)
5375 if (IS_ZEBRA_DEBUG_VXLAN
)
5376 zlog_debug("EVPN subnet Adv %s on VNI %d, currently %s",
5377 advertise
? "enabled" : "disabled", vni
,
5378 zevpn
->advertise_subnet
? "enabled" : "disabled");
5381 zevpn
->advertise_subnet
= advertise
;
5383 ifp
= zevpn
->vxlan_if
;
5389 /* If down or not mapped to a bridge, we're done. */
5390 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5393 zl2_info_vni
= zebra_vxlan_if_vni_find(zif
, vni
);
5397 vlan_if
= zvni_map_to_svi(zl2_info_vni
->access_vlan
,
5398 zif
->brslave_info
.br_if
);
5402 if (zevpn
->advertise_subnet
)
5403 zebra_evpn_advertise_subnet(zevpn
, vlan_if
, 1);
5405 zebra_evpn_advertise_subnet(zevpn
, vlan_if
, 0);
5412 * Handle message from client to enable/disable advertisement of g/w macip
5415 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
5420 struct zebra_evpn
*zevpn
= NULL
;
5421 struct interface
*ifp
= NULL
;
5423 if (!EVPN_ENABLED(zvrf
)) {
5424 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
5430 STREAM_GETC(s
, advertise
);
5431 STREAM_GETL(s
, vni
);
5434 if (IS_ZEBRA_DEBUG_VXLAN
)
5435 zlog_debug("EVPN gateway macip Adv %s, currently %s",
5436 advertise
? "enabled" : "disabled",
5437 advertise_gw_macip_enabled(NULL
)
5441 if (zvrf
->advertise_gw_macip
== advertise
)
5444 zvrf
->advertise_gw_macip
= advertise
;
5446 if (advertise_gw_macip_enabled(zevpn
))
5447 hash_iterate(zvrf
->evpn_table
,
5448 zebra_evpn_gw_macip_add_for_evpn_hash
,
5451 hash_iterate(zvrf
->evpn_table
,
5452 zebra_evpn_gw_macip_del_for_evpn_hash
,
5456 struct zebra_if
*zif
= NULL
;
5457 struct interface
*vlan_if
= NULL
;
5458 struct interface
*vrr_if
= NULL
;
5459 struct zebra_vxlan_vni
*zl2_info_vni
= NULL
;
5462 zevpn
= zebra_evpn_lookup(vni
);
5466 if (IS_ZEBRA_DEBUG_VXLAN
)
5468 "EVPN gateway macip Adv %s on VNI %d, currently %s",
5469 advertise
? "enabled" : "disabled", vni
,
5470 advertise_gw_macip_enabled(zevpn
) ? "enabled"
5473 old_advertise
= advertise_gw_macip_enabled(zevpn
);
5475 zevpn
->advertise_gw_macip
= advertise
;
5476 if (advertise_gw_macip_enabled(zevpn
) == old_advertise
)
5479 ifp
= zevpn
->vxlan_if
;
5485 /* If down or not mapped to a bridge, we're done. */
5486 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5489 zl2_info_vni
= zebra_vxlan_if_vni_find(zif
, vni
);
5493 vlan_if
= zvni_map_to_svi(zl2_info_vni
->access_vlan
,
5494 zif
->brslave_info
.br_if
);
5498 if (advertise_gw_macip_enabled(zevpn
)) {
5499 /* Add primary SVI MAC-IP */
5500 zebra_evpn_add_macip_for_intf(vlan_if
, zevpn
);
5502 /* Add VRR MAC-IP - if any*/
5503 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
5505 zebra_evpn_add_macip_for_intf(vrr_if
, zevpn
);
5507 /* Del primary MAC-IP */
5508 zebra_evpn_del_macip_for_intf(vlan_if
, zevpn
);
5510 /* Del VRR MAC-IP - if any*/
5511 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
5513 zebra_evpn_del_macip_for_intf(vrr_if
, zevpn
);
5521 static int macfdb_read_ns(struct ns
*ns
,
5522 void *_in_param
__attribute__((unused
)),
5523 void **out_param
__attribute__((unused
)))
5525 struct zebra_ns
*zns
= ns
->info
;
5528 return NS_WALK_CONTINUE
;
5531 static int neigh_read_ns(struct ns
*ns
,
5532 void *_in_param
__attribute__((unused
)),
5533 void **out_param
__attribute__((unused
)))
5535 struct zebra_ns
*zns
= ns
->info
;
5538 return NS_WALK_CONTINUE
;
5542 * Handle message from client to learn (or stop learning) about VNIs and MACs.
5543 * When enabled, the VNI hash table will be built and MAC FDB table read;
5544 * when disabled, the entries should be deleted and remote VTEPs and MACs
5545 * uninstalled from the kernel.
5546 * This also informs the setting for BUM handling at the time this change
5547 * occurs; it is relevant only when specifying "learn".
5549 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
5551 struct stream
*s
= NULL
;
5553 enum vxlan_flood_control flood_ctrl
;
5555 /* Mismatch between EVPN VRF and current VRF (should be prevented by
5557 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf
))
5561 STREAM_GETC(s
, advertise
);
5562 STREAM_GETC(s
, flood_ctrl
);
5564 if (IS_ZEBRA_DEBUG_VXLAN
)
5565 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
5566 zvrf_name(zvrf
), zvrf_id(zvrf
),
5567 advertise
? "enabled" : "disabled",
5568 is_evpn_enabled() ? "enabled" : "disabled",
5571 if (zvrf
->advertise_all_vni
== advertise
)
5574 zvrf
->advertise_all_vni
= advertise
;
5575 if (EVPN_ENABLED(zvrf
)) {
5576 zrouter
.evpn_vrf
= zvrf
;
5578 /* Note BUM handling */
5579 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
5581 /* Replay all ESs */
5582 zebra_evpn_es_send_all_to_client(true /* add */);
5584 /* Build EVPN hash table and inform BGP. */
5585 zevpn_build_hash_table();
5587 /* Add all SVI (L3 GW) MACs to BGP*/
5588 hash_iterate(zvrf
->evpn_table
,
5589 zebra_evpn_gw_macip_add_for_evpn_hash
, NULL
);
5591 /* Read the MAC FDB */
5592 ns_walk_func(macfdb_read_ns
, NULL
, NULL
);
5594 /* Read neighbors */
5595 ns_walk_func(neigh_read_ns
, NULL
, NULL
);
5597 /* Cleanup VTEPs for all EVPNs - uninstall from
5598 * kernel and free entries.
5600 hash_iterate(zvrf
->evpn_table
, zebra_evpn_vxlan_cleanup_all
,
5603 /* Delete all ESs in BGP */
5604 zebra_evpn_es_send_all_to_client(false /* add */);
5606 /* cleanup all l3vnis */
5607 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
5609 /* Mark as "no EVPN VRF" */
5610 zrouter
.evpn_vrf
= NULL
;
5618 * Allocate EVPN hash table for this VRF and do other initialization.
5619 * NOTE: Currently supported only for default VRF.
5621 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
5628 snprintf(buffer
, sizeof(buffer
), "Zebra VRF EVPN Table: %s",
5630 zvrf
->evpn_table
= hash_create_size(8, zebra_evpn_hash_keymake
,
5631 zebra_evpn_hash_cmp
, buffer
);
5633 snprintf(buffer
, sizeof(buffer
), "Zebra VxLAN SG Table: %s",
5635 zvrf
->vxlan_sg_table
= hash_create_size(8, zebra_vxlan_sg_hash_key_make
,
5636 zebra_vxlan_sg_hash_eq
, buffer
);
5639 /* Cleanup EVPN info, but don't free the table. */
5640 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
5642 struct zebra_vrf
*evpn_zvrf
= zebra_vrf_get_evpn();
5644 hash_iterate(zvrf
->evpn_table
, zebra_evpn_vxlan_cleanup_all
, zvrf
);
5645 zebra_vxlan_cleanup_sg_table(zvrf
);
5647 if (zvrf
== evpn_zvrf
)
5648 zebra_evpn_es_cleanup();
5651 /* Close all EVPN handling */
5652 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
5656 hash_iterate(zvrf
->evpn_table
, zebra_evpn_vxlan_cleanup_all
, zvrf
);
5657 hash_free(zvrf
->evpn_table
);
5658 if (zvrf
->vxlan_sg_table
) {
5659 zebra_vxlan_cleanup_sg_table(zvrf
);
5660 hash_free(zvrf
->vxlan_sg_table
);
5661 zvrf
->vxlan_sg_table
= NULL
;
5665 /* init the l3vni table */
5666 void zebra_vxlan_init(void)
5668 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
5669 "Zebra VRF L3 VNI table");
5671 svd_nh_table
= zebra_neigh_db_create("Zebra SVD next-hop table");
5673 zrouter
.evpn_vrf
= NULL
;
5674 zebra_evpn_mh_init();
5677 /* free l3vni table */
5678 void zebra_vxlan_disable(void)
5680 hash_free(zrouter
.l3vni_table
);
5681 zebra_evpn_mh_terminate();
5684 /* get the l3vni svi ifindex */
5685 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
5687 struct zebra_l3vni
*zl3vni
= NULL
;
5689 zl3vni
= zl3vni_from_vrf(vrf_id
);
5690 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5693 return zl3vni
->svi_if
->ifindex
;
5696 /* get the l3vni vxlan ifindex */
5697 ifindex_t
get_l3vni_vxlan_ifindex(vrf_id_t vrf_id
)
5699 struct zebra_l3vni
*zl3vni
= NULL
;
5701 zl3vni
= zl3vni_from_vrf(vrf_id
);
5702 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5705 return zl3vni
->vxlan_if
->ifindex
;
5708 /* get the l3vni vni */
5709 vni_t
get_l3vni_vni(vrf_id_t vrf_id
)
5711 struct zebra_l3vni
*zl3vni
= NULL
;
5713 zl3vni
= zl3vni_from_vrf(vrf_id
);
5714 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5720 /* is the vrf l3vni SVD backed? */
5721 bool is_vrf_l3vni_svd_backed(vrf_id_t vrf_id
)
5723 struct zebra_l3vni
*zl3vni
= NULL
;
5725 zl3vni
= zl3vni_from_vrf(vrf_id
);
5726 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5729 return IS_ZL3VNI_SVD_BACKED(zl3vni
);
5732 /************************** vxlan SG cache management ************************/
5733 /* Inform PIM about the mcast group */
5734 static int zebra_vxlan_sg_send(struct zebra_vrf
*zvrf
,
5735 struct prefix_sg
*sg
,
5736 char *sg_str
, uint16_t cmd
)
5738 struct zserv
*client
= NULL
;
5739 struct stream
*s
= NULL
;
5741 client
= zserv_find_client(ZEBRA_ROUTE_PIM
, 0);
5745 if (!CHECK_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
))
5748 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5750 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
5751 stream_putl(s
, IPV4_MAX_BYTELEN
);
5752 stream_put(s
, &sg
->src
.s_addr
, IPV4_MAX_BYTELEN
);
5753 stream_put(s
, &sg
->grp
.s_addr
, IPV4_MAX_BYTELEN
);
5755 /* Write packet size. */
5756 stream_putw_at(s
, 0, stream_get_endp(s
));
5758 if (IS_ZEBRA_DEBUG_VXLAN
)
5761 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", sg_str
,
5762 zebra_route_string(client
->proto
));
5764 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
5765 client
->vxlan_sg_add_cnt
++;
5767 client
->vxlan_sg_del_cnt
++;
5769 return zserv_send_message(client
, s
);
5772 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
)
5774 const struct zebra_vxlan_sg
*vxlan_sg
= p
;
5776 return (jhash_2words(vxlan_sg
->sg
.src
.s_addr
,
5777 vxlan_sg
->sg
.grp
.s_addr
, 0));
5780 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
)
5782 const struct zebra_vxlan_sg
*sg1
= p1
;
5783 const struct zebra_vxlan_sg
*sg2
= p2
;
5785 return ((sg1
->sg
.src
.s_addr
== sg2
->sg
.src
.s_addr
)
5786 && (sg1
->sg
.grp
.s_addr
== sg2
->sg
.grp
.s_addr
));
5789 static struct zebra_vxlan_sg
*zebra_vxlan_sg_new(struct zebra_vrf
*zvrf
,
5790 struct prefix_sg
*sg
)
5792 struct zebra_vxlan_sg
*vxlan_sg
;
5794 vxlan_sg
= XCALLOC(MTYPE_ZVXLAN_SG
, sizeof(*vxlan_sg
));
5796 vxlan_sg
->zvrf
= zvrf
;
5798 prefix_sg2str(sg
, vxlan_sg
->sg_str
);
5800 vxlan_sg
= hash_get(zvrf
->vxlan_sg_table
, vxlan_sg
, hash_alloc_intern
);
5802 if (IS_ZEBRA_DEBUG_VXLAN
)
5803 zlog_debug("vxlan SG %s created", vxlan_sg
->sg_str
);
5808 static struct zebra_vxlan_sg
*zebra_vxlan_sg_find(struct zebra_vrf
*zvrf
,
5809 struct prefix_sg
*sg
)
5811 struct zebra_vxlan_sg lookup
;
5814 return hash_lookup(zvrf
->vxlan_sg_table
, &lookup
);
5817 static struct zebra_vxlan_sg
*zebra_vxlan_sg_add(struct zebra_vrf
*zvrf
,
5818 struct prefix_sg
*sg
)
5820 struct zebra_vxlan_sg
*vxlan_sg
;
5821 struct zebra_vxlan_sg
*parent
= NULL
;
5824 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, sg
);
5828 /* create a *G entry for every BUM group implicitly -
5829 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
5830 * 2. the XG entry is used by pimd to setup the
5831 * vxlan-termination-mroute
5833 if (sg
->src
.s_addr
!= INADDR_ANY
) {
5834 memset(&sip
, 0, sizeof(sip
));
5835 parent
= zebra_vxlan_sg_do_ref(zvrf
, sip
, sg
->grp
);
5840 vxlan_sg
= zebra_vxlan_sg_new(zvrf
, sg
);
5842 zebra_vxlan_sg_send(zvrf
, sg
, vxlan_sg
->sg_str
,
5843 ZEBRA_VXLAN_SG_ADD
);
5848 static void zebra_vxlan_sg_del(struct zebra_vxlan_sg
*vxlan_sg
)
5851 struct zebra_vrf
*zvrf
;
5853 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
5857 /* On SG entry deletion remove the reference to its parent XG
5860 if (vxlan_sg
->sg
.src
.s_addr
!= INADDR_ANY
) {
5861 memset(&sip
, 0, sizeof(sip
));
5862 zebra_vxlan_sg_do_deref(zvrf
, sip
, vxlan_sg
->sg
.grp
);
5865 zebra_vxlan_sg_send(zvrf
, &vxlan_sg
->sg
,
5866 vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_DEL
);
5868 hash_release(vxlan_sg
->zvrf
->vxlan_sg_table
, vxlan_sg
);
5870 if (IS_ZEBRA_DEBUG_VXLAN
)
5871 zlog_debug("VXLAN SG %s deleted", vxlan_sg
->sg_str
);
5873 XFREE(MTYPE_ZVXLAN_SG
, vxlan_sg
);
5876 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
5877 struct in_addr sip
, struct in_addr mcast_grp
)
5879 struct zebra_vxlan_sg
*vxlan_sg
;
5880 struct prefix_sg sg
;
5882 sg
.family
= AF_INET
;
5883 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
5886 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, &sg
);
5890 if (vxlan_sg
->ref_cnt
)
5891 --vxlan_sg
->ref_cnt
;
5893 if (!vxlan_sg
->ref_cnt
)
5894 zebra_vxlan_sg_del(vxlan_sg
);
5897 static struct zebra_vxlan_sg
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*zvrf
,
5899 struct in_addr mcast_grp
)
5901 struct zebra_vxlan_sg
*vxlan_sg
;
5902 struct prefix_sg sg
;
5904 sg
.family
= AF_INET
;
5905 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
5908 vxlan_sg
= zebra_vxlan_sg_add(zvrf
, &sg
);
5910 ++vxlan_sg
->ref_cnt
;
5915 void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
5916 struct in_addr mcast_grp
)
5918 struct zebra_vrf
*zvrf
;
5920 if (local_vtep_ip
.s_addr
== INADDR_ANY
5921 || mcast_grp
.s_addr
== INADDR_ANY
)
5924 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
5928 zebra_vxlan_sg_do_deref(zvrf
, local_vtep_ip
, mcast_grp
);
5931 void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
, struct in_addr mcast_grp
)
5933 struct zebra_vrf
*zvrf
;
5935 if (local_vtep_ip
.s_addr
== INADDR_ANY
5936 || mcast_grp
.s_addr
== INADDR_ANY
)
5939 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
5942 zebra_vxlan_sg_do_ref(zvrf
, local_vtep_ip
, mcast_grp
);
5945 static void zebra_vxlan_xg_pre_cleanup(struct hash_bucket
*bucket
, void *arg
)
5947 struct zebra_vxlan_sg
*vxlan_sg
= (struct zebra_vxlan_sg
*)bucket
->data
;
5949 /* increment the ref count against (*,G) to prevent them from being
5952 if (vxlan_sg
->sg
.src
.s_addr
== INADDR_ANY
)
5953 ++vxlan_sg
->ref_cnt
;
5956 static void zebra_vxlan_xg_post_cleanup(struct hash_bucket
*bucket
, void *arg
)
5958 struct zebra_vxlan_sg
*vxlan_sg
= (struct zebra_vxlan_sg
*)bucket
->data
;
5960 /* decrement the dummy ref count against (*,G) to delete them */
5961 if (vxlan_sg
->sg
.src
.s_addr
== INADDR_ANY
) {
5962 if (vxlan_sg
->ref_cnt
)
5963 --vxlan_sg
->ref_cnt
;
5964 if (!vxlan_sg
->ref_cnt
)
5965 zebra_vxlan_sg_del(vxlan_sg
);
5969 static void zebra_vxlan_sg_cleanup(struct hash_bucket
*bucket
, void *arg
)
5971 struct zebra_vxlan_sg
*vxlan_sg
= (struct zebra_vxlan_sg
*)bucket
->data
;
5973 zebra_vxlan_sg_del(vxlan_sg
);
5976 static void zebra_vxlan_cleanup_sg_table(struct zebra_vrf
*zvrf
)
5978 /* increment the ref count against (*,G) to prevent them from being
5981 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_xg_pre_cleanup
, NULL
);
5983 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_cleanup
, NULL
);
5985 /* decrement the dummy ref count against the XG entries */
5986 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_xg_post_cleanup
, NULL
);
5989 static void zebra_vxlan_sg_replay_send(struct hash_bucket
*bucket
, void *arg
)
5991 struct zebra_vxlan_sg
*vxlan_sg
= (struct zebra_vxlan_sg
*)bucket
->data
;
5993 zebra_vxlan_sg_send(vxlan_sg
->zvrf
, &vxlan_sg
->sg
,
5994 vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_ADD
);
5997 /* Handle message from client to replay vxlan SG entries */
5998 void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS
)
6000 if (IS_ZEBRA_DEBUG_VXLAN
)
6001 zlog_debug("VxLAN SG updates to PIM, start");
6003 SET_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
);
6005 if (!EVPN_ENABLED(zvrf
)) {
6006 if (IS_ZEBRA_DEBUG_VXLAN
)
6007 zlog_debug("VxLAN SG replay request on unexpected vrf %d",
6012 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_replay_send
, NULL
);
6016 /* Cleanup EVPN configuration of a specific VRF */
6017 static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf
*zvrf
)
6019 struct zebra_l3vni
*zl3vni
= NULL
;
6021 zvrf
->advertise_all_vni
= 0;
6022 zvrf
->advertise_gw_macip
= 0;
6023 zvrf
->advertise_svi_macip
= 0;
6024 zvrf
->vxlan_flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
6026 hash_iterate(zvrf
->evpn_table
, zebra_evpn_cfg_cleanup
, NULL
);
6029 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6031 /* delete and uninstall all rmacs */
6032 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
6034 /* delete and uninstall all next-hops */
6035 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
6040 /* Cleanup BGP EVPN configuration upon client disconnect */
6041 static int zebra_evpn_bgp_cfg_clean_up(struct zserv
*client
)
6044 struct zebra_vrf
*zvrf
;
6046 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
6049 zebra_evpn_vrf_cfg_cleanup(zvrf
);
6055 static int zebra_evpn_pim_cfg_clean_up(struct zserv
*client
)
6057 struct zebra_vrf
*zvrf
= zebra_vrf_get_evpn();
6059 if (CHECK_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
)) {
6060 if (IS_ZEBRA_DEBUG_VXLAN
)
6061 zlog_debug("VxLAN SG updates to PIM, stop");
6062 UNSET_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
);
6068 static int zebra_evpn_cfg_clean_up(struct zserv
*client
)
6070 if (client
->proto
== ZEBRA_ROUTE_BGP
)
6071 return zebra_evpn_bgp_cfg_clean_up(client
);
6073 if (client
->proto
== ZEBRA_ROUTE_PIM
)
6074 return zebra_evpn_pim_cfg_clean_up(client
);
6080 * Handle results for vxlan dataplane operations.
6082 extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx
*ctx
)
6087 /* Config knob for accepting lower sequence numbers */
6088 void zebra_vxlan_set_accept_bgp_seq(bool set
)
6090 accept_bgp_seq
= set
;
6093 bool zebra_vxlan_get_accept_bgp_seq(void)
6095 return accept_bgp_seq
;
6098 /* Cleanup BGP EVPN configuration upon client disconnect */
6099 extern void zebra_evpn_init(void)
6101 hook_register(zserv_client_close
, zebra_evpn_cfg_clean_up
);