diff options
| author | Pat Ruddy <pat@voltanet.io> | 2020-08-10 17:40:48 +0100 | 
|---|---|---|
| committer | Pat Ruddy <pat@voltanet.io> | 2020-08-12 12:39:34 +0100 | 
| commit | 8b5fdf2e66611aaee2d8ea3d5694da0fbfeae5c2 (patch) | |
| tree | 22c536134c32cbfa8706541422a4121bf0053c8d | |
| parent | 6006414dc9a0bcd8fe33a05537adaaf3d998afe4 (diff) | |
zebra: extract core EVPN functions from zebra_vxlan.c
extract the core EVPN functions from zebra_vxlan.c and put them in
a new file zebra_evpn.c.
Signed-off-by: Pat Ruddy <pat@voltanet.io>
| -rw-r--r-- | zebra/subdir.am | 2 | ||||
| -rw-r--r-- | zebra/zebra_evpn.c | 6225 | ||||
| -rw-r--r-- | zebra/zebra_evpn.h | 61 | ||||
| -rw-r--r-- | zebra/zebra_evpn_mac.c | 2 | ||||
| -rw-r--r-- | zebra/zebra_evpn_mh.c | 4 | ||||
| -rw-r--r-- | zebra/zebra_evpn_neigh.c | 2 | ||||
| -rw-r--r-- | zebra/zebra_evpn_vxlan.h | 71 | ||||
| -rw-r--r-- | zebra/zebra_vxlan.c | 1714 | 
8 files changed, 408 insertions, 7673 deletions
diff --git a/zebra/subdir.am b/zebra/subdir.am index 2860a7e8e3..a6ef1537c0 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -80,6 +80,7 @@ zebra_zebra_SOURCES = \  	zebra/zebra_errors.c \  	zebra/zebra_gr.c \  	zebra/zebra_l2.c \ +	zebra/zebra_evpn.c \  	zebra/zebra_evpn_mac.c \  	zebra/zebra_evpn_neigh.c \  	zebra/zebra_mlag.c \ @@ -152,6 +153,7 @@ noinst_HEADERS += \  	zebra/zebra_evpn.h \  	zebra/zebra_evpn_mac.h \  	zebra/zebra_evpn_neigh.h \ +	zebra/zebra_evpn_vxlan.h \  	zebra/zebra_fpm_private.h \  	zebra/zebra_l2.h \  	zebra/zebra_memory.h \ diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c index 98f5688d2c..73df93258e 100644 --- a/zebra/zebra_evpn.c +++ b/zebra/zebra_evpn.c @@ -19,7 +19,6 @@   * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA   * 02111-1307, USA.   */ -  #include <zebra.h>  #include "hash.h" @@ -54,20 +53,12 @@  #include "zebra/zebra_evpn_neigh.h"  #include "zebra/zebra_vxlan_private.h"  #include "zebra/zebra_evpn_mh.h" +#include "zebra/zebra_evpn_vxlan.h"  #include "zebra/zebra_router.h" -DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix"); -DEFINE_MTYPE_STATIC(ZEBRA, ZEVPN, "EVPN hash"); -DEFINE_MTYPE_STATIC(ZEBRA, ZL3VNI, "L3 VNI hash"); -DEFINE_MTYPE_STATIC(ZEBRA, ZEVPN_VTEP, "EVPN remote VTEP/PTUN"); -DEFINE_MTYPE_STATIC(ZEBRA, L3VNI_MAC, "EVPN L3VNI MAC"); -DEFINE_MTYPE_STATIC(ZEBRA, L3NEIGH, "EVPN Neighbor"); -DEFINE_MTYPE_STATIC(ZEBRA, ZVXLAN_SG, "zebra VxLAN multicast group"); - -DEFINE_HOOK(zebra_rmac_update, (zebra_mac_t *rmac, zebra_l3vni_t *zl3vni, -	    bool delete, const char *reason), (rmac, zl3vni, delete, reason)) +DEFINE_MTYPE_STATIC(ZEBRA, ZEVPN, "VNI hash"); +DEFINE_MTYPE_STATIC(ZEBRA, ZEVPN_VTEP, "VNI remote VTEP"); -/* definitions */  /* PMSI strings. */  #define VXLAN_FLOOD_STR_NO_INFO "-"  #define VXLAN_FLOOD_STR_DEFAULT VXLAN_FLOOD_STR_NO_INFO @@ -78,138 +69,6 @@ static const struct message zvtep_flood_str[] = {  	{0}  }; -/* static function declarations */ -static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p, -				    uint16_t cmd); -static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket *bucket, -					    void **args); -static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty, -			    json_object *json); -static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty, -			      json_object *json); -static void zevpn_print_mac_hash_all_evpn(struct hash_bucket *bucket, void *ctxt); -static void zevpn_print(zebra_evpn_t *zevpn, void **ctxt); -static void zevpn_print_hash(struct hash_bucket *bucket, void *ctxt[]); - -static zebra_evpn_t *zevpn_from_svi(struct interface *ifp, -				  struct interface *br_if); -static struct interface *zevpn_map_to_macvlan(struct interface *br_if, -					     struct interface *svi_if); - -/* l3-vni next-hop neigh related APIs */ -static zebra_neigh_t *zl3vni_nh_lookup(zebra_l3vni_t *zl3vni, -				       const struct ipaddr *ip); -static void *zl3vni_nh_alloc(void *p); -static zebra_neigh_t *zl3vni_nh_add(zebra_l3vni_t *zl3vni, -				    const struct ipaddr *vtep_ip, -				    const struct ethaddr *rmac); -static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n); -static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n); -static int zl3vni_nh_uninstall(zebra_l3vni_t *zl3vni, zebra_neigh_t *n); - -/* l3-vni rmac related APIs */ -static void zl3vni_print_rmac_hash(struct hash_bucket *, void *); -static zebra_mac_t *zl3vni_rmac_lookup(zebra_l3vni_t *zl3vni, -				       const struct ethaddr *rmac); -static void *zl3vni_rmac_alloc(void *p); -static zebra_mac_t *zl3vni_rmac_add(zebra_l3vni_t *zl3vni, -				    const struct ethaddr *rmac); -static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac); -static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac); -static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac); - -/* l3-vni related APIs*/ -static zebra_l3vni_t *zl3vni_lookup(vni_t vni); -static void *zl3vni_alloc(void *p); -static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id); -static int zl3vni_del(zebra_l3vni_t *zl3vni); -static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni); -static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni); - -static zebra_evpn_t *zevpn_map_vlan(struct interface *ifp, -				  struct interface *br_if, vlanid_t vid); -static void zevpn_install_mac_hash(struct hash_bucket *bucket, void *ctxt); - -static unsigned int evpn_hash_keymake(const void *p); -static void *zevpn_alloc(void *p); -static zebra_evpn_t *zevpn_add(vni_t vni); -static int zevpn_del(zebra_evpn_t *zevpn); -static int zevpn_send_add_to_client(zebra_evpn_t *zevpn); -static int zevpn_send_del_to_client(zebra_evpn_t *zevpn); -static void zevpn_build_hash_table(void); -static int zevpn_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep); -static zebra_vtep_t *zevpn_vtep_find(zebra_evpn_t *zevpn, struct in_addr *vtep_ip); -static zebra_vtep_t *zevpn_vtep_add(zebra_evpn_t *zevpn, struct in_addr *vtep_ip, -		int flood_control); -static int zevpn_vtep_del(zebra_evpn_t *zevpn, zebra_vtep_t *zvtep); -static int zevpn_vtep_del_all(zebra_evpn_t *zevpn, int uninstall); -static int zevpn_vtep_install(zebra_evpn_t *zevpn, zebra_vtep_t *zvtep); -static int zevpn_vtep_uninstall(zebra_evpn_t *zevpn, struct in_addr *vtep_ip); -static int zevpn_del_macip_for_intf(struct interface *ifp, zebra_evpn_t *zevpn); -static int zevpn_add_macip_for_intf(struct interface *ifp, zebra_evpn_t *zevpn); -static int zevpn_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn, -			     struct ethaddr *macaddr, struct ipaddr *ip); -static int zevpn_gw_macip_del(struct interface *ifp, zebra_evpn_t *zevpn, -			     struct ipaddr *ip); -struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp); -static unsigned int zebra_vxlan_sg_hash_key_make(const void *p); -static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2); -static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf, -		struct in_addr sip, struct in_addr mcast_grp); -static zebra_vxlan_sg_t *zebra_vxlan_sg_do_ref(struct zebra_vrf *vrf, -				struct in_addr sip, struct in_addr mcast_grp); -static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip, -				struct in_addr mcast_grp); -static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip, -				struct in_addr mcast_grp); -static void zebra_vxlan_sg_cleanup(struct hash_bucket *bucket, void *arg); - -/* Private functions */ -static int host_rb_entry_compare(const struct host_rb_entry *hle1, -				 const struct host_rb_entry *hle2) -{ -	if (hle1->p.family < hle2->p.family) -		return -1; - -	if (hle1->p.family > hle2->p.family) -		return 1; - -	if (hle1->p.prefixlen < hle2->p.prefixlen) -		return -1; - -	if (hle1->p.prefixlen > hle2->p.prefixlen) -		return 1; - -	if (hle1->p.family == AF_INET) { -		if (hle1->p.u.prefix4.s_addr < hle2->p.u.prefix4.s_addr) -			return -1; - -		if (hle1->p.u.prefix4.s_addr > hle2->p.u.prefix4.s_addr) -			return 1; - -		return 0; -	} else if (hle1->p.family == AF_INET6) { -		return memcmp(&hle1->p.u.prefix6, &hle2->p.u.prefix6, -			      IPV6_MAX_BYTELEN); -	} else { -		zlog_debug("%s: Unexpected family type: %d", __func__, -			   hle1->p.family); -		return 0; -	} -} -RB_GENERATE(host_rb_tree_entry, host_rb_entry, hl_entry, host_rb_entry_compare); - -static uint32_t rb_host_count(struct host_rb_tree_entry *hrbe) -{ -	struct host_rb_entry *hle; -	uint32_t count = 0; - -	RB_FOREACH (hle, host_rb_tree_entry, hrbe) -		count++; - -	return count; -} -  int advertise_gw_macip_enabled(zebra_evpn_t *zevpn)  {  	struct zebra_vrf *zvrf; @@ -239,567 +98,9 @@ int advertise_svi_macip_enabled(zebra_evpn_t *zevpn)  }  /* - * Print neighbors for all EVPN. - */ -static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket *bucket, -					  void **args) -{ -	struct vty *vty; -	json_object *json = NULL, *json_evpn = NULL; -	zebra_evpn_t *zevpn; -	uint32_t num_neigh; -	struct neigh_walk_ctx wctx; -	char vni_str[VNI_STR_LEN]; -	uint32_t print_dup; - -	vty = (struct vty *)args[0]; -	json = (json_object *)args[1]; -	print_dup = (uint32_t)(uintptr_t)args[2]; - -	zevpn = (zebra_evpn_t *)bucket->data; - -	num_neigh = hashcount(zevpn->neigh_table); - -	if (print_dup) -		num_neigh = num_dup_detected_neighs(zevpn); - -	if (json == NULL) { -		vty_out(vty, -			"\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n", -			zevpn->vni, num_neigh); -	} else { -		json_evpn = json_object_new_object(); -		json_object_int_add(json_evpn, "numArpNd", num_neigh); -		snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni); -	} - -	if (!num_neigh) { -		if (json) -			json_object_object_add(json, vni_str, json_evpn); -		return; -	} - -	/* Since we have IPv6 addresses to deal with which can vary widely in -	 * size, we try to be a bit more elegant in display by first computing -	 * the maximum width. -	 */ -	memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); -	wctx.zevpn = zevpn; -	wctx.vty = vty; -	wctx.addr_width = 15; -	wctx.json = json_evpn; -	hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width, -		     &wctx); - -	if (json == NULL) -		zebra_evpn_print_neigh_hdr(vty, &wctx); - -	if (print_dup) -		hash_iterate(zevpn->neigh_table, -			     zebra_evpn_print_dad_neigh_hash, &wctx); -	else -		hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash, -			     &wctx); - -	if (json) -		json_object_object_add(json, vni_str, json_evpn); -} - -/* - * Print neighbors for all EVPNs in detail. - */ -static void zevpn_print_neigh_hash_all_evpn_detail(struct hash_bucket *bucket, -						 void **args) -{ -	struct vty *vty; -	json_object *json = NULL, *json_evpn = NULL; -	zebra_evpn_t *zevpn; -	uint32_t num_neigh; -	struct neigh_walk_ctx wctx; -	char vni_str[VNI_STR_LEN]; -	uint32_t print_dup; - -	vty = (struct vty *)args[0]; -	json = (json_object *)args[1]; -	print_dup = (uint32_t)(uintptr_t)args[2]; - -	zevpn = (zebra_evpn_t *)bucket->data; -	if (!zevpn) { -		if (json) -			vty_out(vty, "{}\n"); -		return; -	} -	num_neigh = hashcount(zevpn->neigh_table); - -	if (print_dup && num_dup_detected_neighs(zevpn) == 0) -		return; - -	if (json == NULL) { -		vty_out(vty, -			"\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n", -			zevpn->vni, num_neigh); -	} else { -		json_evpn = json_object_new_object(); -		json_object_int_add(json_evpn, "numArpNd", num_neigh); -		snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni); -	} -	if (!num_neigh) { -		if (json) -			json_object_object_add(json, vni_str, json_evpn); -		return; -	} - -	memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); -	wctx.zevpn = zevpn; -	wctx.vty = vty; -	wctx.addr_width = 15; -	wctx.json = json_evpn; - -	if (print_dup) -		hash_iterate(zevpn->neigh_table, -			     zebra_evpn_print_dad_neigh_hash_detail, &wctx); -	else -		hash_iterate(zevpn->neigh_table, -			     zebra_evpn_print_neigh_hash_detail, &wctx); - -	if (json) -		json_object_object_add(json, vni_str, json_evpn); -} - -/* print a specific next hop for an l3vni */ -static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty, -			    json_object *json) -{ -	char buf1[ETHER_ADDR_STRLEN]; -	char buf2[INET6_ADDRSTRLEN]; -	json_object *json_hosts = NULL; -	struct host_rb_entry *hle; - -	if (!json) { -		vty_out(vty, "Ip: %s\n", -			ipaddr2str(&n->ip, buf2, sizeof(buf2))); -		vty_out(vty, "  RMAC: %s\n", -			prefix_mac2str(&n->emac, buf1, sizeof(buf1))); -		vty_out(vty, "  Refcount: %d\n", -			rb_host_count(&n->host_rb)); -		vty_out(vty, "  Prefixes:\n"); -		RB_FOREACH (hle, host_rb_tree_entry, &n->host_rb) -			vty_out(vty, "    %s\n", -				prefix2str(&hle->p, buf2, sizeof(buf2))); -	} else { -		json_hosts = json_object_new_array(); -		json_object_string_add( -			json, "ip", ipaddr2str(&(n->ip), buf2, sizeof(buf2))); -		json_object_string_add( -			json, "routerMac", -			prefix_mac2str(&n->emac, buf2, sizeof(buf2))); -		json_object_int_add(json, "refCount", -				    rb_host_count(&n->host_rb)); -		RB_FOREACH (hle, host_rb_tree_entry, &n->host_rb) -			json_object_array_add(json_hosts, -					      json_object_new_string(prefix2str( -										&hle->p, buf2, sizeof(buf2)))); -		json_object_object_add(json, "prefixList", json_hosts); -	} -} - -/* Print a specific RMAC entry */ -static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty, -			      json_object *json) -{ -	char buf1[ETHER_ADDR_STRLEN]; -	char buf2[PREFIX_STRLEN]; -	json_object *json_hosts = NULL; -	struct host_rb_entry *hle; - -	if (!json) { -		vty_out(vty, "MAC: %s\n", -			prefix_mac2str(&zrmac->macaddr, buf1, sizeof(buf1))); -		vty_out(vty, " Remote VTEP: %s\n", -			inet_ntoa(zrmac->fwd_info.r_vtep_ip)); -		vty_out(vty, " Refcount: %d\n", rb_host_count(&zrmac->host_rb)); -		vty_out(vty, "  Prefixes:\n"); -		RB_FOREACH (hle, host_rb_tree_entry, &zrmac->host_rb) -			vty_out(vty, "    %s\n", -				prefix2str(&hle->p, buf2, sizeof(buf2))); -	} else { -		json_hosts = json_object_new_array(); -		json_object_string_add( -			json, "routerMac", -			prefix_mac2str(&zrmac->macaddr, buf1, sizeof(buf1))); -		json_object_string_add(json, "vtepIp", -				       inet_ntoa(zrmac->fwd_info.r_vtep_ip)); -		json_object_int_add(json, "refCount", -				    rb_host_count(&zrmac->host_rb)); -		json_object_int_add(json, "localSequence", zrmac->loc_seq); -		json_object_int_add(json, "remoteSequence", zrmac->rem_seq); -		RB_FOREACH (hle, host_rb_tree_entry, &zrmac->host_rb) -			json_object_array_add( -				json_hosts, -				json_object_new_string(prefix2str( -					&hle->p, buf2, sizeof(buf2)))); -		json_object_object_add(json, "prefixList", json_hosts); -	} -} - -/* - * Print MACs for all EVPNs. - */ -static void zevpn_print_mac_hash_all_evpn(struct hash_bucket *bucket, void *ctxt) -{ -	struct vty *vty; -	json_object *json = NULL, *json_evpn = NULL; -	json_object *json_mac = NULL; -	zebra_evpn_t *zevpn; -	uint32_t num_macs; -	struct mac_walk_ctx *wctx = ctxt; -	char vni_str[VNI_STR_LEN]; - -	vty = wctx->vty; -	json = wctx->json; - -	zevpn = (zebra_evpn_t *)bucket->data; -	wctx->zevpn = zevpn; - -	/*We are iterating over a new VNI, set the count to 0*/ -	wctx->count = 0; - -	num_macs = num_valid_macs(zevpn); -	if (!num_macs) -		return; - -	if (wctx->print_dup) -		num_macs = num_dup_detected_macs(zevpn); - -	if (json) { -		json_evpn = json_object_new_object(); -		json_mac = json_object_new_object(); -		snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni); -	} - -	if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) { -		if (json == NULL) { -			vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n", -				zevpn->vni, num_macs); -			vty_out(vty, -				"Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n"); -			vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC", -				"Type", "Flags", "Intf/Remote ES/VTEP", -				"VLAN", "Seq #'s"); -		} else -			json_object_int_add(json_evpn, "numMacs", num_macs); -	} - -	if (!num_macs) { -		if (json) { -			json_object_int_add(json_evpn, "numMacs", num_macs); -			json_object_object_add(json, vni_str, json_evpn); -		} -		return; -	} - -	/* assign per-evpn to wctx->json object to fill macs -	 * under the evpn. Re-assign primary json object to fill -	 * next evpn information. -	 */ -	wctx->json = json_mac; -	if (wctx->print_dup) -		hash_iterate(zevpn->mac_table, zebra_evpn_print_dad_mac_hash, -			     wctx); -	else -		hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, wctx); -	wctx->json = json; -	if (json) { -		if (wctx->count) -			json_object_object_add(json_evpn, "macs", json_mac); -		json_object_object_add(json, vni_str, json_evpn); -	} -} - -/* - * Print MACs in detail for all EVPNs. - */ -static void zevpn_print_mac_hash_all_evpn_detail(struct hash_bucket *bucket, -					       void *ctxt) -{ -	struct vty *vty; -	json_object *json = NULL, *json_evpn = NULL; -	json_object *json_mac = NULL; -	zebra_evpn_t *zevpn; -	uint32_t num_macs; -	struct mac_walk_ctx *wctx = ctxt; -	char vni_str[VNI_STR_LEN]; - -	vty = wctx->vty; -	json = wctx->json; - -	zevpn = (zebra_evpn_t *)bucket->data; -	if (!zevpn) { -		if (json) -			vty_out(vty, "{}\n"); -		return; -	} -	wctx->zevpn = zevpn; - -	/*We are iterating over a new EVPN, set the count to 0*/ -	wctx->count = 0; - -	num_macs = num_valid_macs(zevpn); -	if (!num_macs) -		return; - -	if (wctx->print_dup && (num_dup_detected_macs(zevpn) == 0)) -		return; - -	if (json) { -		json_evpn = json_object_new_object(); -		json_mac = json_object_new_object(); -		snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni); -	} - -	if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) { -		if (json == NULL) { -			vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n", -				zevpn->vni, num_macs); -		} else -			json_object_int_add(json_evpn, "numMacs", num_macs); -	} -	/* assign per-evpn to wctx->json object to fill macs -	 * under the evpn. Re-assign primary json object to fill -	 * next evpn information. -	 */ -	wctx->json = json_mac; -	if (wctx->print_dup) -		hash_iterate(zevpn->mac_table, -			     zebra_evpn_print_dad_mac_hash_detail, wctx); -	else -		hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash_detail, -			     wctx); -	wctx->json = json; -	if (json) { -		if (wctx->count) -			json_object_object_add(json_evpn, "macs", json_mac); -		json_object_object_add(json, vni_str, json_evpn); -	} -} - -static void zl3vni_print_nh_hash(struct hash_bucket *bucket, void *ctx) -{ -	struct nh_walk_ctx *wctx = NULL; -	struct vty *vty = NULL; -	struct json_object *json_evpn = NULL; -	struct json_object *json_nh = NULL; -	zebra_neigh_t *n = NULL; -	char buf1[ETHER_ADDR_STRLEN]; -	char buf2[INET6_ADDRSTRLEN]; - -	wctx = (struct nh_walk_ctx *)ctx; -	vty = wctx->vty; -	json_evpn = wctx->json; -	if (json_evpn) -		json_nh = json_object_new_object(); -	n = (zebra_neigh_t *)bucket->data; - -	if (!json_evpn) { -		vty_out(vty, "%-15s %-17s\n", -			ipaddr2str(&(n->ip), buf2, sizeof(buf2)), -			prefix_mac2str(&n->emac, buf1, sizeof(buf1))); -	} else { -		json_object_string_add(json_nh, "nexthopIp", -				       ipaddr2str(&n->ip, buf2, sizeof(buf2))); -		json_object_string_add( -			json_nh, "routerMac", -			prefix_mac2str(&n->emac, buf1, sizeof(buf1))); -		json_object_object_add(json_evpn, -				       ipaddr2str(&(n->ip), buf2, sizeof(buf2)), -				       json_nh); -	} -} - -static void zl3vni_print_nh_hash_all_vni(struct hash_bucket *bucket, -					 void **args) -{ -	struct vty *vty = NULL; -	json_object *json = NULL; -	json_object *json_evpn = NULL; -	zebra_l3vni_t *zl3vni = NULL; -	uint32_t num_nh = 0; -	struct nh_walk_ctx wctx; -	char vni_str[VNI_STR_LEN]; - -	vty = (struct vty *)args[0]; -	json = (struct json_object *)args[1]; - -	zl3vni = (zebra_l3vni_t *)bucket->data; - -	num_nh = hashcount(zl3vni->nh_table); -	if (!num_nh) -		return; - -	if (json) { -		json_evpn = json_object_new_object(); -		snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni); -	} - -	if (json == NULL) { -		vty_out(vty, "\nVNI %u #Next-Hops %u\n\n", zl3vni->vni, num_nh); -		vty_out(vty, "%-15s %-17s\n", "IP", "RMAC"); -	} else -		json_object_int_add(json_evpn, "numNextHops", num_nh); - -	memset(&wctx, 0, sizeof(struct nh_walk_ctx)); -	wctx.vty = vty; -	wctx.json = json_evpn; -	hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx); -	if (json) -		json_object_object_add(json, vni_str, json_evpn); -} - -static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket *bucket, -					   void **args) -{ -	struct vty *vty = NULL; -	json_object *json = NULL; -	json_object *json_evpn = NULL; -	zebra_l3vni_t *zl3vni = NULL; -	uint32_t num_rmacs; -	struct rmac_walk_ctx wctx; -	char vni_str[VNI_STR_LEN]; - -	vty = (struct vty *)args[0]; -	json = (struct json_object *)args[1]; - -	zl3vni = (zebra_l3vni_t *)bucket->data; - -	num_rmacs = hashcount(zl3vni->rmac_table); -	if (!num_rmacs) -		return; - -	if (json) { -		json_evpn = json_object_new_object(); -		snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni); -	} - -	if (json == NULL) { -		vty_out(vty, "\nVNI %u #RMACs %u\n\n", zl3vni->vni, num_rmacs); -		vty_out(vty, "%-17s %-21s\n", "RMAC", "Remote VTEP"); -	} else -		json_object_int_add(json_evpn, "numRmacs", num_rmacs); - -	/* assign per-vni to wctx->json object to fill macs -	 * under the vni. Re-assign primary json object to fill -	 * next vni information. -	 */ -	memset(&wctx, 0, sizeof(struct rmac_walk_ctx)); -	wctx.vty = vty; -	wctx.json = json_evpn; -	hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx); -	if (json) -		json_object_object_add(json, vni_str, json_evpn); -} - -static void zl3vni_print_rmac_hash(struct hash_bucket *bucket, void *ctx) -{ -	zebra_mac_t *zrmac = NULL; -	struct rmac_walk_ctx *wctx = NULL; -	struct vty *vty = NULL; -	struct json_object *json = NULL; -	struct json_object *json_rmac = NULL; -	char buf[ETHER_ADDR_STRLEN]; - -	wctx = (struct rmac_walk_ctx *)ctx; -	vty = wctx->vty; -	json = wctx->json; -	if (json) -		json_rmac = json_object_new_object(); -	zrmac = (zebra_mac_t *)bucket->data; - -	if (!json) { -		vty_out(vty, "%-17s %-21s\n", -			prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)), -			inet_ntoa(zrmac->fwd_info.r_vtep_ip)); -	} else { -		json_object_string_add( -			json_rmac, "routerMac", -			prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf))); -		json_object_string_add(json_rmac, "vtepIp", -				       inet_ntoa(zrmac->fwd_info.r_vtep_ip)); -		json_object_object_add( -			json, prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)), -			json_rmac); -	} -} - -/* print a specific L3 VNI entry */ -static void zl3vni_print(zebra_l3vni_t *zl3vni, void **ctx) -{ -	char buf[ETHER_ADDR_STRLEN]; -	struct vty *vty = NULL; -	json_object *json = NULL; -	zebra_evpn_t *zevpn = NULL; -	json_object *json_evpn_list = NULL; -	struct listnode *node = NULL, *nnode = NULL; - -	vty = ctx[0]; -	json = ctx[1]; - -	if (!json) { -		vty_out(vty, "VNI: %u\n", zl3vni->vni); -		vty_out(vty, "  Type: %s\n", "L3"); -		vty_out(vty, "  Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni)); -		vty_out(vty, "  Local Vtep Ip: %s\n", -			inet_ntoa(zl3vni->local_vtep_ip)); -		vty_out(vty, "  Vxlan-Intf: %s\n", -			zl3vni_vxlan_if_name(zl3vni)); -		vty_out(vty, "  SVI-If: %s\n", zl3vni_svi_if_name(zl3vni)); -		vty_out(vty, "  State: %s\n", zl3vni_state2str(zl3vni)); -		vty_out(vty, "  VNI Filter: %s\n", -			CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY) -				? "prefix-routes-only" -				: "none"); -		vty_out(vty, "  System MAC: %s\n", -			zl3vni_sysmac2str(zl3vni, buf, sizeof(buf))); -		vty_out(vty, "  Router MAC: %s\n", -			zl3vni_rmac2str(zl3vni, buf, sizeof(buf))); -		vty_out(vty, "  L2 VNIs: "); -		for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zevpn)) -			vty_out(vty, "%u ", zevpn->vni); -		vty_out(vty, "\n"); -	} else { -		json_evpn_list = json_object_new_array(); -		json_object_int_add(json, "vni", zl3vni->vni); -		json_object_string_add(json, "type", "L3"); -		json_object_string_add(json, "localVtepIp", -				       inet_ntoa(zl3vni->local_vtep_ip)); -		json_object_string_add(json, "vxlanIntf", -				       zl3vni_vxlan_if_name(zl3vni)); -		json_object_string_add(json, "sviIntf", -				       zl3vni_svi_if_name(zl3vni)); -		json_object_string_add(json, "state", zl3vni_state2str(zl3vni)); -		json_object_string_add(json, "vrf", zl3vni_vrf_name(zl3vni)); -		json_object_string_add( -			json, "sysMac", -			zl3vni_sysmac2str(zl3vni, buf, sizeof(buf))); -		json_object_string_add( -			json, "routerMac", -			zl3vni_rmac2str(zl3vni, buf, sizeof(buf))); -		json_object_string_add( -			json, "vniFilter", -			CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY) -				? "prefix-routes-only" -				: "none"); -		for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zevpn)) { -			json_object_array_add(json_evpn_list, -					      json_object_new_int(zevpn->vni)); -		} -		json_object_object_add(json, "l2Vnis", json_evpn_list); -	} -} - -/*   * Print a specific EVPN entry.   */ -static void zevpn_print(zebra_evpn_t *zevpn, void **ctxt) +void zebra_evpn_print(zebra_evpn_t *zevpn, void **ctxt)  {  	struct vty *vty;  	zebra_vtep_t *zvtep; @@ -891,80 +192,10 @@ static void zevpn_print(zebra_evpn_t *zevpn, void **ctxt)  	}  } -/* print a L3 VNI hash entry */ -static void zl3vni_print_hash(struct hash_bucket *bucket, void *ctx[]) -{ -	struct vty *vty = NULL; -	json_object *json = NULL; -	json_object *json_evpn = NULL; -	zebra_l3vni_t *zl3vni = NULL; - -	vty = (struct vty *)ctx[0]; -	json = (json_object *)ctx[1]; - -	zl3vni = (zebra_l3vni_t *)bucket->data; - -	if (!json) { -		vty_out(vty, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n", -			zl3vni->vni, "L3", zl3vni_vxlan_if_name(zl3vni), -			hashcount(zl3vni->rmac_table), -			hashcount(zl3vni->nh_table), "n/a", -			zl3vni_vrf_name(zl3vni)); -	} else { -		char vni_str[VNI_STR_LEN]; - -		snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni); -		json_evpn = json_object_new_object(); -		json_object_int_add(json_evpn, "vni", zl3vni->vni); -		json_object_string_add(json_evpn, "vxlanIf", -				       zl3vni_vxlan_if_name(zl3vni)); -		json_object_int_add(json_evpn, "numMacs", -				    hashcount(zl3vni->rmac_table)); -		json_object_int_add(json_evpn, "numArpNd", -				    hashcount(zl3vni->nh_table)); -		json_object_string_add(json_evpn, "numRemoteVteps", "n/a"); -		json_object_string_add(json_evpn, "type", "L3"); -		json_object_string_add(json_evpn, "tenantVrf", -				       zl3vni_vrf_name(zl3vni)); -		json_object_object_add(json, vni_str, json_evpn); -	} -} - -/* Private Structure to pass callback data for hash iterator */ -struct zevpn_show { -	struct vty *vty; -	json_object *json; -	struct zebra_vrf *zvrf; -	bool use_json; -}; - -/* print a L3 VNI hash entry in detail*/ -static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data) -{ -	struct vty *vty = NULL; -	zebra_l3vni_t *zl3vni = NULL; -	json_object *json_array = NULL; -	bool use_json = false; -	struct zevpn_show *zes = data; - -	vty = zes->vty; -	json_array = zes->json; -	use_json = zes->use_json; - -	zl3vni = (zebra_l3vni_t *)bucket->data; - -	zebra_vxlan_print_vni(vty, zes->zvrf, zl3vni->vni, -		use_json, json_array); - -	if (!use_json) -		vty_out(vty, "\n"); -} - -  /*   * Print an EVPN hash entry - called for display of all VNIs.   */ -static void zevpn_print_hash(struct hash_bucket *bucket, void *ctxt[]) +void zebra_evpn_print_hash(struct hash_bucket *bucket, void *ctxt[])  {  	struct vty *vty;  	zebra_evpn_t *zevpn; @@ -1028,13 +259,13 @@ static void zevpn_print_hash(struct hash_bucket *bucket, void *ctxt[])  /*   * Print an EVPN hash entry in detail - called for display of all EVPNs.   */ -static void zevpn_print_hash_detail(struct hash_bucket *bucket, void *data) +void zebra_evpn_print_hash_detail(struct hash_bucket *bucket, void *data)  {  	struct vty *vty;  	zebra_evpn_t *zevpn;  	json_object *json_array = NULL;  	bool use_json = false; -	struct zevpn_show *zes = data; +	struct zebra_evpn_show *zes = data;  	vty = zes->vty;  	json_array = zes->json; @@ -1048,32 +279,7 @@ static void zevpn_print_hash_detail(struct hash_bucket *bucket, void *data)  		vty_out(vty, "\n");  } -/* Get the VRR interface for SVI if any */ -struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp) -{ -	struct zebra_vrf *zvrf = NULL; -	struct interface *tmp_if = NULL; -	struct zebra_if *zif = NULL; - -	zvrf = vrf_info_lookup(ifp->vrf_id); -	assert(zvrf); - -	FOR_ALL_INTERFACES (zvrf->vrf, tmp_if) { -		zif = tmp_if->info; -		if (!zif) -			continue; - -		if (!IS_ZEBRA_IF_MACVLAN(tmp_if)) -			continue; - -		if (zif->link == ifp) -			return tmp_if; -	} - -	return NULL; -} - -static int zevpn_del_macip_for_intf(struct interface *ifp, zebra_evpn_t *zevpn) +int zebra_evpn_del_macip_for_intf(struct interface *ifp, zebra_evpn_t *zevpn)  {  	struct listnode *cnode = NULL, *cnnode = NULL;  	struct connected *c = NULL; @@ -1100,13 +306,13 @@ static int zevpn_del_macip_for_intf(struct interface *ifp, zebra_evpn_t *zevpn)  			continue;  		} -		zevpn_gw_macip_del(ifp, zevpn, &ip); +		zebra_evpn_gw_macip_del(ifp, zevpn, &ip);  	}  	return 0;  } -static int zevpn_add_macip_for_intf(struct interface *ifp, zebra_evpn_t *zevpn) +int zebra_evpn_add_macip_for_intf(struct interface *ifp, zebra_evpn_t *zevpn)  {  	struct listnode *cnode = NULL, *cnnode = NULL;  	struct connected *c = NULL; @@ -1133,14 +339,47 @@ static int zevpn_add_macip_for_intf(struct interface *ifp, zebra_evpn_t *zevpn)  			continue;  		} -		zevpn_gw_macip_add(ifp, zevpn, &macaddr, &ip); +		zebra_evpn_gw_macip_add(ifp, zevpn, &macaddr, &ip);  	}  	return 0;  } +static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p, +				    uint16_t cmd) +{ +	struct zserv *client = NULL; +	struct stream *s = NULL; +	char buf[PREFIX_STRLEN]; + +	client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); +	/* BGP may not be running. */ +	if (!client) +		return 0; + +	s = stream_new(ZEBRA_MAX_PACKET_SIZ); + +	zclient_create_header(s, cmd, vrf_id); +	stream_put(s, p, sizeof(struct prefix)); + +	/* Write packet size. */ +	stream_putw_at(s, 0, stream_get_endp(s)); + +	if (IS_ZEBRA_DEBUG_VXLAN) +		zlog_debug("Send ip prefix %s %s on vrf %s", +			   prefix2str(p, buf, sizeof(buf)), +			   (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) ? "ADD" : "DEL", +			   vrf_id_to_name(vrf_id)); + +	if (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) +		client->prefixadd_cnt++; +	else +		client->prefixdel_cnt++; + +	return zserv_send_message(client, s); +} -static int zevpn_advertise_subnet(zebra_evpn_t *zevpn, struct interface *ifp, -				 int advertise) +int zebra_evpn_advertise_subnet(zebra_evpn_t *zevpn, struct interface *ifp, +				int advertise)  {  	struct listnode *cnode = NULL, *cnnode = NULL;  	struct connected *c = NULL; @@ -1169,10 +408,10 @@ static int zevpn_advertise_subnet(zebra_evpn_t *zevpn, struct interface *ifp,  }  /* - * zevpn_gw_macip_add_to_client + * zebra_evpn_gw_macip_add_to_client   */ -static int zevpn_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn, -			     struct ethaddr *macaddr, struct ipaddr *ip) +int zebra_evpn_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn, +			    struct ethaddr *macaddr, struct ipaddr *ip)  {  	zebra_mac_t *mac = NULL;  	struct zebra_if *zif = NULL; @@ -1193,10 +432,10 @@ static int zevpn_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,  }  /* - * zevpn_gw_macip_del_from_client + * zebra_evpn_gw_macip_del_from_client   */ -static int zevpn_gw_macip_del(struct interface *ifp, zebra_evpn_t *zevpn, -			     struct ipaddr *ip) +int zebra_evpn_gw_macip_del(struct interface *ifp, zebra_evpn_t *zevpn, +			    struct ipaddr *ip)  {  	char buf1[ETHER_ADDR_STRLEN];  	char buf2[INET6_ADDRSTRLEN]; @@ -1247,7 +486,7 @@ static int zevpn_gw_macip_del(struct interface *ifp, zebra_evpn_t *zevpn,  	return 0;  } -static void zevpn_gw_macip_del_for_evpn_hash(struct hash_bucket *bucket, +void zebra_evpn_gw_macip_del_for_evpn_hash(struct hash_bucket *bucket,  					   void *ctxt)  {  	zebra_evpn_t *zevpn = NULL; @@ -1287,17 +526,17 @@ static void zevpn_gw_macip_del_for_evpn_hash(struct hash_bucket *bucket,  		return;  	/* Del primary MAC-IP */ -	zevpn_del_macip_for_intf(vlan_if, zevpn); +	zebra_evpn_del_macip_for_intf(vlan_if, zevpn);  	/* Del VRR MAC-IP - if any*/  	vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);  	if (vrr_if) -		zevpn_del_macip_for_intf(vrr_if, zevpn); +		zebra_evpn_del_macip_for_intf(vrr_if, zevpn);  	return;  } -static void zevpn_gw_macip_add_for_evpn_hash(struct hash_bucket *bucket, +void zebra_evpn_gw_macip_add_for_evpn_hash(struct hash_bucket *bucket,  					   void *ctxt)  {  	zebra_evpn_t *zevpn = NULL; @@ -1325,20 +564,20 @@ static void zevpn_gw_macip_add_for_evpn_hash(struct hash_bucket *bucket,  		return;  	/* Add primary SVI MAC-IP */ -	zevpn_add_macip_for_intf(vlan_if, zevpn); +	zebra_evpn_add_macip_for_intf(vlan_if, zevpn);  	if (advertise_gw_macip_enabled(zevpn)) {  		/* Add VRR MAC-IP - if any*/  		vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);  		if (vrr_if) -			zevpn_add_macip_for_intf(vrr_if, zevpn); +			zebra_evpn_add_macip_for_intf(vrr_if, zevpn);  	}  	return;  } -static void zevpn_svi_macip_del_for_evpn_hash(struct hash_bucket *bucket, -					   void *ctxt) +void zebra_evpn_svi_macip_del_for_evpn_hash(struct hash_bucket *bucket, +					    void *ctxt)  {  	zebra_evpn_t *zevpn = NULL;  	struct zebra_if *zif = NULL; @@ -1378,7 +617,7 @@ static void zevpn_svi_macip_del_for_evpn_hash(struct hash_bucket *bucket,  		return;  	/* Del primary MAC-IP */ -	zevpn_del_macip_for_intf(vlan_if, zevpn); +	zebra_evpn_del_macip_for_intf(vlan_if, zevpn);  	return;  } @@ -1387,7 +626,7 @@ static void zevpn_svi_macip_del_for_evpn_hash(struct hash_bucket *bucket,   * Map port or (port, VLAN) to an EVPN. This is invoked upon getting MAC   * notifications, to see if they are of interest.   */ -static zebra_evpn_t *zevpn_map_vlan(struct interface *ifp, +zebra_evpn_t *zebra_evpn_map_vlan(struct interface *ifp,  				  struct interface *br_if, vlanid_t vid)  {  	struct zebra_ns *zns; @@ -1432,15 +671,15 @@ static zebra_evpn_t *zevpn_map_vlan(struct interface *ifp,  	if (!found)  		return NULL; -	zevpn = zevpn_lookup(vxl->vni); +	zevpn = zebra_evpn_lookup(vxl->vni);  	return zevpn;  }  /* - * Map SVI and associated bridge to a VNI. This is invoked upon getting + * Map SVI and associated bridge to an EVPN. This is invoked upon getting   * neighbor notifications, to see if they are of interest.   */ -static zebra_evpn_t *zevpn_from_svi(struct interface *ifp, +zebra_evpn_t *zebra_evpn_from_svi(struct interface *ifp,  				  struct interface *br_if)  {  	struct zebra_ns *zns; @@ -1504,69 +743,14 @@ static zebra_evpn_t *zevpn_from_svi(struct interface *ifp,  	if (!found)  		return NULL; -	zevpn = zevpn_lookup(vxl->vni); +	zevpn = zebra_evpn_lookup(vxl->vni);  	return zevpn;  } -/* Map to SVI on bridge corresponding to specified VLAN. This can be one - * of two cases: - * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface - * linked to the bridge - * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge interface - * itself - */ -struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if) -{ -	struct zebra_ns *zns; -	struct route_node *rn; -	struct interface *tmp_if = NULL; -	struct zebra_if *zif; -	struct zebra_l2info_bridge *br; -	struct zebra_l2info_vlan *vl; -	uint8_t bridge_vlan_aware; -	int found = 0; - -	/* Defensive check, caller expected to invoke only with valid bridge. */ -	if (!br_if) -		return NULL; - -	/* Determine if bridge is VLAN-aware or not */ -	zif = br_if->info; -	assert(zif); -	br = &zif->l2info.br; -	bridge_vlan_aware = br->vlan_aware; - -	/* Check oper status of the SVI. */ -	if (!bridge_vlan_aware) -		return if_is_operative(br_if) ? br_if : NULL; - -	/* Identify corresponding VLAN interface. */ -	/* TODO: Optimize with a hash. */ -	zns = zebra_ns_lookup(NS_DEFAULT); -	for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { -		tmp_if = (struct interface *)rn->info; -		/* Check oper status of the SVI. */ -		if (!tmp_if || !if_is_operative(tmp_if)) -			continue; -		zif = tmp_if->info; -		if (!zif || zif->zif_type != ZEBRA_IF_VLAN -		    || zif->link != br_if) -			continue; -		vl = &zif->l2info.vl; - -		if (vl->vid == vid) { -			found = 1; -			break; -		} -	} - -	return found ? tmp_if : NULL; -} -  /* Map to MAC-VLAN interface corresponding to specified SVI interface.   */ -static struct interface *zevpn_map_to_macvlan(struct interface *br_if, -					     struct interface *svi_if) +struct interface *zebra_evpn_map_to_macvlan(struct interface *br_if, +					    struct interface *svi_if)  {  	struct zebra_ns *zns;  	struct route_node *rn; @@ -1611,7 +795,7 @@ static struct interface *zevpn_map_to_macvlan(struct interface *br_if,  /*   * Install MAC hash entry - called upon access VLAN change.   */ -static void zevpn_install_mac_hash(struct hash_bucket *bucket, void *ctxt) +void zebra_evpn_install_mac_hash(struct hash_bucket *bucket, void *ctxt)  {  	zebra_mac_t *mac;  	struct mac_walk_ctx *wctx = ctxt; @@ -1625,7 +809,7 @@ static void zevpn_install_mac_hash(struct hash_bucket *bucket, void *ctxt)  /*   * Read and populate local MACs and neighbors corresponding to this EVPN.   */ -static void zevpn_read_mac_neigh(zebra_evpn_t *zevpn, struct interface *ifp) +void zebra_evpn_read_mac_neigh(zebra_evpn_t *zevpn, struct interface *ifp)  {  	struct zebra_ns *zns;  	struct zebra_if *zif; @@ -1648,21 +832,21 @@ static void zevpn_read_mac_neigh(zebra_evpn_t *zevpn, struct interface *ifp)  	if (vlan_if) {  		/* Add SVI MAC-IP */ -		zevpn_add_macip_for_intf(vlan_if, zevpn); +		zebra_evpn_add_macip_for_intf(vlan_if, zevpn);  		/* Add VRR MAC-IP - if any*/  		vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);  		if (vrr_if) -			zevpn_add_macip_for_intf(vrr_if, zevpn); +			zebra_evpn_add_macip_for_intf(vrr_if, zevpn);  		neigh_read_for_vlan(zns, vlan_if);  	}  }  /* - * Hash function for VNI. + * Hash function for EVPN.   */ -static unsigned int evpn_hash_keymake(const void *p) +unsigned int zebra_evpn_hash_keymake(const void *p)  {  	const zebra_evpn_t *zevpn = p; @@ -1670,9 +854,9 @@ static unsigned int evpn_hash_keymake(const void *p)  }  /* - * Compare 2 VNI hash entries. + * Compare 2 evpn hash entries.   */ -static bool vni_hash_cmp(const void *p1, const void *p2) +bool zebra_evpn_hash_cmp(const void *p1, const void *p2)  {  	const zebra_evpn_t *zevpn1 = p1;  	const zebra_evpn_t *zevpn2 = p2; @@ -1680,7 +864,7 @@ static bool vni_hash_cmp(const void *p1, const void *p2)  	return (zevpn1->vni == zevpn2->vni);  } -int vni_list_cmp(void *p1, void *p2) +int zebra_evpn_list_cmp(void *p1, void *p2)  {  	const zebra_evpn_t *zevpn1 = p1;  	const zebra_evpn_t *zevpn2 = p2; @@ -1693,7 +877,7 @@ int vni_list_cmp(void *p1, void *p2)  /*   * Callback to allocate VNI hash entry.   */ -static void *zevpn_alloc(void *p) +void *zebra_evpn_alloc(void *p)  {  	const zebra_evpn_t *tmp_vni = p;  	zebra_evpn_t *zevpn; @@ -1706,7 +890,7 @@ static void *zevpn_alloc(void *p)  /*   * Look up EVPN hash entry.   */ -zebra_evpn_t *zevpn_lookup(vni_t vni) +zebra_evpn_t *zebra_evpn_lookup(vni_t vni)  {  	struct zebra_vrf *zvrf;  	zebra_evpn_t tmp_vni; @@ -1724,7 +908,7 @@ zebra_evpn_t *zevpn_lookup(vni_t vni)  /*   * Add EVPN hash entry.   */ -static zebra_evpn_t *zevpn_add(vni_t vni) +zebra_evpn_t *zebra_evpn_add(vni_t vni)  {  	struct zebra_vrf *zvrf;  	zebra_evpn_t tmp_zevpn; @@ -1734,7 +918,7 @@ static zebra_evpn_t *zevpn_add(vni_t vni)  	assert(zvrf);  	memset(&tmp_zevpn, 0, sizeof(zebra_evpn_t));  	tmp_zevpn.vni = vni; -	zevpn = hash_get(zvrf->evpn_table, &tmp_zevpn, zevpn_alloc); +	zevpn = hash_get(zvrf->evpn_table, &tmp_zevpn, zebra_evpn_alloc);  	assert(zevpn);  	zebra_evpn_evpn_es_init(zevpn); @@ -1748,34 +932,10 @@ static zebra_evpn_t *zevpn_add(vni_t vni)  	return zevpn;  } -/* EVPN<=>vxlan_zif association */ -static void zevpn_vxlan_if_set(zebra_evpn_t *zevpn, struct interface *ifp, -		bool set) -{ -	struct zebra_if *zif; - -	if (set) { -		if (zevpn->vxlan_if == ifp) -			return; -		zevpn->vxlan_if = ifp; -	} else { -		if (!zevpn->vxlan_if) -			return; -		zevpn->vxlan_if = NULL; -	} - -	if (ifp) -		zif = ifp->info; -	else -		zif = NULL; - -	zebra_evpn_vxl_evpn_set(zif, zevpn, set); -} -  /*   * Delete EVPN hash entry.   */ -static int zevpn_del(zebra_evpn_t *zevpn) +int zebra_evpn_del(zebra_evpn_t *zevpn)  {  	struct zebra_vrf *zvrf;  	zebra_evpn_t *tmp_zevpn; @@ -1783,11 +943,6 @@ static int zevpn_del(zebra_evpn_t *zevpn)  	zvrf = zebra_vrf_get_evpn();  	assert(zvrf); -	zevpn_vxlan_if_set(zevpn, zevpn->vxlan_if, false /* set */); - -	/* Remove references to the BUM mcast grp */ -	zebra_vxlan_sg_deref(zevpn->local_vtep_ip, zevpn->mcast_grp); -  	/* Free the neighbor hash table. */  	hash_free(zevpn->neigh_table);  	zevpn->neigh_table = NULL; @@ -1808,7 +963,7 @@ static int zevpn_del(zebra_evpn_t *zevpn)  /*   * Inform BGP about local EVPN addition.   */ -static int zevpn_send_add_to_client(zebra_evpn_t *zevpn) +int zebra_evpn_send_add_to_client(zebra_evpn_t *zevpn)  {  	struct zserv *client;  	struct stream *s; @@ -1852,7 +1007,7 @@ static int zevpn_send_add_to_client(zebra_evpn_t *zevpn)  /*   * Inform BGP about local EVPN deletion.   */ -static int zevpn_send_del_to_client(zebra_evpn_t *zevpn) +int zebra_evpn_send_del_to_client(zebra_evpn_t *zevpn)  {  	struct zserv *client;  	struct stream *s; @@ -1886,150 +1041,9 @@ static int zevpn_send_del_to_client(zebra_evpn_t *zevpn)  }  /* - * Build the VNI hash table by going over the VxLAN interfaces. This - * is called when EVPN (advertise-all-vni) is enabled. - */ -static void zevpn_build_hash_table(void) -{ -	struct zebra_ns *zns; -	struct route_node *rn; -	struct interface *ifp; - -	/* Walk VxLAN interfaces and create EVPN hash. */ -	zns = zebra_ns_lookup(NS_DEFAULT); -	for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { -		vni_t vni; -		zebra_evpn_t *zevpn = NULL; -		zebra_l3vni_t *zl3vni = NULL; -		struct zebra_if *zif; -		struct zebra_l2info_vxlan *vxl; - -		ifp = (struct interface *)rn->info; -		if (!ifp) -			continue; -		zif = ifp->info; -		if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) -			continue; - -		vxl = &zif->l2info.vxl; -		vni = vxl->vni; - -		/* L3-VNI and L2-VNI are handled seperately */ -		zl3vni = zl3vni_lookup(vni); -		if (zl3vni) { - -			if (IS_ZEBRA_DEBUG_VXLAN) -				zlog_debug( -					"create L3-VNI hash for Intf %s(%u) L3-VNI %u", -					ifp->name, ifp->ifindex, vni); - -			/* associate with vxlan_if */ -			zl3vni->local_vtep_ip = vxl->vtep_ip; -			zl3vni->vxlan_if = ifp; - -			/* -			 * we need to associate with SVI. -			 * we can associate with svi-if only after association -			 * with vxlan-intf is complete -			 */ -			zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni); - -			/* Associate l3vni to mac-vlan and extract VRR MAC */ -			zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni); - -			if (IS_ZEBRA_DEBUG_VXLAN) -				zlog_debug("create l3vni %u svi_if %s mac_vlan_if %s", -				   vni, zl3vni->svi_if ? zl3vni->svi_if->name -				   : "NIL", -				   zl3vni->mac_vlan_if ? -				   zl3vni->mac_vlan_if->name : "NIL"); - -			if (is_l3vni_oper_up(zl3vni)) -				zebra_vxlan_process_l3vni_oper_up(zl3vni); - -		} else { -			struct interface *vlan_if = NULL; - -			if (IS_ZEBRA_DEBUG_VXLAN) -				zlog_debug( -					"Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s", -					ifp->name, ifp->ifindex, vni, -					inet_ntoa(vxl->vtep_ip)); - -			/* EVPN hash entry is expected to exist, if the BGP process is killed */ -			zevpn = zevpn_lookup(vni); -			if (zevpn) { -				zlog_debug( -					"EVPN hash already present for IF %s(%u) L2-VNI %u", -					ifp->name, ifp->ifindex, vni); - -				/* -				 * Inform BGP if intf is up and mapped to -				 * bridge. -				 */ -				if (if_is_operative(ifp) && -					zif->brslave_info.br_if) -					zevpn_send_add_to_client(zevpn); - -				/* Send Local MAC-entries to client */ -				zebra_evpn_send_mac_list_to_client(zevpn); - -				/* Send Loval Neighbor entries to client */ -				zebra_evpn_send_neigh_to_client(zevpn); -			} else { -				zevpn = zevpn_add(vni); -				if (!zevpn) { -					zlog_debug( -						"Failed to add EVPN hash, IF %s(%u) L2-VNI %u", -						ifp->name, ifp->ifindex, vni); -					return; -				} - -				if (zevpn->local_vtep_ip.s_addr != -					vxl->vtep_ip.s_addr || -					zevpn->mcast_grp.s_addr != -					vxl->mcast_grp.s_addr) { -					zebra_vxlan_sg_deref( -						zevpn->local_vtep_ip, -						zevpn->mcast_grp); -					zebra_vxlan_sg_ref(vxl->vtep_ip, -						vxl->mcast_grp); -					zevpn->local_vtep_ip = vxl->vtep_ip; -					zevpn->mcast_grp = vxl->mcast_grp; -					/* on local vtep-ip check if ES -					 * orig-ip needs to be updated -					 */ -					zebra_evpn_es_set_base_evpn(zevpn); -				} -				zevpn_vxlan_if_set(zevpn, ifp, true /* set */); -				vlan_if = zvni_map_to_svi( -					vxl->access_vlan, -					zif->brslave_info.br_if); -				if (vlan_if) { -					zevpn->vrf_id = vlan_if->vrf_id; -					zl3vni = zl3vni_from_vrf( -							vlan_if->vrf_id); -					if (zl3vni) -						listnode_add_sort( -							zl3vni->l2vnis, zevpn); -				} - -				/* -				 * Inform BGP if intf is up and mapped to -				 * bridge. -				 */ -				if (if_is_operative(ifp) && -					zif->brslave_info.br_if) -					zevpn_send_add_to_client(zevpn); -			} -		} -	} -} - -/*   * See if remote VTEP matches with prefix.   */ -static int zevpn_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep) +static int zebra_evpn_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep)  {  	return (IPV4_ADDR_SAME(vtep_ip, &zvtep->vtep_ip));  } @@ -2037,7 +1051,7 @@ static int zevpn_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep)  /*   * Locate remote VTEP in EVPN hash table.   */ -static zebra_vtep_t *zevpn_vtep_find(zebra_evpn_t *zevpn, struct in_addr *vtep_ip) +zebra_vtep_t *zebra_evpn_vtep_find(zebra_evpn_t *zevpn, struct in_addr *vtep_ip)  {  	zebra_vtep_t *zvtep; @@ -2045,7 +1059,7 @@ static zebra_vtep_t *zevpn_vtep_find(zebra_evpn_t *zevpn, struct in_addr *vtep_i  		return NULL;  	for (zvtep = zevpn->vteps; zvtep; zvtep = zvtep->next) { -		if (zevpn_vtep_match(vtep_ip, zvtep)) +		if (zebra_evpn_vtep_match(vtep_ip, zvtep))  			break;  	} @@ -2055,8 +1069,8 @@ static zebra_vtep_t *zevpn_vtep_find(zebra_evpn_t *zevpn, struct in_addr *vtep_i  /*   * Add remote VTEP to EVPN hash table.   */ -static zebra_vtep_t *zevpn_vtep_add(zebra_evpn_t *zevpn, struct in_addr *vtep_ip, -		int flood_control) +zebra_vtep_t *zebra_evpn_vtep_add(zebra_evpn_t *zevpn, struct in_addr *vtep_ip, +				  int flood_control)  {  	zebra_vtep_t *zvtep; @@ -2077,7 +1091,7 @@ static zebra_vtep_t *zevpn_vtep_add(zebra_evpn_t *zevpn, struct in_addr *vtep_ip  /*   * Remove remote VTEP from EVPN hash table.   */ -static int zevpn_vtep_del(zebra_evpn_t *zevpn, zebra_vtep_t *zvtep) +int zebra_evpn_vtep_del(zebra_evpn_t *zevpn, zebra_vtep_t *zvtep)  {  	if (zvtep->next)  		zvtep->next->prev = zvtep->prev; @@ -2096,7 +1110,7 @@ static int zevpn_vtep_del(zebra_evpn_t *zevpn, zebra_vtep_t *zvtep)   * Delete all remote VTEPs for this EVPN (upon VNI delete). Also   * uninstall from kernel if asked to.   */ -static int zevpn_vtep_del_all(zebra_evpn_t *zevpn, int uninstall) +int zebra_evpn_vtep_del_all(zebra_evpn_t *zevpn, int uninstall)  {  	zebra_vtep_t *zvtep, *zvtep_next; @@ -2106,8 +1120,8 @@ static int zevpn_vtep_del_all(zebra_evpn_t *zevpn, int uninstall)  	for (zvtep = zevpn->vteps; zvtep; zvtep = zvtep_next) {  		zvtep_next = zvtep->next;  		if (uninstall) -			zevpn_vtep_uninstall(zevpn, &zvtep->vtep_ip); -		zevpn_vtep_del(zevpn, zvtep); +			zebra_evpn_vtep_uninstall(zevpn, &zvtep->vtep_ip); +		zebra_evpn_vtep_del(zevpn, zvtep);  	}  	return 0; @@ -2117,7 +1131,7 @@ static int zevpn_vtep_del_all(zebra_evpn_t *zevpn, int uninstall)   * Install remote VTEP into the kernel if the remote VTEP has asked   * for head-end-replication.   */ -static int zevpn_vtep_install(zebra_evpn_t *zevpn, zebra_vtep_t *zvtep) +int zebra_evpn_vtep_install(zebra_evpn_t *zevpn, zebra_vtep_t *zvtep)  {  	if (is_vxlan_flooding_head_end() &&  	    (zvtep->flood_control == VXLAN_FLOOD_HEAD_END_REPL)) { @@ -2133,7 +1147,7 @@ static int zevpn_vtep_install(zebra_evpn_t *zevpn, zebra_vtep_t *zvtep)  /*   * Uninstall remote VTEP from the kernel.   */ -static int zevpn_vtep_uninstall(zebra_evpn_t *zevpn, struct in_addr *vtep_ip) +int zebra_evpn_vtep_uninstall(zebra_evpn_t *zevpn, struct in_addr *vtep_ip)  {  	if (!zevpn->vxlan_if) {  		zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf", @@ -2152,8 +1166,8 @@ static int zevpn_vtep_uninstall(zebra_evpn_t *zevpn, struct in_addr *vtep_ip)   * Install or uninstall flood entries in the kernel corresponding to   * remote VTEPs. This is invoked upon change to BUM handling.   */ -static void zevpn_handle_flooding_remote_vteps(struct hash_bucket *bucket, -					      void *zvrf) +void zebra_evpn_handle_flooding_remote_vteps(struct hash_bucket *bucket, +					     void *zvrf)  {  	zebra_evpn_t *zevpn;  	zebra_vtep_t *zvtep; @@ -2164,1077 +1178,36 @@ static void zevpn_handle_flooding_remote_vteps(struct hash_bucket *bucket,  	for (zvtep = zevpn->vteps; zvtep; zvtep = zvtep->next) {  		if (is_vxlan_flooding_head_end()) -			zevpn_vtep_install(zevpn, zvtep); +			zebra_evpn_vtep_install(zevpn, zvtep);  		else -			zevpn_vtep_uninstall(zevpn, &zvtep->vtep_ip); +			zebra_evpn_vtep_uninstall(zevpn, &zvtep->vtep_ip);  	}  }  /*   * Cleanup EVPN/VTEP and update kernel   */ -static void zevpn_cleanup_all(struct hash_bucket *bucket, void *arg) +void zebra_evpn_cleanup_all(struct hash_bucket *bucket, void *arg)  {  	zebra_evpn_t *zevpn = NULL; -	zebra_l3vni_t *zl3vni = NULL; -	struct zebra_vrf *zvrf = (struct zebra_vrf *)arg;  	zevpn = (zebra_evpn_t *)bucket->data; -	/* remove from l3-vni list */ -	if (zvrf->l3vni) -		zl3vni = zl3vni_lookup(zvrf->l3vni); -	if (zl3vni) -		listnode_delete(zl3vni->l2vnis, zevpn); -  	/* Free up all neighbors and MACs, if any. */  	zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);  	zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);  	/* Free up all remote VTEPs, if any. */ -	zevpn_vtep_del_all(zevpn, 1); +	zebra_evpn_vtep_del_all(zevpn, 1);  	/* Delete the hash entry. */ -	zevpn_del(zevpn); -} - -/* cleanup L3VNI */ -static void zl3vni_cleanup_all(struct hash_bucket *bucket, void *args) -{ -	zebra_l3vni_t *zl3vni = NULL; - -	zl3vni = (zebra_l3vni_t *)bucket->data; - -	zebra_vxlan_process_l3vni_oper_down(zl3vni); -} - -static void rb_find_or_add_host(struct host_rb_tree_entry *hrbe, -				const struct prefix *host) -{ -	struct host_rb_entry lookup; -	struct host_rb_entry *hle; - -	memset(&lookup, 0, sizeof(lookup)); -	memcpy(&lookup.p, host, sizeof(*host)); - -	hle = RB_FIND(host_rb_tree_entry, hrbe, &lookup); -	if (hle) -		return; - -	hle = XCALLOC(MTYPE_HOST_PREFIX, sizeof(struct host_rb_entry)); -	memcpy(hle, &lookup, sizeof(lookup)); - -	RB_INSERT(host_rb_tree_entry, hrbe, hle); -} - -static void rb_delete_host(struct host_rb_tree_entry *hrbe, struct prefix *host) -{ -	struct host_rb_entry lookup; -	struct host_rb_entry *hle; - -	memset(&lookup, 0, sizeof(lookup)); -	memcpy(&lookup.p, host, sizeof(*host)); - -	hle = RB_FIND(host_rb_tree_entry, hrbe, &lookup); -	if (hle) { -		RB_REMOVE(host_rb_tree_entry, hrbe, hle); -		XFREE(MTYPE_HOST_PREFIX, hle); -	} - -	return; -} - -/* - * Look up MAC hash entry. - */ -static zebra_mac_t *zl3vni_rmac_lookup(zebra_l3vni_t *zl3vni, -				       const struct ethaddr *rmac) -{ -	zebra_mac_t tmp; -	zebra_mac_t *pmac; - -	memset(&tmp, 0, sizeof(tmp)); -	memcpy(&tmp.macaddr, rmac, ETH_ALEN); -	pmac = hash_lookup(zl3vni->rmac_table, &tmp); - -	return pmac; -} - -/* - * Callback to allocate RMAC hash entry. - */ -static void *zl3vni_rmac_alloc(void *p) -{ -	const zebra_mac_t *tmp_rmac = p; -	zebra_mac_t *zrmac; - -	zrmac = XCALLOC(MTYPE_L3VNI_MAC, sizeof(zebra_mac_t)); -	*zrmac = *tmp_rmac; - -	return ((void *)zrmac); -} - -/* - * Add RMAC entry to l3-vni - */ -static zebra_mac_t *zl3vni_rmac_add(zebra_l3vni_t *zl3vni, -				    const struct ethaddr *rmac) -{ -	zebra_mac_t tmp_rmac; -	zebra_mac_t *zrmac = NULL; - -	memset(&tmp_rmac, 0, sizeof(zebra_mac_t)); -	memcpy(&tmp_rmac.macaddr, rmac, ETH_ALEN); -	zrmac = hash_get(zl3vni->rmac_table, &tmp_rmac, zl3vni_rmac_alloc); -	assert(zrmac); - -	RB_INIT(host_rb_tree_entry, &zrmac->host_rb); - -	SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE); -	SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC); - -	return zrmac; -} - -/* - * Delete MAC entry. - */ -static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac) -{ -	zebra_mac_t *tmp_rmac; -	struct host_rb_entry *hle; - -	while (!RB_EMPTY(host_rb_tree_entry, &zrmac->host_rb)) { -		hle = RB_ROOT(host_rb_tree_entry, &zrmac->host_rb); - -		RB_REMOVE(host_rb_tree_entry, &zrmac->host_rb, hle); -		XFREE(MTYPE_HOST_PREFIX, hle); -	} - -	tmp_rmac = hash_release(zl3vni->rmac_table, zrmac); -	XFREE(MTYPE_L3VNI_MAC, tmp_rmac); - -	return 0; -} - -/* - * Install remote RMAC into the forwarding plane. - */ -static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac) -{ -	const struct zebra_if *zif = NULL, *br_zif = NULL; -	const struct zebra_l2info_vxlan *vxl = NULL; -	const struct interface *br_ifp; -	enum zebra_dplane_result res; -	vlanid_t vid; - -	if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE)) -	    || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC))) -		return 0; - -	zif = zl3vni->vxlan_if->info; -	if (!zif) -		return -1; - -	br_ifp = zif->brslave_info.br_if; -	if (br_ifp == NULL) -		return -1; - -	vxl = &zif->l2info.vxl; - -	br_zif = (const struct zebra_if *)br_ifp->info; - -	if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif)) -		vid = vxl->access_vlan; -	else -		vid = 0; - -	res = dplane_rem_mac_add(zl3vni->vxlan_if, br_ifp, vid, -			     &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0, 0, -				 false /*was_static*/); -	if (res != ZEBRA_DPLANE_REQUEST_FAILURE) -		return 0; -	else -		return -1; -} - -/* - * Uninstall remote RMAC from the forwarding plane. - */ -static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac) -{ -	char buf[ETHER_ADDR_STRLEN]; -	const struct zebra_if *zif = NULL, *br_zif; -	const struct zebra_l2info_vxlan *vxl = NULL; -	const struct interface *br_ifp; -	vlanid_t vid; -	enum zebra_dplane_result res; - -	if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE)) -	    || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC))) -		return 0; - -	if (!zl3vni->vxlan_if) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug( -				"RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if", -				prefix_mac2str(&zrmac->macaddr, -					       buf, sizeof(buf)), -				zl3vni->vni, zl3vni); -		return -1; -	} - -	zif = zl3vni->vxlan_if->info; -	if (!zif) -		return -1; - -	br_ifp = zif->brslave_info.br_if; -	if (br_ifp == NULL) -		return -1; - -	vxl = &zif->l2info.vxl; - -	br_zif = (const struct zebra_if *)br_ifp->info; -	if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif)) -		vid = vxl->access_vlan; -	else -		vid = 0; - -	res = dplane_rem_mac_del(zl3vni->vxlan_if, br_ifp, vid, -			     &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip); -	if (res != ZEBRA_DPLANE_REQUEST_FAILURE) -		return 0; -	else -		return -1; -} - -/* handle rmac add */ -static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni, -				  const struct ethaddr *rmac, -				  const struct ipaddr *vtep_ip, -				  const struct prefix *host_prefix) -{ -	char buf[ETHER_ADDR_STRLEN]; -	char buf1[INET6_ADDRSTRLEN]; -	char buf2[PREFIX_STRLEN]; -	zebra_mac_t *zrmac = NULL; - -	zrmac = zl3vni_rmac_lookup(zl3vni, rmac); -	if (!zrmac) { - -		 /* Create the RMAC entry, or update its vtep, if necessary. */ -		zrmac = zl3vni_rmac_add(zl3vni, rmac); -		if (!zrmac) { -			zlog_debug( -				"Failed to add RMAC %s L3VNI %u Remote VTEP %s, prefix %s", -				prefix_mac2str(rmac, buf, sizeof(buf)), -				zl3vni->vni, -				ipaddr2str(vtep_ip, buf1, sizeof(buf1)), -				prefix2str(host_prefix, buf2, sizeof(buf2))); -			return -1; -		} -		memset(&zrmac->fwd_info, 0, sizeof(zrmac->fwd_info)); -		zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4; - -		/* Send RMAC for FPM processing */ -		hook_call(zebra_rmac_update, zrmac, zl3vni, false, -			  "new RMAC added"); - -		/* install rmac in kernel */ -		zl3vni_rmac_install(zl3vni, zrmac); -	} else if (!IPV4_ADDR_SAME(&zrmac->fwd_info.r_vtep_ip, -				   &vtep_ip->ipaddr_v4)) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug( -				"L3VNI %u Remote VTEP change(%s -> %s) for RMAC %s, prefix %s", -				zl3vni->vni, -				inet_ntoa(zrmac->fwd_info.r_vtep_ip), -				ipaddr2str(vtep_ip, buf1, sizeof(buf1)), -				prefix_mac2str(rmac, buf, sizeof(buf)), -				prefix2str(host_prefix, buf2, sizeof(buf2))); - -		zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4; - -		/* install rmac in kernel */ -		zl3vni_rmac_install(zl3vni, zrmac); -	} - -	rb_find_or_add_host(&zrmac->host_rb, host_prefix); - -	return 0; -} - - -/* handle rmac delete */ -static void zl3vni_remote_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac, -				  struct prefix *host_prefix) -{ -	rb_delete_host(&zrmac->host_rb, host_prefix); - -	if (RB_EMPTY(host_rb_tree_entry, &zrmac->host_rb)) { -		/* uninstall from kernel */ -		zl3vni_rmac_uninstall(zl3vni, zrmac); - -		/* Send RMAC for FPM processing */ -		hook_call(zebra_rmac_update, zrmac, zl3vni, true, -			  "RMAC deleted"); - -		/* del the rmac entry */ -		zl3vni_rmac_del(zl3vni, zrmac); -	} -} - -/* - * Look up nh hash entry on a l3-vni. - */ -static zebra_neigh_t *zl3vni_nh_lookup(zebra_l3vni_t *zl3vni, -				       const struct ipaddr *ip) -{ -	zebra_neigh_t tmp; -	zebra_neigh_t *n; - -	memset(&tmp, 0, sizeof(tmp)); -	memcpy(&tmp.ip, ip, sizeof(struct ipaddr)); -	n = hash_lookup(zl3vni->nh_table, &tmp); - -	return n; -} - - -/* - * Callback to allocate NH hash entry on L3-VNI. - */ -static void *zl3vni_nh_alloc(void *p) -{ -	const zebra_neigh_t *tmp_n = p; -	zebra_neigh_t *n; - -	n = XCALLOC(MTYPE_L3NEIGH, sizeof(zebra_neigh_t)); -	*n = *tmp_n; - -	return ((void *)n); -} - -/* - * Add neighbor entry. - */ -static zebra_neigh_t *zl3vni_nh_add(zebra_l3vni_t *zl3vni, -				    const struct ipaddr *ip, -				    const struct ethaddr *mac) -{ -	zebra_neigh_t tmp_n; -	zebra_neigh_t *n = NULL; - -	memset(&tmp_n, 0, sizeof(zebra_neigh_t)); -	memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr)); -	n = hash_get(zl3vni->nh_table, &tmp_n, zl3vni_nh_alloc); -	assert(n); - -	RB_INIT(host_rb_tree_entry, &n->host_rb); - -	memcpy(&n->emac, mac, ETH_ALEN); -	SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); -	SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE_NH); - -	return n; -} - -/* - * Delete neighbor entry. - */ -static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) -{ -	zebra_neigh_t *tmp_n; -	struct host_rb_entry *hle; - -	while (!RB_EMPTY(host_rb_tree_entry, &n->host_rb)) { -		hle = RB_ROOT(host_rb_tree_entry, &n->host_rb); - -		RB_REMOVE(host_rb_tree_entry, &n->host_rb, hle); -		XFREE(MTYPE_HOST_PREFIX, hle); -	} - -	tmp_n = hash_release(zl3vni->nh_table, n); -	XFREE(MTYPE_L3NEIGH, tmp_n); - -	return 0; -} - -/* - * Install remote nh as neigh into the kernel. - */ -static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) -{ -	uint8_t flags; -	int ret = 0; - -	if (!is_l3vni_oper_up(zl3vni)) -		return -1; - -	if (!(n->flags & ZEBRA_NEIGH_REMOTE) -	    || !(n->flags & ZEBRA_NEIGH_REMOTE_NH)) -		return 0; - -	flags = DPLANE_NTF_EXT_LEARNED; -	if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG) -		flags |= DPLANE_NTF_ROUTER; - -	dplane_rem_neigh_add(zl3vni->svi_if, &n->ip, &n->emac, flags, -			false /*was_static*/); - -	return ret; -} - -/* - * Uninstall remote nh from the kernel. - */ -static int zl3vni_nh_uninstall(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) -{ -	if (!(n->flags & ZEBRA_NEIGH_REMOTE) -	    || !(n->flags & ZEBRA_NEIGH_REMOTE_NH)) -		return 0; - -	if (!zl3vni->svi_if || !if_is_operative(zl3vni->svi_if)) -		return 0; - -	dplane_rem_neigh_delete(zl3vni->svi_if, &n->ip); - -	return 0; -} - -/* add remote vtep as a neigh entry */ -static int zl3vni_remote_nh_add(zebra_l3vni_t *zl3vni, -				const struct ipaddr *vtep_ip, -				const struct ethaddr *rmac, -				const struct prefix *host_prefix) -{ -	char buf[ETHER_ADDR_STRLEN]; -	char buf1[ETHER_ADDR_STRLEN]; -	char buf2[INET6_ADDRSTRLEN]; -	char buf3[PREFIX_STRLEN]; -	zebra_neigh_t *nh = NULL; - -	/* Create the next hop entry, or update its mac, if necessary. */ -	nh = zl3vni_nh_lookup(zl3vni, vtep_ip); -	if (!nh) { -		nh = zl3vni_nh_add(zl3vni, vtep_ip, rmac); -		if (!nh) { -			zlog_debug( -				"Failed to add NH %s as Neigh (RMAC %s L3-VNI %u prefix %s)", -				ipaddr2str(vtep_ip, buf1, sizeof(buf2)), -				prefix_mac2str(rmac, buf, sizeof(buf)), -				zl3vni->vni, -				prefix2str(host_prefix, buf2, sizeof(buf2))); -			return -1; -		} - -		/* install the nh neigh in kernel */ -		zl3vni_nh_install(zl3vni, nh); -	} else if (memcmp(&nh->emac, rmac, ETH_ALEN) != 0) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("L3VNI %u RMAC change(%s --> %s) for nexthop %s, prefix %s", -				   zl3vni->vni, -				   prefix_mac2str(&nh->emac, buf, sizeof(buf)), -				   prefix_mac2str(rmac, buf1, sizeof(buf1)), -				   ipaddr2str(vtep_ip, buf2, sizeof(buf2)), -				   prefix2str(host_prefix, buf3, sizeof(buf3))); - -		memcpy(&nh->emac, rmac, ETH_ALEN); -		/* install (update) the nh neigh in kernel */ -		zl3vni_nh_install(zl3vni, nh); -	} - -	rb_find_or_add_host(&nh->host_rb, host_prefix); - -	return 0; -} - -/* handle nh neigh delete */ -static void zl3vni_remote_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *nh, -				 struct prefix *host_prefix) -{ -	rb_delete_host(&nh->host_rb, host_prefix); - -	if (RB_EMPTY(host_rb_tree_entry, &nh->host_rb)) { -		/* uninstall from kernel */ -		zl3vni_nh_uninstall(zl3vni, nh); - -		/* delete the nh entry */ -		zl3vni_nh_del(zl3vni, nh); -	} -} - -/* handle neigh update from kernel - the only thing of interest is to - * readd stale entries. - */ -static int zl3vni_local_nh_add_update(zebra_l3vni_t *zl3vni, struct ipaddr *ip, -				      uint16_t state) -{ -#ifdef GNU_LINUX -	zebra_neigh_t *n = NULL; - -	n = zl3vni_nh_lookup(zl3vni, ip); -	if (!n) -		return 0; - -	/* all next hop neigh are remote and installed by frr. -	 * If the kernel has aged this entry, re-install. -	 */ -	if (state & NUD_STALE) -		zl3vni_nh_install(zl3vni, n); -#endif -	return 0; -} - -/* handle neigh delete from kernel */ -static int zl3vni_local_nh_del(zebra_l3vni_t *zl3vni, struct ipaddr *ip) -{ -	zebra_neigh_t *n = NULL; - -	n = zl3vni_nh_lookup(zl3vni, ip); -	if (!n) -		return 0; - -	/* all next hop neigh are remote and installed by frr. -	 * If we get an age out notification for these neigh entries, we have to -	 * install it back -	 */ -	zl3vni_nh_install(zl3vni, n); - -	return 0; -} - -/* - * Hash function for L3 VNI. - */ -static unsigned int l3vni_hash_keymake(const void *p) -{ -	const zebra_l3vni_t *zl3vni = p; - -	return jhash_1word(zl3vni->vni, 0); +	zebra_evpn_del(zevpn);  } -/* - * Compare 2 L3 VNI hash entries. - */ -static bool l3vni_hash_cmp(const void *p1, const void *p2) -{ -	const zebra_l3vni_t *zl3vni1 = p1; -	const zebra_l3vni_t *zl3vni2 = p2; - -	return (zl3vni1->vni == zl3vni2->vni); -} - -/* - * Callback to allocate L3 VNI hash entry. - */ -static void *zl3vni_alloc(void *p) -{ -	zebra_l3vni_t *zl3vni = NULL; -	const zebra_l3vni_t *tmp_l3vni = p; - -	zl3vni = XCALLOC(MTYPE_ZL3VNI, sizeof(zebra_l3vni_t)); -	zl3vni->vni = tmp_l3vni->vni; -	return ((void *)zl3vni); -} - -/* - * Look up L3 VNI hash entry. - */ -static zebra_l3vni_t *zl3vni_lookup(vni_t vni) -{ -	zebra_l3vni_t tmp_l3vni; -	zebra_l3vni_t *zl3vni = NULL; - -	memset(&tmp_l3vni, 0, sizeof(zebra_l3vni_t)); -	tmp_l3vni.vni = vni; -	zl3vni = hash_lookup(zrouter.l3vni_table, &tmp_l3vni); - -	return zl3vni; -} - -/* - * Add L3 VNI hash entry. - */ -static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id) -{ -	zebra_l3vni_t tmp_zl3vni; -	zebra_l3vni_t *zl3vni = NULL; - -	memset(&tmp_zl3vni, 0, sizeof(zebra_l3vni_t)); -	tmp_zl3vni.vni = vni; - -	zl3vni = hash_get(zrouter.l3vni_table, &tmp_zl3vni, zl3vni_alloc); -	assert(zl3vni); - -	zl3vni->vrf_id = vrf_id; -	zl3vni->svi_if = NULL; -	zl3vni->vxlan_if = NULL; -	zl3vni->l2vnis = list_new(); -	zl3vni->l2vnis->cmp = vni_list_cmp; - -	/* Create hash table for remote RMAC */ -	zl3vni->rmac_table = zebra_mac_db_create("Zebra L3-VNI RMAC-Table"); - -	/* Create hash table for neighbors */ -	zl3vni->nh_table = zebra_neigh_db_create("Zebra L3-VNI next-hop table"); - -	return zl3vni; -} - -/* - * Delete L3 VNI hash entry. - */ -static int zl3vni_del(zebra_l3vni_t *zl3vni) -{ -	zebra_l3vni_t *tmp_zl3vni; - -	/* free the list of l2vnis */ -	list_delete(&zl3vni->l2vnis); -	zl3vni->l2vnis = NULL; - -	/* Free the rmac table */ -	hash_free(zl3vni->rmac_table); -	zl3vni->rmac_table = NULL; - -	/* Free the nh table */ -	hash_free(zl3vni->nh_table); -	zl3vni->nh_table = NULL; - -	/* Free the VNI hash entry and allocated memory. */ -	tmp_zl3vni = hash_release(zrouter.l3vni_table, zl3vni); -	XFREE(MTYPE_ZL3VNI, tmp_zl3vni); - -	return 0; -} - -struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni) -{ -	struct zebra_ns *zns = NULL; -	struct route_node *rn = NULL; -	struct interface *ifp = NULL; - -	/* loop through all vxlan-interface */ -	zns = zebra_ns_lookup(NS_DEFAULT); -	for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { - -		struct zebra_if *zif = NULL; -		struct zebra_l2info_vxlan *vxl = NULL; - -		ifp = (struct interface *)rn->info; -		if (!ifp) -			continue; - -		zif = ifp->info; -		if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) -			continue; - -		vxl = &zif->l2info.vxl; -		if (vxl->vni == zl3vni->vni) { -			zl3vni->local_vtep_ip = vxl->vtep_ip; -			return ifp; -		} -	} - -	return NULL; -} - -struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni) -{ -	struct zebra_if *zif = NULL;	   /* zebra_if for vxlan_if */ -	struct zebra_l2info_vxlan *vxl = NULL; /* l2 info for vxlan_if */ - -	if (!zl3vni) -		return NULL; - -	if (!zl3vni->vxlan_if) -		return NULL; - -	zif = zl3vni->vxlan_if->info; -	if (!zif) -		return NULL; - -	vxl = &zif->l2info.vxl; - -	return zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if); -} - -struct interface *zl3vni_map_to_mac_vlan_if(zebra_l3vni_t *zl3vni) -{ -	struct zebra_if *zif = NULL;	   /* zebra_if for vxlan_if */ - -	if (!zl3vni) -		return NULL; - -	if (!zl3vni->vxlan_if) -		return NULL; - -	zif = zl3vni->vxlan_if->info; -	if (!zif) -		return NULL; - -	return zevpn_map_to_macvlan(zif->brslave_info.br_if, zl3vni->svi_if); -} - - -zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t vrf_id) -{ -	struct zebra_vrf *zvrf = NULL; - -	zvrf = zebra_vrf_lookup_by_id(vrf_id); -	if (!zvrf) -		return NULL; - -	return zl3vni_lookup(zvrf->l3vni); -} - -/* - * Map SVI and associated bridge to a VNI. This is invoked upon getting - * neighbor notifications, to see if they are of interest. - */ -static zebra_l3vni_t *zl3vni_from_svi(struct interface *ifp, -				      struct interface *br_if) -{ -	int found = 0; -	vlanid_t vid = 0; -	uint8_t bridge_vlan_aware = 0; -	zebra_l3vni_t *zl3vni = NULL; -	struct zebra_ns *zns = NULL; -	struct route_node *rn = NULL; -	struct zebra_if *zif = NULL; -	struct interface *tmp_if = NULL; -	struct zebra_l2info_bridge *br = NULL; -	struct zebra_l2info_vxlan *vxl = NULL; - -	if (!br_if) -		return NULL; - -	/* Make sure the linked interface is a bridge. */ -	if (!IS_ZEBRA_IF_BRIDGE(br_if)) -		return NULL; - -	/* Determine if bridge is VLAN-aware or not */ -	zif = br_if->info; -	assert(zif); -	br = &zif->l2info.br; -	bridge_vlan_aware = br->vlan_aware; -	if (bridge_vlan_aware) { -		struct zebra_l2info_vlan *vl; - -		if (!IS_ZEBRA_IF_VLAN(ifp)) -			return NULL; - -		zif = ifp->info; -		assert(zif); -		vl = &zif->l2info.vl; -		vid = vl->vid; -	} - -	/* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ -	/* TODO: Optimize with a hash. */ -	zns = zebra_ns_lookup(NS_DEFAULT); -	for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { -		tmp_if = (struct interface *)rn->info; -		if (!tmp_if) -			continue; -		zif = tmp_if->info; -		if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) -			continue; -		if (!if_is_operative(tmp_if)) -			continue; -		vxl = &zif->l2info.vxl; - -		if (zif->brslave_info.br_if != br_if) -			continue; - -		if (!bridge_vlan_aware || vxl->access_vlan == vid) { -			found = 1; -			break; -		} -	} - -	if (!found) -		return NULL; - -	zl3vni = zl3vni_lookup(vxl->vni); -	return zl3vni; -} - -static inline void zl3vni_get_vrr_rmac(zebra_l3vni_t *zl3vni, -				       struct ethaddr *rmac) -{ -	if (!zl3vni) -		return; - -	if (!is_l3vni_oper_up(zl3vni)) -		return; - -	if (zl3vni->mac_vlan_if && if_is_operative(zl3vni->mac_vlan_if)) -		memcpy(rmac->octet, zl3vni->mac_vlan_if->hw_addr, ETH_ALEN); -} - -/* - * Inform BGP about l3-vni. - */ -static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni) -{ -	struct stream *s = NULL; -	struct zserv *client = NULL; -	struct ethaddr svi_rmac, vrr_rmac = {.octet = {0} }; -	struct zebra_vrf *zvrf; -	char buf[ETHER_ADDR_STRLEN]; -	char buf1[ETHER_ADDR_STRLEN]; -	bool is_anycast_mac = true; - -	client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); -	/* BGP may not be running. */ -	if (!client) -		return 0; - -	zvrf = zebra_vrf_lookup_by_id(zl3vni->vrf_id); -	assert(zvrf); - -	/* get the svi and vrr rmac values */ -	memset(&svi_rmac, 0, sizeof(struct ethaddr)); -	zl3vni_get_svi_rmac(zl3vni, &svi_rmac); -	zl3vni_get_vrr_rmac(zl3vni, &vrr_rmac); - -	/* In absence of vrr mac use svi mac as anycast MAC value */ -	if (is_zero_mac(&vrr_rmac)) { -		memcpy(&vrr_rmac, &svi_rmac, ETH_ALEN); -		is_anycast_mac = false; -	} - -	s = stream_new(ZEBRA_MAX_PACKET_SIZ); - -	/* The message is used for both vni add and/or update like -	 * vrr mac is added for l3vni SVI. -	 */ -	zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni)); -	stream_putl(s, zl3vni->vni); -	stream_put(s, &svi_rmac, sizeof(struct ethaddr)); -	stream_put_in_addr(s, &zl3vni->local_vtep_ip); -	stream_put(s, &zl3vni->filter, sizeof(int)); -	stream_putl(s, zl3vni->svi_if->ifindex); -	stream_put(s, &vrr_rmac, sizeof(struct ethaddr)); -	stream_putl(s, is_anycast_mac); - -	/* Write packet size. */ -	stream_putw_at(s, 0, stream_get_endp(s)); - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug( -			"Send L3_VNI_ADD %u VRF %s RMAC %s VRR %s local-ip %s filter %s to %s", -			zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)), -			prefix_mac2str(&svi_rmac, buf, sizeof(buf)), -			prefix_mac2str(&vrr_rmac, buf1, sizeof(buf1)), -			inet_ntoa(zl3vni->local_vtep_ip), -			CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY) -				? "prefix-routes-only" -				: "none", -			zebra_route_string(client->proto)); - -	client->l3vniadd_cnt++; -	return zserv_send_message(client, s); -} - -/* - * Inform BGP about local l3-VNI deletion. - */ -static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni) -{ -	struct stream *s = NULL; -	struct zserv *client = NULL; - -	client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); -	/* BGP may not be running. */ -	if (!client) -		return 0; - -	s = stream_new(ZEBRA_MAX_PACKET_SIZ); - -	zclient_create_header(s, ZEBRA_L3VNI_DEL, zl3vni_vrf_id(zl3vni)); -	stream_putl(s, zl3vni->vni); - -	/* Write packet size. */ -	stream_putw_at(s, 0, stream_get_endp(s)); - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni->vni, -			   vrf_id_to_name(zl3vni_vrf_id(zl3vni)), -			   zebra_route_string(client->proto)); - -	client->l3vnidel_cnt++; -	return zserv_send_message(client, s); -} - -static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni) -{ -	if (!zl3vni) -		return; - -	/* send l3vni add to BGP */ -	zl3vni_send_add_to_client(zl3vni); -} - -static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni) -{ -	if (!zl3vni) -		return; - -	/* send l3-vni del to BGP*/ -	zl3vni_send_del_to_client(zl3vni); -} - -static void zevpn_add_to_l3vni_list(struct hash_bucket *bucket, void *ctxt) -{ -	zebra_evpn_t *zevpn = (zebra_evpn_t *)bucket->data; -	zebra_l3vni_t *zl3vni = (zebra_l3vni_t *)ctxt; - -	if (zevpn->vrf_id == zl3vni_vrf_id(zl3vni)) -		listnode_add_sort(zl3vni->l2vnis, zevpn); -} - -/* - *  handle transition of vni from l2 to l3 and vice versa - */ -static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni, -					     int add) -{ -	zebra_evpn_t *zevpn = NULL; - -	/* There is a possibility that VNI notification was already received -	 * from kernel and we programmed it as L2-VNI -	 * In such a case we need to delete this L2-VNI first, so -	 * that it can be reprogrammed as L3-VNI in the system. It is also -	 * possible that the vrf-vni mapping is removed from FRR while the vxlan -	 * interface is still present in kernel. In this case to keep it -	 * symmetric, we will delete the l3-vni and reprogram it as l2-vni -	 */ -	if (add) { -		/* Locate hash entry */ -		zevpn = zevpn_lookup(vni); -		if (!zevpn) -			return 0; - -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni); - -		/* Delete EVPN from BGP. */ -		zevpn_send_del_to_client(zevpn); - -		zebra_evpn_neigh_del_all(zevpn, 0, 0, DEL_ALL_NEIGH); -		zebra_evpn_mac_del_all(zevpn, 0, 0, DEL_ALL_MAC); - -		/* Free up all remote VTEPs, if any. */ -		zevpn_vtep_del_all(zevpn, 0); - -		/* Delete the hash entry. */ -		if (zevpn_del(zevpn)) { -			flog_err(EC_ZEBRA_VNI_DEL_FAILED, -				 "Failed to del EVPN hash %p, VNI %u", zevpn, -				 zevpn->vni); -			return -1; -		} -	} else { -		/* TODO_MITESH: This needs to be thought through. We don't have -		 * enough information at this point to reprogram the vni as -		 * l2-vni. One way is to store the required info in l3-vni and -		 * used it solely for this purpose -		 */ -	} - -	return 0; -} - -/* delete and uninstall rmac hash entry */ -static void zl3vni_del_rmac_hash_entry(struct hash_bucket *bucket, void *ctx) -{ -	zebra_mac_t *zrmac = NULL; -	zebra_l3vni_t *zl3vni = NULL; - -	zrmac = (zebra_mac_t *)bucket->data; -	zl3vni = (zebra_l3vni_t *)ctx; -	zl3vni_rmac_uninstall(zl3vni, zrmac); - -	/* Send RMAC for FPM processing */ -	hook_call(zebra_rmac_update, zrmac, zl3vni, true, "RMAC deleted"); - -	zl3vni_rmac_del(zl3vni, zrmac); -} - -/* delete and uninstall nh hash entry */ -static void zl3vni_del_nh_hash_entry(struct hash_bucket *bucket, void *ctx) -{ -	zebra_neigh_t *n = NULL; -	zebra_l3vni_t *zl3vni = NULL; - -	n = (zebra_neigh_t *)bucket->data; -	zl3vni = (zebra_l3vni_t *)ctx; -	zl3vni_nh_uninstall(zl3vni, n); -	zl3vni_nh_del(zl3vni, n); -} - -static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p, -				    uint16_t cmd) -{ -	struct zserv *client = NULL; -	struct stream *s = NULL; -	char buf[PREFIX_STRLEN]; - -	client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); -	/* BGP may not be running. */ -	if (!client) -		return 0; - -	s = stream_new(ZEBRA_MAX_PACKET_SIZ); - -	zclient_create_header(s, cmd, vrf_id); -	stream_put(s, p, sizeof(struct prefix)); - -	/* Write packet size. */ -	stream_putw_at(s, 0, stream_get_endp(s)); - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("Send ip prefix %s %s on vrf %s", -			   prefix2str(p, buf, sizeof(buf)), -			   (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) ? "ADD" : "DEL", -			   vrf_id_to_name(vrf_id)); - -	if (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) -		client->prefixadd_cnt++; -	else -		client->prefixdel_cnt++; - -	return zserv_send_message(client, s); -} - -/* re-add remote rmac if needed */ -static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t *zl3vni, -					 struct ethaddr *rmac) -{ -	char buf[ETHER_ADDR_STRLEN]; -	zebra_mac_t *zrmac = NULL; - -	zrmac = zl3vni_rmac_lookup(zl3vni, rmac); -	if (!zrmac) -		return 0; - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("Del remote RMAC %s L3VNI %u - readd", -			   prefix_mac2str(rmac, buf, sizeof(buf)), zl3vni->vni); - -	zl3vni_rmac_install(zl3vni, zrmac); -	return 0; -} - -static void zebra_vxlan_process_sync_macip_add(zebra_evpn_t *zevpn, -				     struct ethaddr *macaddr, -				     uint16_t ipa_len, -				     struct ipaddr *ipaddr, -				     uint8_t flags, -				     uint32_t seq, -				     esi_t *esi) +static void +zebra_evpn_process_sync_macip_add(zebra_evpn_t *zevpn, struct ethaddr *macaddr, +				  uint16_t ipa_len, struct ipaddr *ipaddr, +				  uint8_t flags, uint32_t seq, esi_t *esi)  {  	struct sync_mac_ip_ctx ctx;  	char macbuf[ETHER_ADDR_STRLEN]; @@ -3247,14 +1220,16 @@ static void zebra_vxlan_process_sync_macip_add(zebra_evpn_t *zevpn,  	remote_gw = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW);  	/* if sticky or remote-gw ignore updates from the peer */  	if (sticky || remote_gw) { -		if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_NEIGH || -				IS_ZEBRA_DEBUG_EVPN_MH_MAC) -			zlog_debug("Ignore sync-macip vni %u mac %s%s%s%s%s", +		if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_NEIGH +		    || IS_ZEBRA_DEBUG_EVPN_MH_MAC) +			zlog_debug( +				"Ignore sync-macip vni %u mac %s%s%s%s%s",  				zevpn->vni,  				prefix_mac2str(macaddr, macbuf, sizeof(macbuf)),  				ipa_len ? " IP " : "", -				ipa_len ? -				ipaddr2str(ipaddr, ipbuf, sizeof(ipbuf)) : "", +				ipa_len ? ipaddr2str(ipaddr, ipbuf, +						     sizeof(ipbuf)) +					: "",  				sticky ? " sticky" : "",  				remote_gw ? " remote_gw" : "");  		return; @@ -3279,14 +1254,10 @@ static void zebra_vxlan_process_sync_macip_add(zebra_evpn_t *zevpn,  /************************** remote mac-ip handling **************************/  /* Process a remote MACIP add from BGP. */ -static void process_remote_macip_add(vni_t vni, -				     struct ethaddr *macaddr, -				     uint16_t ipa_len, -				     struct ipaddr *ipaddr, -				     uint8_t flags, -				     uint32_t seq, -				     struct in_addr vtep_ip, -				     esi_t *esi) +void process_remote_macip_add(vni_t vni, struct ethaddr *macaddr, +			      uint16_t ipa_len, struct ipaddr *ipaddr, +			      uint8_t flags, uint32_t seq, +			      struct in_addr vtep_ip, esi_t *esi)  {  	zebra_evpn_t *zevpn;  	zebra_vtep_t *zvtep; @@ -3296,7 +1267,7 @@ static void process_remote_macip_add(vni_t vni,  	struct zebra_vrf *zvrf;  	/* Locate EVPN hash entry - expected to exist. */ -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn) {  		zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni);  		return; @@ -3305,12 +1276,10 @@ static void process_remote_macip_add(vni_t vni,  	ifp = zevpn->vxlan_if;  	if (ifp)  		zif = ifp->info; -	if (!ifp || -	    !if_is_operative(ifp) || -	    !zif || -	    !zif->brslave_info.br_if) { -		zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info", -			  vni); +	if (!ifp || !if_is_operative(ifp) || !zif || !zif->brslave_info.br_if) { +		zlog_warn( +			"Ignoring remote MACIP ADD VNI %u, invalid interface state or info", +			vni);  		return;  	} @@ -3320,8 +1289,8 @@ static void process_remote_macip_add(vni_t vni,  	 * REMOTE - if ES is not local  	 */  	if (flags & ZEBRA_MACIP_TYPE_SYNC_PATH) { -		zebra_vxlan_process_sync_macip_add(zevpn, macaddr, ipa_len, -				ipaddr, flags, seq, esi); +		zebra_evpn_process_sync_macip_add(zevpn, macaddr, ipa_len, +						  ipaddr, flags, seq, esi);  		return;  	} @@ -3330,10 +1299,10 @@ static void process_remote_macip_add(vni_t vni,  	 * routes before advertising type-3 routes.  	 */  	if (vtep_ip.s_addr) { -		zvtep = zevpn_vtep_find(zevpn, &vtep_ip); +		zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);  		if (!zvtep) { -			zvtep = zevpn_vtep_add(zevpn, &vtep_ip, -					VXLAN_FLOOD_DISABLED); +			zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip, +						    VXLAN_FLOOD_DISABLED);  			if (!zvtep) {  				flog_err(  					EC_ZEBRA_VTEP_ADD_FAILED, @@ -3342,7 +1311,7 @@ static void process_remote_macip_add(vni_t vni,  				return;  			} -			zevpn_vtep_install(zevpn, zvtep); +			zebra_evpn_vtep_install(zevpn, zvtep);  		}  	} @@ -3361,11 +1330,9 @@ static void process_remote_macip_add(vni_t vni,  }  /* Process a remote MACIP delete from BGP. */ -static void process_remote_macip_del(vni_t vni, -				     struct ethaddr *macaddr, -				     uint16_t ipa_len, -				     struct ipaddr *ipaddr, -				     struct in_addr vtep_ip) +void process_remote_macip_del(vni_t vni, struct ethaddr *macaddr, +			      uint16_t ipa_len, struct ipaddr *ipaddr, +			      struct in_addr vtep_ip)  {  	zebra_evpn_t *zevpn;  	zebra_mac_t *mac = NULL; @@ -3379,7 +1346,7 @@ static void process_remote_macip_del(vni_t vni,  	char buf1[INET6_ADDRSTRLEN];  	/* Locate EVPN hash entry - expected to exist. */ -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn) {  		if (IS_ZEBRA_DEBUG_VXLAN)  			zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni); @@ -3389,13 +1356,11 @@ static void process_remote_macip_del(vni_t vni,  	ifp = zevpn->vxlan_if;  	if (ifp)  		zif = ifp->info; -	if (!ifp || -	    !if_is_operative(ifp) || -	    !zif || -	    !zif->brslave_info.br_if) { +	if (!ifp || !if_is_operative(ifp) || !zif || !zif->brslave_info.br_if) {  		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info", -				   vni); +			zlog_debug( +				"Ignoring remote MACIP DEL VNI %u, invalid interface state or info", +				vni);  		return;  	}  	zns = zebra_ns_lookup(NS_DEFAULT); @@ -3406,9 +1371,10 @@ static void process_remote_macip_del(vni_t vni,  		n = zebra_evpn_neigh_lookup(zevpn, ipaddr);  	if (n && !mac) { -		zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL", -			  prefix_mac2str(macaddr, buf, sizeof(buf)), -			  ipaddr2str(ipaddr, buf1, sizeof(buf1)), vni); +		zlog_warn( +			"Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL", +			prefix_mac2str(macaddr, buf, sizeof(buf)), +			ipaddr2str(ipaddr, buf1, sizeof(buf1)), vni);  		return;  	} @@ -3425,11 +1391,9 @@ static void process_remote_macip_del(vni_t vni,  	    && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) {  		zlog_warn(  			"Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC", -			vni, -			prefix_mac2str(macaddr, buf, sizeof(buf)), +			vni, prefix_mac2str(macaddr, buf, sizeof(buf)),  			ipa_len ? " IP " : "", -			ipa_len ? -			ipaddr2str(ipaddr, buf1, sizeof(buf1)) : ""); +			ipa_len ? ipaddr2str(ipaddr, buf1, sizeof(buf1)) : "");  		return;  	} @@ -3443,9 +1407,9 @@ static void process_remote_macip_del(vni_t vni,  		 * as LOCAL and reachable, avoid deleting this entry instead  		 * use kerenel local entry to update during unfreeze time.  		 */ -		if (zvrf->dad_freeze && -		    CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) && -		    CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { +		if (zvrf->dad_freeze +		    && CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) +		    && CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {  			if (IS_ZEBRA_DEBUG_VXLAN)  				zlog_debug(  					"%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry", @@ -3466,3825 +1430,8 @@ static void process_remote_macip_del(vni_t vni,  	}  } - -/* Public functions */ - -int is_l3vni_for_prefix_routes_only(vni_t vni) -{ -	zebra_l3vni_t *zl3vni = NULL; - -	zl3vni = zl3vni_lookup(vni); -	if (!zl3vni) -		return 0; - -	return CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY) ? 1 : 0; -} - -/* handle evpn route in vrf table */ -void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id, const struct ethaddr *rmac, -				    const struct ipaddr *vtep_ip, -				    const struct prefix *host_prefix) -{ -	zebra_l3vni_t *zl3vni = NULL; -	struct ipaddr ipv4_vtep; - -	zl3vni = zl3vni_from_vrf(vrf_id); -	if (!zl3vni || !is_l3vni_oper_up(zl3vni)) -		return; - -	/* -	 * add the next hop neighbor - -	 * neigh to be installed is the ipv6 nexthop neigh -	 */ -	zl3vni_remote_nh_add(zl3vni, vtep_ip, rmac, host_prefix); - -	/* -	 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4 -	 * address. Rmac is programmed against the ipv4 vtep because we only -	 * support ipv4 tunnels in the h/w right now -	 */ -	memset(&ipv4_vtep, 0, sizeof(struct ipaddr)); -	ipv4_vtep.ipa_type = IPADDR_V4; -	if (vtep_ip->ipa_type == IPADDR_V6) -		ipv4_mapped_ipv6_to_ipv4(&vtep_ip->ipaddr_v6, -					 &(ipv4_vtep.ipaddr_v4)); -	else -		memcpy(&(ipv4_vtep.ipaddr_v4), &vtep_ip->ipaddr_v4, -		       sizeof(struct in_addr)); - -	/* -	 * add the rmac - remote rmac to be installed is against the ipv4 -	 * nexthop address -	 */ -	zl3vni_remote_rmac_add(zl3vni, rmac, &ipv4_vtep, host_prefix); -} - -/* handle evpn vrf route delete */ -void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id, -				    struct ipaddr *vtep_ip, -				    struct prefix *host_prefix) -{ -	zebra_l3vni_t *zl3vni = NULL; -	zebra_neigh_t *nh = NULL; -	zebra_mac_t *zrmac = NULL; - -	zl3vni = zl3vni_from_vrf(vrf_id); -	if (!zl3vni) -		return; - -	/* find the next hop entry and rmac entry */ -	nh = zl3vni_nh_lookup(zl3vni, vtep_ip); -	if (!nh) -		return; -	zrmac = zl3vni_rmac_lookup(zl3vni, &nh->emac); - -	/* delete the next hop entry */ -	zl3vni_remote_nh_del(zl3vni, nh, host_prefix); - -	/* delete the rmac entry */ -	if (zrmac) -		zl3vni_remote_rmac_del(zl3vni, zrmac, host_prefix); - -} - -void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni, -					   struct ethaddr *rmac, bool use_json) -{ -	zebra_l3vni_t *zl3vni = NULL; -	zebra_mac_t *zrmac = NULL; -	json_object *json = NULL; - -	if (!is_evpn_enabled()) { -		if (use_json) -			vty_out(vty, "{}\n"); -		return; -	} - -	if (use_json) -		json = json_object_new_object(); - -	zl3vni = zl3vni_lookup(l3vni); -	if (!zl3vni) { -		if (use_json) -			vty_out(vty, "{}\n"); -		else -			vty_out(vty, "%% L3-VNI %u doesn't exist\n", l3vni); -		return; -	} - -	zrmac = zl3vni_rmac_lookup(zl3vni, rmac); -	if (!zrmac) { -		if (use_json) -			vty_out(vty, "{}\n"); -		else -			vty_out(vty, -				"%% Requested RMAC doesn't exist in L3-VNI %u", -				l3vni); -		return; -	} - -	zl3vni_print_rmac(zrmac, vty, json); - -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json) -{ -	zebra_l3vni_t *zl3vni; -	uint32_t num_rmacs; -	struct rmac_walk_ctx wctx; -	json_object *json = NULL; - -	if (!is_evpn_enabled()) -		return; - -	zl3vni = zl3vni_lookup(l3vni); -	if (!zl3vni) { -		if (use_json) -			vty_out(vty, "{}\n"); -		else -			vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni); -		return; -	} -	num_rmacs = hashcount(zl3vni->rmac_table); -	if (!num_rmacs) -		return; - -	if (use_json) -		json = json_object_new_object(); - -	memset(&wctx, 0, sizeof(struct rmac_walk_ctx)); -	wctx.vty = vty; -	wctx.json = json; -	if (!use_json) { -		vty_out(vty, "Number of Remote RMACs known for this VNI: %u\n", -			num_rmacs); -		vty_out(vty, "%-17s %-21s\n", "MAC", "Remote VTEP"); -	} else -		json_object_int_add(json, "numRmacs", num_rmacs); - -	hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx); - -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json) -{ -	json_object *json = NULL; -	void *args[2]; - -	if (!is_evpn_enabled()) { -		if (use_json) -			vty_out(vty, "{}\n"); -		return; -	} - -	if (use_json) -		json = json_object_new_object(); - -	args[0] = vty; -	args[1] = json; -	hash_iterate(zrouter.l3vni_table, -		     (void (*)(struct hash_bucket *, -			       void *))zl3vni_print_rmac_hash_all_vni, -		     args); - -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni, -					 struct ipaddr *ip, bool use_json) -{ -	zebra_l3vni_t *zl3vni = NULL; -	zebra_neigh_t *n = NULL; -	json_object *json = NULL; - -	if (!is_evpn_enabled()) { -		if (use_json) -			vty_out(vty, "{}\n"); -		return; -	} - -	if (use_json) -		json = json_object_new_object(); - -	zl3vni = zl3vni_lookup(l3vni); -	if (!zl3vni) { -		if (use_json) -			vty_out(vty, "{}\n"); -		else -			vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni); -		return; -	} - -	n = zl3vni_nh_lookup(zl3vni, ip); -	if (!n) { -		if (use_json) -			vty_out(vty, "{}\n"); -		else -			vty_out(vty, -				"%% Requested next-hop not present for L3-VNI %u", -				l3vni); -		return; -	} - -	zl3vni_print_nh(n, vty, json); - -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, bool use_json) -{ -	uint32_t num_nh; -	struct nh_walk_ctx wctx; -	json_object *json = NULL; -	zebra_l3vni_t *zl3vni = NULL; - -	if (!is_evpn_enabled()) -		return; - -	zl3vni = zl3vni_lookup(l3vni); -	if (!zl3vni) { -		if (use_json) -			vty_out(vty, "{}\n"); -		else -			vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni); -		return; -	} - -	num_nh = hashcount(zl3vni->nh_table); -	if (!num_nh) -		return; - -	if (use_json) -		json = json_object_new_object(); - -	wctx.vty = vty; -	wctx.json = json; -	if (!use_json) { -		vty_out(vty, "Number of NH Neighbors known for this VNI: %u\n", -			num_nh); -		vty_out(vty, "%-15s %-17s\n", "IP", "RMAC"); -	} else -		json_object_int_add(json, "numNextHops", num_nh); - -	hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx); - -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json) -{ -	json_object *json = NULL; -	void *args[2]; - -	if (!is_evpn_enabled()) { -		if (use_json) -			vty_out(vty, "{}\n"); -		return; -	} - -	if (use_json) -		json = json_object_new_object(); - -	args[0] = vty; -	args[1] = json; -	hash_iterate(zrouter.l3vni_table, -		     (void (*)(struct hash_bucket *, -			       void *))zl3vni_print_nh_hash_all_vni, -		     args); - -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -/* - * Display L3 VNI information (VTY command handler). - */ -void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, bool use_json) -{ -	void *args[2]; -	json_object *json = NULL; -	zebra_l3vni_t *zl3vni = NULL; - -	if (!is_evpn_enabled()) { -		if (use_json) -			vty_out(vty, "{}\n"); -		return; -	} - -	zl3vni = zl3vni_lookup(vni); -	if (!zl3vni) { -		if (use_json) -			vty_out(vty, "{}\n"); -		else -			vty_out(vty, "%% VNI %u does not exist\n", vni); -		return; -	} - -	if (use_json) -		json = json_object_new_object(); - -	args[0] = vty; -	args[1] = json; -	zl3vni_print(zl3vni, (void *)args); - -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf, -			       json_object *json_vrfs) -{ -	char buf[ETHER_ADDR_STRLEN]; -	zebra_l3vni_t *zl3vni = NULL; - -	zl3vni = zl3vni_lookup(zvrf->l3vni); -	if (!zl3vni) -		return; - -	if (!json_vrfs) { -		vty_out(vty, "%-37s %-10u %-20s %-20s %-5s %-18s\n", -			zvrf_name(zvrf), zl3vni->vni, -			zl3vni_vxlan_if_name(zl3vni), -			zl3vni_svi_if_name(zl3vni), zl3vni_state2str(zl3vni), -			zl3vni_rmac2str(zl3vni, buf, sizeof(buf))); -	} else { -		json_object *json_vrf = NULL; - -		json_vrf = json_object_new_object(); -		json_object_string_add(json_vrf, "vrf", zvrf_name(zvrf)); -		json_object_int_add(json_vrf, "vni", zl3vni->vni); -		json_object_string_add(json_vrf, "vxlanIntf", -				       zl3vni_vxlan_if_name(zl3vni)); -		json_object_string_add(json_vrf, "sviIntf", -				       zl3vni_svi_if_name(zl3vni)); -		json_object_string_add(json_vrf, "state", -				       zl3vni_state2str(zl3vni)); -		json_object_string_add( -			json_vrf, "routerMac", -			zl3vni_rmac2str(zl3vni, buf, sizeof(buf))); -		json_object_array_add(json_vrfs, json_vrf); -	} -} - -/* - * Display Neighbors for a VNI (VTY command handler). - */ -void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, -				 vni_t vni, bool use_json) -{ -	zebra_evpn_t *zevpn; -	uint32_t num_neigh; -	struct neigh_walk_ctx wctx; -	json_object *json = NULL; - -	if (!is_evpn_enabled()) -		return; -	zevpn = zevpn_lookup(vni); -	if (!zevpn) { -		if (use_json) -			vty_out(vty, "{}\n"); -		else -			vty_out(vty, "%% VNI %u does not exist\n", vni); -		return; -	} -	num_neigh = hashcount(zevpn->neigh_table); -	if (!num_neigh) -		return; - -	if (use_json) -		json = json_object_new_object(); - -	/* Since we have IPv6 addresses to deal with which can vary widely in -	 * size, we try to be a bit more elegant in display by first computing -	 * the maximum width. -	 */ -	memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); -	wctx.zevpn = zevpn; -	wctx.vty = vty; -	wctx.addr_width = 15; -	wctx.json = json; -	hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width, -		     &wctx); - -	if (!use_json) { -		vty_out(vty, -			"Number of ARPs (local and remote) known for this VNI: %u\n", -			num_neigh); -		zebra_evpn_print_neigh_hdr(vty, &wctx); -	} else -		json_object_int_add(json, "numArpNd", num_neigh); - -	hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash, &wctx); -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -/* - * Display neighbors across all VNIs (VTY command handler). - */ -void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf, -				     bool print_dup, bool use_json) -{ -	json_object *json = NULL; -	void *args[3]; - -	if (!is_evpn_enabled()) -		return; - -	if (use_json) -		json = json_object_new_object(); - -	args[0] = vty; -	args[1] = json; -	args[2] = (void *)(ptrdiff_t)print_dup; - -	hash_iterate(zvrf->evpn_table, -		     (void (*)(struct hash_bucket *, -			       void *))zevpn_print_neigh_hash_all_evpn, -		     args); -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -/* - * Display neighbors across all VNIs in detail(VTY command handler). - */ -void zebra_vxlan_print_neigh_all_vni_detail(struct vty *vty, -					    struct zebra_vrf *zvrf, -					    bool print_dup, bool use_json) -{ -	json_object *json = NULL; -	void *args[3]; - -	if (!is_evpn_enabled()) -		return; - -	if (use_json) -		json = json_object_new_object(); - -	args[0] = vty; -	args[1] = json; -	args[2] = (void *)(ptrdiff_t)print_dup; - -	hash_iterate(zvrf->evpn_table, -		     (void (*)(struct hash_bucket *, -			       void *))zevpn_print_neigh_hash_all_evpn_detail, -		     args); -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -/* - * Display specific neighbor for a VNI, if present (VTY command handler). - */ -void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, -					  struct zebra_vrf *zvrf, vni_t vni, -					  struct ipaddr *ip, bool use_json) -{ -	zebra_evpn_t *zevpn; -	zebra_neigh_t *n; -	json_object *json = NULL; - -	if (!is_evpn_enabled()) -		return; -	zevpn = zevpn_lookup(vni); -	if (!zevpn) { -		if (use_json) -			vty_out(vty, "{}\n"); -		else -			vty_out(vty, "%% VNI %u does not exist\n", vni); -		return; -	} -	n = zebra_evpn_neigh_lookup(zevpn, ip); -	if (!n) { -		if (!use_json) -			vty_out(vty, -				"%% Requested neighbor does not exist in VNI %u\n", -				vni); -		return; -	} -	if (use_json) -		json = json_object_new_object(); - -	zebra_evpn_print_neigh(n, vty, json); - -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -/* - * Display neighbors for a VNI from specific VTEP (VTY command handler). - * By definition, these are remote neighbors. - */ -void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, -				      vni_t vni, struct in_addr vtep_ip, -				      bool use_json) -{ -	zebra_evpn_t *zevpn; -	uint32_t num_neigh; -	struct neigh_walk_ctx wctx; -	json_object *json = NULL; - -	if (!is_evpn_enabled()) -		return; -	zevpn = zevpn_lookup(vni); -	if (!zevpn) { -		if (use_json) -			vty_out(vty, "{}\n"); -		else -			vty_out(vty, "%% VNI %u does not exist\n", vni); -		return; -	} -	num_neigh = hashcount(zevpn->neigh_table); -	if (!num_neigh) -		return; - -	memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); -	wctx.zevpn = zevpn; -	wctx.vty = vty; -	wctx.addr_width = 15; -	wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP; -	wctx.r_vtep_ip = vtep_ip; -	wctx.json = json; -	hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width, -		     &wctx); -	hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash, &wctx); - -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -/* - * Display Duplicate detected Neighbors for a VNI - * (VTY command handler). - */ -void zebra_vxlan_print_neigh_vni_dad(struct vty *vty, -				     struct zebra_vrf *zvrf, -				     vni_t vni, -				     bool use_json) -{ -	zebra_evpn_t *zevpn; -	uint32_t num_neigh; -	struct neigh_walk_ctx wctx; -	json_object *json = NULL; - -	if (!is_evpn_enabled()) -		return; - -	zevpn = zevpn_lookup(vni); -	if (!zevpn) { -		vty_out(vty, "%% VNI %u does not exist\n", vni); -		return; -	} - -	num_neigh = hashcount(zevpn->neigh_table); -	if (!num_neigh) -		return; - -	num_neigh = num_dup_detected_neighs(zevpn); -	if (!num_neigh) -		return; - -	if (use_json) -		json = json_object_new_object(); - -	/* Since we have IPv6 addresses to deal with which can vary widely in -	 * size, we try to be a bit more elegant in display by first computing -	 * the maximum width. -	 */ -	memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); -	wctx.zevpn = zevpn; -	wctx.vty = vty; -	wctx.addr_width = 15; -	wctx.json = json; -	hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width, -		     &wctx); - -	if (!use_json) { -		vty_out(vty, -			"Number of ARPs (local and remote) known for this VNI: %u\n", -			num_neigh); -		vty_out(vty, "%*s %-6s %-8s %-17s %-30s\n", -			-wctx.addr_width, "IP", "Type", -			"State", "MAC", "Remote ES/VTEP"); -	} else -		json_object_int_add(json, "numArpNd", num_neigh); - -	hash_iterate(zevpn->neigh_table, zebra_evpn_print_dad_neigh_hash, -		     &wctx); - -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -/* - * Display MACs for a VNI (VTY command handler). - */ -void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, -				vni_t vni, bool use_json) -{ -	zebra_evpn_t *zevpn; -	uint32_t num_macs; -	struct mac_walk_ctx wctx; -	json_object *json = NULL; -	json_object *json_mac = NULL; - -	if (!is_evpn_enabled()) -		return; -	zevpn = zevpn_lookup(vni); -	if (!zevpn) { -		if (use_json) -			vty_out(vty, "{}\n"); -		else -			vty_out(vty, "%% VNI %u does not exist\n", vni); -		return; -	} -	num_macs = num_valid_macs(zevpn); -	if (!num_macs) -		return; - -	if (use_json) { -		json = json_object_new_object(); -		json_mac = json_object_new_object(); -	} - -	memset(&wctx, 0, sizeof(struct mac_walk_ctx)); -	wctx.zevpn = zevpn; -	wctx.vty = vty; -	wctx.json = json_mac; - -	if (!use_json) { -		vty_out(vty, -			"Number of MACs (local and remote) known for this VNI: %u\n", -			num_macs); -			vty_out(vty, -				"Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n"); -			vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC", -				"Type", "Flags", "Intf/Remote ES/VTEP", -				"VLAN", "Seq #'s"); -	} else -		json_object_int_add(json, "numMacs", num_macs); - -	hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, &wctx); - -	if (use_json) { -		json_object_object_add(json, "macs", json_mac); -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -/* - * Display MACs for all VNIs (VTY command handler). - */ -void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf, -				    bool print_dup, bool use_json) -{ -	struct mac_walk_ctx wctx; -	json_object *json = NULL; - -	if (!is_evpn_enabled()) { -		if (use_json) -			vty_out(vty, "{}\n"); -		return; -	} -	if (use_json) -		json = json_object_new_object(); - -	memset(&wctx, 0, sizeof(struct mac_walk_ctx)); -	wctx.vty = vty; -	wctx.json = json; -	wctx.print_dup = print_dup; -	hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn, &wctx); - -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -/* - * Display MACs in detail for all VNIs (VTY command handler). - */ -void zebra_vxlan_print_macs_all_vni_detail(struct vty *vty, -					   struct zebra_vrf *zvrf, -					   bool print_dup, bool use_json) -{ -	struct mac_walk_ctx wctx; -	json_object *json = NULL; - -	if (!is_evpn_enabled()) { -		if (use_json) -			vty_out(vty, "{}\n"); -		return; -	} -	if (use_json) -		json = json_object_new_object(); - -	memset(&wctx, 0, sizeof(struct mac_walk_ctx)); -	wctx.vty = vty; -	wctx.json = json; -	wctx.print_dup = print_dup; -	hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn_detail, -		     &wctx); - -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -/* - * Display MACs for all VNIs (VTY command handler). - */ -void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty, -					 struct zebra_vrf *zvrf, -					 struct in_addr vtep_ip, bool use_json) -{ -	struct mac_walk_ctx wctx; -	json_object *json = NULL; - -	if (!is_evpn_enabled()) -		return; - -	if (use_json) -		json = json_object_new_object(); - -	memset(&wctx, 0, sizeof(struct mac_walk_ctx)); -	wctx.vty = vty; -	wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP; -	wctx.r_vtep_ip = vtep_ip; -	wctx.json = json; -	hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn, &wctx); - -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -/* - * Display specific MAC for a VNI, if present (VTY command handler). - */ -void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, -					vni_t vni, struct ethaddr *macaddr, -					bool use_json) -{ -	zebra_evpn_t *zevpn; -	zebra_mac_t *mac; -	json_object *json = NULL; - -	if (!is_evpn_enabled()) -		return; - -	zevpn = zevpn_lookup(vni); -	if (!zevpn) { -		if (use_json) -			vty_out(vty, "{}\n"); -		else -			vty_out(vty, "%% VNI %u does not exist\n", vni); -		return; -	} -	mac = zebra_evpn_mac_lookup(zevpn, macaddr); -	if (!mac) { -		if (use_json) -			vty_out(vty, "{}\n"); -		else -			vty_out(vty, -				"%% Requested MAC does not exist in VNI %u\n", -				vni); -		return; -	} - -	if (use_json) -		json = json_object_new_object(); - -	zebra_evpn_print_mac(mac, vty, json); -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -/* Print Duplicate MACs per VNI */ -void zebra_vxlan_print_macs_vni_dad(struct vty *vty, -				    struct zebra_vrf *zvrf, -				    vni_t vni, bool use_json) -{ -	zebra_evpn_t *zevpn; -	struct mac_walk_ctx wctx; -	uint32_t num_macs; -	json_object *json = NULL; -	json_object *json_mac = NULL; - -	if (!is_evpn_enabled()) -		return; - -	zevpn = zevpn_lookup(vni); -	if (!zevpn) { -		vty_out(vty, "%% VNI %u does not exist\n", vni); -		return; -	} - -	num_macs = num_valid_macs(zevpn); -	if (!num_macs) -		return; - -	num_macs = num_dup_detected_macs(zevpn); -	if (!num_macs) -		return; - -	if (use_json) { -		json = json_object_new_object(); -		json_mac = json_object_new_object(); -	} - -	memset(&wctx, 0, sizeof(struct mac_walk_ctx)); -	wctx.zevpn = zevpn; -	wctx.vty = vty; -	wctx.json = json_mac; - -	if (!use_json) { -		vty_out(vty, -		"Number of MACs (local and remote) known for this VNI: %u\n", -			num_macs); -		vty_out(vty, "%-17s %-6s %-5s %-30s %-5s\n", "MAC", "Type", -			"Flags", "Intf/Remote ES/VTEP", "VLAN"); -	} else -		json_object_int_add(json, "numMacs", num_macs); - -	hash_iterate(zevpn->mac_table, zebra_evpn_print_dad_mac_hash, &wctx); - -	if (use_json) { -		json_object_object_add(json, "macs", json_mac); -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} - -} - -int zebra_vxlan_clear_dup_detect_vni_mac(struct zebra_vrf *zvrf, vni_t vni, -					 struct ethaddr *macaddr) -{ -	zebra_evpn_t *zevpn; -	zebra_mac_t *mac; -	struct listnode *node = NULL; -	zebra_neigh_t *nbr = NULL; - -	if (!is_evpn_enabled()) -		return 0; - -	zevpn = zevpn_lookup(vni); -	if (!zevpn) { -		zlog_warn("VNI %u does not exist\n", vni); -		return -1; -	} - -	mac = zebra_evpn_mac_lookup(zevpn, macaddr); -	if (!mac) { -		zlog_warn("Requested MAC does not exist in VNI %u\n", vni); -		return -1; -	} - -	if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) { -		zlog_warn("Requested MAC is not duplicate detected\n"); -		return -1; -	} - -	/* Remove all IPs as duplicate associcated with this MAC */ -	for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) { -		/* For local neigh mark inactive so MACIP update is generated -		 * to BGP. This is a scenario where MAC update received -		 * and detected as duplicate which marked neigh as duplicate. -		 * Later local neigh update did not get a chance to relay -		 * to BGP. Similarly remote macip update, neigh needs to be -		 * installed locally. -		 */ -		if (zvrf->dad_freeze && -		    CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) { -			if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) -				ZEBRA_NEIGH_SET_INACTIVE(nbr); -			else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) -				zebra_evpn_rem_neigh_install( -					zevpn, nbr, false /*was_static*/); -		} - -		UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); -		nbr->dad_count = 0; -		nbr->detect_start_time.tv_sec = 0; -		nbr->dad_dup_detect_time = 0; -	} - -	UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE); -	mac->dad_count = 0; -	mac->detect_start_time.tv_sec = 0; -	mac->detect_start_time.tv_usec = 0; -	mac->dad_dup_detect_time = 0; -	THREAD_OFF(mac->dad_mac_auto_recovery_timer); - -	/* warn-only action return */ -	if (!zvrf->dad_freeze) -		return 0; - -	/* Local: Notify Peer VTEPs, Remote: Install the entry */ -	if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { -		/* Inform to BGP */ -		if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr, -						      mac->flags, mac->loc_seq, -						      mac->es)) -			return 0; - -		/* Process all neighbors associated with this MAC. */ -		zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0, -							     0 /*es_change*/); - -	} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { -		zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac); - -		/* Install the entry. */ -		zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */); -	} - -	return 0; -} - -int zebra_vxlan_clear_dup_detect_vni_ip(struct zebra_vrf *zvrf, vni_t vni, -					struct ipaddr *ip) -{ -	zebra_evpn_t *zevpn; -	zebra_neigh_t *nbr; -	zebra_mac_t *mac; -	char buf[INET6_ADDRSTRLEN]; -	char buf2[ETHER_ADDR_STRLEN]; - -	if (!is_evpn_enabled()) -		return 0; - -	zevpn = zevpn_lookup(vni); -	if (!zevpn) { -		zlog_debug("VNI %u does not exist\n", vni); -		return -1; -	} - -	nbr = zebra_evpn_neigh_lookup(zevpn, ip); -	if (!nbr) { -		zlog_warn("Requested host IP does not exist in VNI %u\n", vni); -		return -1; -	} - -	ipaddr2str(&nbr->ip, buf, sizeof(buf)); - -	if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) { -		zlog_warn("Requested host IP %s is not duplicate detected\n", -			  buf); -		return -1; -	} - -	mac = zebra_evpn_mac_lookup(zevpn, &nbr->emac); - -	if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) { -		zlog_warn( -			"Requested IP's associated MAC %s is still in duplicate state\n", -			prefix_mac2str(&nbr->emac, buf2, sizeof(buf2))); -		return -1; -	} - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u", -			   __func__, buf, nbr->flags, nbr->loc_seq); - -	UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); -	nbr->dad_count = 0; -	nbr->detect_start_time.tv_sec = 0; -	nbr->detect_start_time.tv_usec = 0; -	nbr->dad_dup_detect_time = 0; -	THREAD_OFF(nbr->dad_ip_auto_recovery_timer); - -	if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) { -		zebra_evpn_neigh_send_add_to_client(zevpn->vni, ip, &nbr->emac, -						    nbr->mac, nbr->flags, -						    nbr->loc_seq); -	} else if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) { -		zebra_evpn_rem_neigh_install(zevpn, nbr, false /*was_static*/); -	} - -	return 0; -} - -static void zevpn_clear_dup_mac_hash(struct hash_bucket *bucket, void *ctxt) -{ -	struct mac_walk_ctx *wctx = ctxt; -	zebra_mac_t *mac; -	zebra_evpn_t *zevpn; -	struct listnode *node = NULL; -	zebra_neigh_t *nbr = NULL; - -	mac = (zebra_mac_t *)bucket->data; -	if (!mac) -		return; - -	zevpn = wctx->zevpn; - -	if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) -		return; - -	UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE); -	mac->dad_count = 0; -	mac->detect_start_time.tv_sec = 0; -	mac->detect_start_time.tv_usec = 0; -	mac->dad_dup_detect_time = 0; -	THREAD_OFF(mac->dad_mac_auto_recovery_timer); - -	/* Remove all IPs as duplicate associcated with this MAC */ -	for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) { -		if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL) -		    && nbr->dad_count) -			ZEBRA_NEIGH_SET_INACTIVE(nbr); - -		UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); -		nbr->dad_count = 0; -		nbr->detect_start_time.tv_sec = 0; -		nbr->dad_dup_detect_time = 0; -	} - -	/* Local: Notify Peer VTEPs, Remote: Install the entry */ -	if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { -		/* Inform to BGP */ -		if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr, -						      mac->flags, mac->loc_seq, -						      mac->es)) -			return; - -		/* Process all neighbors associated with this MAC. */ -		zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0, -							     0 /*es_change*/); - -	} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { -		zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac); - -		/* Install the entry. */ -		zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */); -	} -} - -static void zevpn_clear_dup_detect_hash_vni_all(struct hash_bucket *bucket, -					    void **args) -{ -	zebra_evpn_t *zevpn; -	struct zebra_vrf *zvrf; -	struct mac_walk_ctx m_wctx; -	struct neigh_walk_ctx n_wctx; - -	zevpn = (zebra_evpn_t *)bucket->data; -	if (!zevpn) -		return; - -	zvrf = (struct zebra_vrf *)args[0]; - -	if (hashcount(zevpn->neigh_table)) { -		memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx)); -		n_wctx.zevpn = zevpn; -		n_wctx.zvrf = zvrf; -		hash_iterate(zevpn->neigh_table, -			     zebra_evpn_clear_dup_neigh_hash, &n_wctx); -	} - -	if (num_valid_macs(zevpn)) { -		memset(&m_wctx, 0, sizeof(struct mac_walk_ctx)); -		m_wctx.zevpn = zevpn; -		m_wctx.zvrf = zvrf; -		hash_iterate(zevpn->mac_table, zevpn_clear_dup_mac_hash, &m_wctx); -	} - -} - -int zebra_vxlan_clear_dup_detect_vni_all(struct zebra_vrf *zvrf) -{ -	void *args[1]; - -	if (!is_evpn_enabled()) -		return 0; - -	args[0] = zvrf; - -	hash_iterate(zvrf->evpn_table, -		     (void (*)(struct hash_bucket *, void *)) -		     zevpn_clear_dup_detect_hash_vni_all, args); - -	return 0; -} - -int zebra_vxlan_clear_dup_detect_vni(struct zebra_vrf *zvrf, vni_t vni) -{ -	zebra_evpn_t *zevpn; -	struct mac_walk_ctx m_wctx; -	struct neigh_walk_ctx n_wctx; - -	if (!is_evpn_enabled()) -		return 0; - -	zevpn = zevpn_lookup(vni); -	if (!zevpn) { -		zlog_warn("VNI %u does not exist\n", vni); -		return CMD_WARNING; -	} - -	if (hashcount(zevpn->neigh_table)) { -		memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx)); -		n_wctx.zevpn = zevpn; -		n_wctx.zvrf = zvrf; -		hash_iterate(zevpn->neigh_table, -			     zebra_evpn_clear_dup_neigh_hash, &n_wctx); -	} - -	if (num_valid_macs(zevpn)) { -		memset(&m_wctx, 0, sizeof(struct mac_walk_ctx)); -		m_wctx.zevpn = zevpn; -		m_wctx.zvrf = zvrf; -		hash_iterate(zevpn->mac_table, zevpn_clear_dup_mac_hash, &m_wctx); -	} - -	return 0; -} - -/* - * Display MACs for a VNI from specific VTEP (VTY command handler). - */ -void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, -				     vni_t vni, struct in_addr vtep_ip, -				     bool use_json) -{ -	zebra_evpn_t *zevpn; -	uint32_t num_macs; -	struct mac_walk_ctx wctx; -	json_object *json = NULL; -	json_object *json_mac = NULL; - -	if (!is_evpn_enabled()) -		return; -	zevpn = zevpn_lookup(vni); -	if (!zevpn) { -		if (use_json) -			vty_out(vty, "{}\n"); -		else -			vty_out(vty, "%% VNI %u does not exist\n", vni); -		return; -	} -	num_macs = num_valid_macs(zevpn); -	if (!num_macs) -		return; - -	if (use_json) { -		json = json_object_new_object(); -		json_mac = json_object_new_object(); -	} - -	memset(&wctx, 0, sizeof(struct mac_walk_ctx)); -	wctx.zevpn = zevpn; -	wctx.vty = vty; -	wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP; -	wctx.r_vtep_ip = vtep_ip; -	wctx.json = json_mac; -	hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, &wctx); - -	if (use_json) { -		json_object_int_add(json, "numMacs", wctx.count); -		if (wctx.count) -			json_object_object_add(json, "macs", json_mac); -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - - -/* - * Display VNI information (VTY command handler). - * - * use_json flag indicates that output should be in JSON format. - * json_array is non NULL when JSON output needs to be aggregated (by the - * caller) and then printed, otherwise, JSON evpn vni info is printed - * right away. - */ -void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, -			   bool use_json, json_object *json_array) -{ -	json_object *json = NULL; -	void *args[2]; -	zebra_l3vni_t *zl3vni = NULL; -	zebra_evpn_t *zevpn = NULL; - -	if (!is_evpn_enabled()) -		return; - -	if (use_json) -		json = json_object_new_object(); - -	args[0] = vty; -	args[1] = json; - -	zl3vni = zl3vni_lookup(vni); -	if (zl3vni) { -		zl3vni_print(zl3vni, (void *)args); -	} else { -		zevpn = zevpn_lookup(vni); -		if (zevpn) -			zevpn_print(zevpn, (void *)args); -		else if (!json) -			vty_out(vty, "%% VNI %u does not exist\n", vni); -	} - -	if (use_json) { -		/* -		 * Each "json" object contains info about 1 VNI. -		 * When "json_array" is non-null, we aggreggate the json output -		 * into json_array and print it as a JSON array. -		 */ -		if (json_array) -			json_object_array_add(json_array, json); -		else { -			vty_out(vty, "%s\n", json_object_to_json_string_ext( -				json, JSON_C_TO_STRING_PRETTY)); -			json_object_free(json); -		} -	} -} - -/* Display all global details for EVPN */ -void zebra_vxlan_print_evpn(struct vty *vty, bool uj) -{ -	int num_l2vnis = 0; -	int num_l3vnis = 0; -	int num_vnis = 0; -	json_object *json = NULL; -	struct zebra_vrf *zvrf = NULL; - -	if (!is_evpn_enabled()) -		return; - -	zvrf = zebra_vrf_get_evpn(); -	if (!zvrf) -		return; - -	num_l3vnis = hashcount(zrouter.l3vni_table); -	num_l2vnis = hashcount(zvrf->evpn_table); -	num_vnis = num_l2vnis + num_l3vnis; - -	if (uj) { -		json = json_object_new_object(); -		json_object_string_add(json, "advertiseGatewayMacip", -				       zvrf->advertise_gw_macip ? "Yes" : "No"); -		json_object_int_add(json, "numVnis", num_vnis); -		json_object_int_add(json, "numL2Vnis", num_l2vnis); -		json_object_int_add(json, "numL3Vnis", num_l3vnis); -		if (zvrf->dup_addr_detect) -			json_object_boolean_true_add(json, -						"isDuplicateAddrDetection"); -		else -			json_object_boolean_false_add(json, -						"isDuplicateAddrDetection"); -		json_object_int_add(json, "maxMoves", zvrf->dad_max_moves); -		json_object_int_add(json, "detectionTime", zvrf->dad_time); -		json_object_int_add(json, "detectionFreezeTime", -				    zvrf->dad_freeze_time); - -	} else { -		vty_out(vty, "L2 VNIs: %u\n", num_l2vnis); -		vty_out(vty, "L3 VNIs: %u\n", num_l3vnis); -		vty_out(vty, "Advertise gateway mac-ip: %s\n", -			zvrf->advertise_gw_macip ? "Yes" : "No"); -		vty_out(vty, "Advertise svi mac-ip: %s\n", -			zvrf->advertise_svi_macip ? "Yes" : "No"); -		vty_out(vty, "Duplicate address detection: %s\n", -			zvrf->dup_addr_detect ? "Enable" : "Disable"); -		vty_out(vty, "  Detection max-moves %u, time %d\n", -			zvrf->dad_max_moves, zvrf->dad_time); -		if (zvrf->dad_freeze) { -			if (zvrf->dad_freeze_time) -				vty_out(vty, "  Detection freeze %u\n", -					zvrf->dad_freeze_time); -			else -				vty_out(vty, "  Detection freeze %s\n", -					"permanent"); -		} -	} - -	if (uj) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -/* - * Display VNI hash table (VTY command handler). - */ -void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf, -			    bool use_json) -{ -	json_object *json = NULL; -	void *args[2]; - -	if (!is_evpn_enabled()) -		return; - -	if (use_json) -		json = json_object_new_object(); -	else -		vty_out(vty, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI", -			"Type", "VxLAN IF", "# MACs", "# ARPs", -			"# Remote VTEPs", "Tenant VRF"); - -	args[0] = vty; -	args[1] = json; - -	/* Display all L2-VNIs */ -	hash_iterate(zvrf->evpn_table, -		     (void (*)(struct hash_bucket *, void *))zevpn_print_hash, -		     args); - -	/* Display all L3-VNIs */ -	hash_iterate(zrouter.l3vni_table, -		     (void (*)(struct hash_bucket *, void *))zl3vni_print_hash, -		     args); - -	if (use_json) { -		vty_out(vty, "%s\n", json_object_to_json_string_ext( -					     json, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json); -	} -} - -void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS) -{ -	struct stream *s; -	int time = 0; -	uint32_t max_moves = 0; -	uint32_t freeze_time = 0; -	bool dup_addr_detect = false; -	bool freeze = false; - -	s = msg; -	STREAM_GETL(s, dup_addr_detect); -	STREAM_GETL(s, time); -	STREAM_GETL(s, max_moves); -	STREAM_GETL(s, freeze); -	STREAM_GETL(s, freeze_time); - -	/* DAD previous state was enabled, and new state is disable, -	 * clear all duplicate detected addresses. -	 */ -	if (zvrf->dup_addr_detect && !dup_addr_detect) -		zebra_vxlan_clear_dup_detect_vni_all(zvrf); - -	zvrf->dup_addr_detect = dup_addr_detect; -	zvrf->dad_time = time; -	zvrf->dad_max_moves = max_moves; -	zvrf->dad_freeze = freeze; -	zvrf->dad_freeze_time = freeze_time; - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug( -			"VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u", -			vrf_id_to_name(zvrf->vrf->vrf_id), -			zvrf->dup_addr_detect ? "enable" : "disable", -			zvrf->dad_max_moves, -			zvrf->dad_time, -			zvrf->dad_freeze ? "enable" : "disable", -			zvrf->dad_freeze_time); - -stream_failure: -	return; -} - -/* - * Display VNI hash table in detail(VTY command handler). - */ -void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf, -				   bool use_json) -{ -	json_object *json_array = NULL; -	struct zebra_ns *zns = NULL; -	struct zevpn_show zes; - -	if (!is_evpn_enabled()) -		return; - -	zns = zebra_ns_lookup(NS_DEFAULT); -	if (!zns) -		return; - -	if (use_json) -		json_array = json_object_new_array(); - -	zes.vty = vty; -	zes.json = json_array; -	zes.zvrf = zvrf; -	zes.use_json = use_json; - -	/* Display all L2-VNIs */ -	hash_iterate( -		zvrf->evpn_table, -		(void (*)(struct hash_bucket *, void *))zevpn_print_hash_detail, -		&zes); - -	/* Display all L3-VNIs */ -	hash_iterate(zrouter.l3vni_table, -		     (void (*)(struct hash_bucket *, -			       void *))zl3vni_print_hash_detail, -		     &zes); - -	if (use_json) { -		vty_out(vty, "%s\n", -			json_object_to_json_string_ext( -				json_array, JSON_C_TO_STRING_PRETTY)); -		json_object_free(json_array); -	} -} - -/* - * Handle neighbor delete notification from the kernel (on a VLAN device - * / L3 interface). This may result in either the neighbor getting deleted - * from our database or being re-added to the kernel (if it is a valid - * remote neighbor). - */ -int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp, -					struct interface *link_if, -					struct ipaddr *ip) -{ -	char buf[INET6_ADDRSTRLEN]; -	zebra_evpn_t *zevpn = NULL; -	zebra_l3vni_t *zl3vni = NULL; - -	/* check if this is a remote neigh entry corresponding to remote -	 * next-hop -	 */ -	zl3vni = zl3vni_from_svi(ifp, link_if); -	if (zl3vni) -		return zl3vni_local_nh_del(zl3vni, ip); - -	/* We are only interested in neighbors on an SVI that resides on top -	 * of a VxLAN bridge. -	 */ -	zevpn = zevpn_from_svi(ifp, link_if); -	if (!zevpn) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug( -				"%s: Del neighbor %s EVPN is not present for interface %s", -				__func__, ipaddr2str(ip, buf, sizeof(buf)), -				ifp->name); -		return 0; -	} - -	if (!zevpn->vxlan_if) { -		zlog_debug( -			"VNI %u hash %p doesn't have intf upon local neighbor DEL", -			zevpn->vni, zevpn); -		return -1; -	} - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u", -			   ipaddr2str(ip, buf, sizeof(buf)), ifp->name, -			   ifp->ifindex, zevpn->vni); - -	return zebra_evpn_neigh_del_ip(zevpn, ip); -} - -/* - * Handle neighbor add or update notification from the kernel (on a VLAN - * device / L3 interface). This is typically for a local neighbor but can - * also be for a remote neighbor (e.g., ageout notification). It could - * also be a "move" scenario. - */ -int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp, -					   struct interface *link_if, -					   struct ipaddr *ip, -					   struct ethaddr *macaddr, -					   uint16_t state, -					   bool is_ext, -					   bool is_router, -					   bool local_inactive, bool dp_static) -{ -	char buf[ETHER_ADDR_STRLEN]; -	char buf2[INET6_ADDRSTRLEN]; -	zebra_evpn_t *zevpn = NULL; -	zebra_l3vni_t *zl3vni = NULL; - -	/* check if this is a remote neigh entry corresponding to remote -	 * next-hop -	 */ -	zl3vni = zl3vni_from_svi(ifp, link_if); -	if (zl3vni) -		return zl3vni_local_nh_add_update(zl3vni, ip, state); - -	/* We are only interested in neighbors on an SVI that resides on top -	 * of a VxLAN bridge. -	 */ -	zevpn = zevpn_from_svi(ifp, link_if); -	if (!zevpn) -		return 0; - -	if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_NEIGH) -		zlog_debug( -			"Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s%s%s-> L2-VNI %u", -			ipaddr2str(ip, buf2, sizeof(buf2)), -			prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, -			ifp->ifindex, state, is_ext ? "ext-learned " : "", -			is_router ? "router " : "", -			local_inactive ? "local_inactive " : "", -			zevpn->vni); - -	/* Is this about a local neighbor or a remote one? */ -	if (!is_ext) -		return zebra_evpn_local_neigh_update(zevpn, ifp, ip, macaddr, -						     is_router, local_inactive, -						     dp_static); - -	return zebra_evpn_remote_neigh_update(zevpn, ifp, ip, macaddr, state); -} - -static int32_t -zebra_vxlan_remote_macip_helper(bool add, struct stream *s, vni_t *vni, -				struct ethaddr *macaddr, uint16_t *ipa_len, -				struct ipaddr *ip, struct in_addr *vtep_ip, -				uint8_t *flags, uint32_t *seq, esi_t *esi) -{ -	uint16_t l = 0; - -	/* -	 * Obtain each remote MACIP and process. -	 * Message contains VNI, followed by MAC followed by IP (if any) -	 * followed by remote VTEP IP. -	 */ -	memset(ip, 0, sizeof(*ip)); -	STREAM_GETL(s, *vni); -	STREAM_GET(macaddr->octet, s, ETH_ALEN); -	STREAM_GETL(s, *ipa_len); - -	if (*ipa_len) { -		if (*ipa_len == IPV4_MAX_BYTELEN) -			ip->ipa_type = IPADDR_V4; -		else if (*ipa_len == IPV6_MAX_BYTELEN) -			ip->ipa_type = IPADDR_V6; -		else { -			if (IS_ZEBRA_DEBUG_VXLAN) -				zlog_debug( -					"ipa_len *must* be %d or %d bytes in length not %d", -					IPV4_MAX_BYTELEN, IPV6_MAX_BYTELEN, -					*ipa_len); -			goto stream_failure; -		} - -		STREAM_GET(&ip->ip.addr, s, *ipa_len); -	} -	l += 4 + ETH_ALEN + 4 + *ipa_len; -	STREAM_GET(&vtep_ip->s_addr, s, IPV4_MAX_BYTELEN); -	l += IPV4_MAX_BYTELEN; - -	if (add) { -		STREAM_GETC(s, *flags); -		STREAM_GETL(s, *seq); -		l += 5; -		STREAM_GET(esi, s, sizeof(esi_t)); -		l += sizeof(esi_t); -	} - -	return l; - -stream_failure: -	return -1; -} - -/* - * Handle message from client to delete a remote MACIP for a VNI. - */ -void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS) -{ -	struct stream *s; -	vni_t vni; -	struct ethaddr macaddr; -	struct ipaddr ip; -	struct in_addr vtep_ip; -	uint16_t l = 0, ipa_len; -	char buf[ETHER_ADDR_STRLEN]; -	char buf1[INET6_ADDRSTRLEN]; - -	memset(&macaddr, 0, sizeof(struct ethaddr)); -	memset(&ip, 0, sizeof(struct ipaddr)); -	memset(&vtep_ip, 0, sizeof(struct in_addr)); - -	s = msg; - -	while (l < hdr->length) { -		int res_length = zebra_vxlan_remote_macip_helper( -			false, s, &vni, &macaddr, &ipa_len, &ip, &vtep_ip, NULL, -			NULL, NULL); - -		if (res_length == -1) -			goto stream_failure; - -		l += res_length; -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug( -				"Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s", -				vni, -				prefix_mac2str(&macaddr, buf, sizeof(buf)), -				ipa_len ? " IP " : "", -				ipa_len ? -				ipaddr2str(&ip, buf1, sizeof(buf1)) : "", -				inet_ntoa(vtep_ip), -				zebra_route_string(client->proto)); - -		process_remote_macip_del(vni, &macaddr, ipa_len, &ip, vtep_ip); -	} - -stream_failure: -	return; -} - -/* - * Handle message from client to add a remote MACIP for a VNI. This - * could be just the add of a MAC address or the add of a neighbor - * (IP+MAC). - */ -void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) -{ -	struct stream *s; -	vni_t vni; -	struct ethaddr macaddr; -	struct ipaddr ip; -	struct in_addr vtep_ip; -	uint16_t l = 0, ipa_len; -	uint8_t flags = 0; -	uint32_t seq; -	char buf[ETHER_ADDR_STRLEN]; -	char buf1[INET6_ADDRSTRLEN]; -	esi_t esi; -	char esi_buf[ESI_STR_LEN]; - -	memset(&macaddr, 0, sizeof(struct ethaddr)); -	memset(&ip, 0, sizeof(struct ipaddr)); -	memset(&vtep_ip, 0, sizeof(struct in_addr)); - -	if (!EVPN_ENABLED(zvrf)) { -		zlog_debug("EVPN not enabled, ignoring remote MACIP ADD"); -		return; -	} - -	s = msg; - -	while (l < hdr->length) { -		int res_length = zebra_vxlan_remote_macip_helper( -			true, s, &vni, &macaddr, &ipa_len, &ip, &vtep_ip, -			&flags, &seq, &esi); - -		if (res_length == -1) -			goto stream_failure; - -		l += res_length; -		if (IS_ZEBRA_DEBUG_VXLAN) { -			if (memcmp(&esi, zero_esi, sizeof(esi_t))) -				esi_to_str(&esi, esi_buf, sizeof(esi_buf)); -			else -				strcpy(esi_buf, "-"); -			zlog_debug( -				"Recv %sMACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s ESI %s from %s", -				(flags & ZEBRA_MACIP_TYPE_SYNC_PATH) ? -				"sync-" : "", -				vni, -				prefix_mac2str(&macaddr, buf, sizeof(buf)), -				ipa_len ? " IP " : "", -				ipa_len ? -				ipaddr2str(&ip, buf1, sizeof(buf1)) : "", -				flags, seq, inet_ntoa(vtep_ip), esi_buf, -				zebra_route_string(client->proto)); -		} - -		process_remote_macip_add(vni, &macaddr, ipa_len, &ip, -					 flags, seq, vtep_ip, &esi); -	} - -stream_failure: -	return; -} - -/* - * Handle remote vtep delete by kernel; re-add the vtep if we have it - */ -int zebra_vxlan_check_readd_vtep(struct interface *ifp, -				 struct in_addr vtep_ip) -{ -	struct zebra_if *zif; -	struct zebra_vrf *zvrf = NULL; -	struct zebra_l2info_vxlan *vxl; -	vni_t vni; -	zebra_evpn_t *zevpn = NULL; -	zebra_vtep_t *zvtep = NULL; - -	zif = ifp->info; -	assert(zif); -	vxl = &zif->l2info.vxl; -	vni = vxl->vni; - -	/* If EVPN is not enabled, nothing to do. */ -	if (!is_evpn_enabled()) -		return 0; - -	/* Locate VRF corresponding to interface. */ -	zvrf = vrf_info_lookup(ifp->vrf_id); -	if (!zvrf) -		return -1; - -	/* Locate hash entry; it is expected to exist. */ -	zevpn = zevpn_lookup(vni); -	if (!zevpn) -		return 0; - -	/* If the remote vtep entry doesn't exists nothing to do */ -	zvtep = zevpn_vtep_find(zevpn, &vtep_ip); -	if (!zvtep) -		return 0; - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug( -			"Del MAC for remote VTEP %s intf %s(%u) VNI %u - readd", -			inet_ntoa(vtep_ip), ifp->name, ifp->ifindex, vni); - -	zevpn_vtep_install(zevpn, zvtep); -	return 0; -} - -/* - * Handle notification of MAC add/update over VxLAN. If the kernel is notifying - * us, this must involve a multihoming scenario. Treat this as implicit delete - * of any prior local MAC. - */ -int zebra_vxlan_check_del_local_mac(struct interface *ifp, -				    struct interface *br_if, -				    struct ethaddr *macaddr, vlanid_t vid) -{ -	struct zebra_if *zif; -	struct zebra_l2info_vxlan *vxl; -	vni_t vni; -	zebra_evpn_t *zevpn; -	zebra_mac_t *mac; -	char buf[ETHER_ADDR_STRLEN]; - -	zif = ifp->info; -	assert(zif); -	vxl = &zif->l2info.vxl; -	vni = vxl->vni; - -	/* Check if EVPN is enabled. */ -	if (!is_evpn_enabled()) -		return 0; - -	/* Locate hash entry; it is expected to exist. */ -	zevpn = zevpn_lookup(vni); -	if (!zevpn) -		return 0; - -	/* If entry doesn't exist, nothing to do. */ -	mac = zebra_evpn_mac_lookup(zevpn, macaddr); -	if (!mac) -		return 0; - -	/* Is it a local entry? */ -	if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) -		return 0; - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug( -			"Add/update remote MAC %s intf %s(%u) VNI %u flags 0x%x - del local", -			prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, -			ifp->ifindex, vni, mac->flags); - -	/* Remove MAC from BGP. */ -	zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr, mac->flags, -					  false /* force */); - -	/* -	 * If there are no neigh associated with the mac delete the mac -	 * else mark it as AUTO for forward reference -	 */ -	if (!listcount(mac->neigh_list)) { -		zebra_evpn_mac_del(zevpn, mac); -	} else { -		UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_LOCAL_FLAGS); -		UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); -		SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); -	} - -	return 0; -} - -/* - * Handle remote MAC delete by kernel; readd the remote MAC if we have it. - * This can happen because the remote MAC entries are also added as "dynamic", - * so the kernel can ageout the entry. - */ -int zebra_vxlan_check_readd_remote_mac(struct interface *ifp, -				       struct interface *br_if, -				       struct ethaddr *macaddr, vlanid_t vid) -{ -	struct zebra_if *zif = NULL; -	struct zebra_l2info_vxlan *vxl = NULL; -	vni_t vni; -	zebra_evpn_t *zevpn = NULL; -	zebra_l3vni_t *zl3vni = NULL; -	zebra_mac_t *mac = NULL; -	char buf[ETHER_ADDR_STRLEN]; - -	zif = ifp->info; -	assert(zif); -	vxl = &zif->l2info.vxl; -	vni = vxl->vni; - -	/* Check if EVPN is enabled. */ -	if (!is_evpn_enabled()) -		return 0; - -	/* check if this is a remote RMAC and readd simillar to remote macs */ -	zl3vni = zl3vni_lookup(vni); -	if (zl3vni) -		return zebra_vxlan_readd_remote_rmac(zl3vni, macaddr); - -	/* Locate hash entry; it is expected to exist. */ -	zevpn = zevpn_lookup(vni); -	if (!zevpn) -		return 0; - -	/* If entry doesn't exist, nothing to do. */ -	mac = zebra_evpn_mac_lookup(zevpn, macaddr); -	if (!mac) -		return 0; - -	/* Is it a remote entry? */ -	if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) -		return 0; - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd", -			   prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, -			   ifp->ifindex, vni); - -	zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */); -	return 0; -} - -/* - * Handle local MAC delete (on a port or VLAN corresponding to this VNI). - */ -int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if, -			      struct ethaddr *macaddr, vlanid_t vid) -{ -	zebra_evpn_t *zevpn; - -	/* We are interested in MACs only on ports or (port, VLAN) that -	 * map to a VNI. -	 */ -	zevpn = zevpn_map_vlan(ifp, br_if, vid); -	if (!zevpn) -		return 0; -	if (!zevpn->vxlan_if) { -		zlog_debug( -			"VNI %u hash %p doesn't have intf upon local MAC DEL", -			zevpn->vni, zevpn); -		return -1; -	} - -	return zebra_evpn_del_local_mac(zevpn, macaddr, ifp); -} - -/* - * Handle local MAC add (on a port or VLAN corresponding to this VNI). - */ -int zebra_vxlan_local_mac_add_update(struct interface *ifp, -				     struct interface *br_if, -				     struct ethaddr *macaddr, vlanid_t vid, -					 bool sticky, bool local_inactive, -					 bool dp_static) -{ -	zebra_evpn_t *zevpn; -	struct zebra_vrf *zvrf; -	char buf[ETHER_ADDR_STRLEN]; - -	/* We are interested in MACs only on ports or (port, VLAN) that -	 * map to an EVPN. -	 */ -	zevpn = zevpn_map_vlan(ifp, br_if, vid); -	if (!zevpn) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug( -				"        Add/Update %sMAC %s intf %s(%u) VID %u, could not find EVPN", -				sticky ? "sticky " : "", -				prefix_mac2str(macaddr, buf, sizeof(buf)), -				ifp->name, ifp->ifindex, vid); -		return 0; -	} - -	if (!zevpn->vxlan_if) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug( -				"        VNI %u hash %p doesn't have intf upon local MAC ADD", -				zevpn->vni, zevpn); -		return -1; -	} - -	zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id); -	if (!zvrf) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("        No Vrf found for vrf_id: %d", -				   zevpn->vxlan_if->vrf_id); -		return -1; -	} - -	return zebra_evpn_add_update_local_mac(zvrf, zevpn, ifp, macaddr, vid, -					       sticky, local_inactive, -					       dp_static); -} - -/* - * Handle message from client to delete a remote VTEP for an EVPN. - */ -void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS) -{ -	struct stream *s; -	unsigned short l = 0; -	vni_t vni; -	struct in_addr vtep_ip; -	zebra_evpn_t *zevpn; -	zebra_vtep_t *zvtep; -	struct interface *ifp; -	struct zebra_if *zif; - -	if (!is_evpn_enabled()) { -		zlog_debug( -			"%s: EVPN is not enabled yet we have received a vtep del command", -			__func__); -		return; -	} - -	if (!EVPN_ENABLED(zvrf)) { -		zlog_debug("Recv MACIP DEL for non-EVPN VRF %u", -			  zvrf_id(zvrf)); -		return; -	} - -	s = msg; - -	while (l < hdr->length) { -		int flood_control __attribute__((unused)); - -		/* Obtain each remote VTEP and process. */ -		STREAM_GETL(s, vni); -		l += 4; -		STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN); -		l += IPV4_MAX_BYTELEN; - -		/* Flood control is intentionally ignored right now */ -		STREAM_GETL(s, flood_control); -		l += 4; - -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("Recv VTEP_DEL %s VNI %u from %s", -				   inet_ntoa(vtep_ip), vni, -				   zebra_route_string(client->proto)); - -		/* Locate VNI hash entry - expected to exist. */ -		zevpn = zevpn_lookup(vni); -		if (!zevpn) { -			if (IS_ZEBRA_DEBUG_VXLAN) -				zlog_debug( -					"Failed to locate VNI hash upon remote VTEP DEL, " -					"VNI %u", -					vni); -			continue; -		} - -		ifp = zevpn->vxlan_if; -		if (!ifp) { -			zlog_debug( -				"VNI %u hash %p doesn't have intf upon remote VTEP DEL", -				zevpn->vni, zevpn); -			continue; -		} -		zif = ifp->info; - -		/* If down or not mapped to a bridge, we're done. */ -		if (!if_is_operative(ifp) || !zif->brslave_info.br_if) -			continue; - -		/* If the remote VTEP does not exist, there's nothing more to -		 * do. -		 * Otherwise, uninstall any remote MACs pointing to this VTEP -		 * and -		 * then, the VTEP entry itself and remove it. -		 */ -		zvtep = zevpn_vtep_find(zevpn, &vtep_ip); -		if (!zvtep) -			continue; - -		zevpn_vtep_uninstall(zevpn, &vtep_ip); -		zevpn_vtep_del(zevpn, zvtep); -	} - -stream_failure: -	return; -} - -/* - * Handle message from client to add a remote VTEP for an EVPN. - */ -void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS) -{ -	struct stream *s; -	unsigned short l = 0; -	vni_t vni; -	struct in_addr vtep_ip; -	zebra_evpn_t *zevpn; -	struct interface *ifp; -	struct zebra_if *zif; -	int flood_control; -	zebra_vtep_t *zvtep; - -	if (!is_evpn_enabled()) { -		zlog_debug( -			"%s: EVPN not enabled yet we received a vtep_add zapi call", -			__func__); -		return; -	} - -	if (!EVPN_ENABLED(zvrf)) { -		zlog_debug("Recv MACIP ADD for non-EVPN VRF %u", -			  zvrf_id(zvrf)); -		return; -	} - -	s = msg; - -	while (l < hdr->length) { -		/* Obtain each remote VTEP and process. */ -		STREAM_GETL(s, vni); -		l += 4; -		STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN); -		STREAM_GETL(s, flood_control); -		l += IPV4_MAX_BYTELEN + 4; - -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("Recv VTEP_ADD %s VNI %u flood %d from %s", -					inet_ntoa(vtep_ip), vni, flood_control, -					zebra_route_string(client->proto)); - -		/* Locate VNI hash entry - expected to exist. */ -		zevpn = zevpn_lookup(vni); -		if (!zevpn) { -			flog_err( -				EC_ZEBRA_VTEP_ADD_FAILED, -				"Failed to locate EVPN hash upon remote VTEP ADD, VNI %u", -				vni); -			continue; -		} - -		ifp = zevpn->vxlan_if; -		if (!ifp) { -			flog_err( -				EC_ZEBRA_VTEP_ADD_FAILED, -				"VNI %u hash %p doesn't have intf upon remote VTEP ADD", -				zevpn->vni, zevpn); -			continue; -		} - -		zif = ifp->info; - -		/* If down or not mapped to a bridge, we're done. */ -		if (!if_is_operative(ifp) || !zif->brslave_info.br_if) -			continue; - -		zvtep = zevpn_vtep_find(zevpn, &vtep_ip); -		if (zvtep) { -			/* If the remote VTEP already exists check if -			 * the flood mode has changed -			 */ -			if (zvtep->flood_control != flood_control) { -				if (zvtep->flood_control -						== VXLAN_FLOOD_DISABLED) -					/* old mode was head-end-replication but -					 * is no longer; get rid of the HER fdb -					 * entry installed before -					 */ -					zevpn_vtep_uninstall(zevpn, &vtep_ip); -				zvtep->flood_control = flood_control; -				zevpn_vtep_install(zevpn, zvtep); -			} -		} else { -			zvtep = zevpn_vtep_add(zevpn, &vtep_ip, flood_control); -			if (zvtep) -				zevpn_vtep_install(zevpn, zvtep); -			else -				flog_err(EC_ZEBRA_VTEP_ADD_FAILED, -					"Failed to add remote VTEP, VNI %u zevpn %p", -					vni, zevpn); -		} -	} - -stream_failure: -	return; -} - -/* - * Add/Del gateway macip to evpn - * g/w can be: - *  1. SVI interface on a vlan aware bridge - *  2. SVI interface on a vlan unaware bridge - *  3. vrr interface (MACVLAN) associated to a SVI - * We advertise macip routes for an interface if it is associated to VxLan vlan - */ -int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p, -				 int add) -{ -	struct ipaddr ip; -	struct ethaddr macaddr; -	zebra_evpn_t *zevpn = NULL; - -	memset(&ip, 0, sizeof(struct ipaddr)); -	memset(&macaddr, 0, sizeof(struct ethaddr)); - -	/* Check if EVPN is enabled. */ -	if (!is_evpn_enabled()) -		return 0; - -	if (IS_ZEBRA_IF_MACVLAN(ifp)) { -		struct interface *svi_if = -			NULL; /* SVI corresponding to the MACVLAN */ -		struct zebra_if *ifp_zif = -			NULL; /* Zebra daemon specific info for MACVLAN */ -		struct zebra_if *svi_if_zif = -			NULL; /* Zebra daemon specific info for SVI*/ - -		ifp_zif = ifp->info; -		if (!ifp_zif) -			return -1; - -		/* -		 * for a MACVLAN interface the link represents the svi_if -		 */ -		svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), -						   ifp_zif->link_ifindex); -		if (!svi_if) { -			zlog_debug("MACVLAN %s(%u) without link information", -				   ifp->name, ifp->ifindex); -			return -1; -		} - -		if (IS_ZEBRA_IF_VLAN(svi_if)) { -			/* -			 * If it is a vlan aware bridge then the link gives the -			 * bridge information -			 */ -			struct interface *svi_if_link = NULL; - -			svi_if_zif = svi_if->info; -			if (svi_if_zif) { -				svi_if_link = if_lookup_by_index_per_ns( -					zebra_ns_lookup(NS_DEFAULT), -					svi_if_zif->link_ifindex); -				zevpn = zevpn_from_svi(svi_if, svi_if_link); -			} -		} else if (IS_ZEBRA_IF_BRIDGE(svi_if)) { -			/* -			 * If it is a vlan unaware bridge then svi is the bridge -			 * itself -			 */ -			zevpn = zevpn_from_svi(svi_if, svi_if); -		} -	} else if (IS_ZEBRA_IF_VLAN(ifp)) { -		struct zebra_if *svi_if_zif = -			NULL; /* Zebra daemon specific info for SVI */ -		struct interface *svi_if_link = -			NULL; /* link info for the SVI = bridge info */ - -		svi_if_zif = ifp->info; -		if (svi_if_zif) { -			svi_if_link = if_lookup_by_index_per_ns( -				zebra_ns_lookup(NS_DEFAULT), -				svi_if_zif->link_ifindex); -			if (svi_if_link) -				zevpn = zevpn_from_svi(ifp, svi_if_link); -		} -	} else if (IS_ZEBRA_IF_BRIDGE(ifp)) { -		zevpn = zevpn_from_svi(ifp, ifp); -	} - -	if (!zevpn) -		return 0; - -	if (!zevpn->vxlan_if) { -		zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up", -			   zevpn->vni, zevpn); -		return -1; -	} - - -	memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN); - -	if (p->family == AF_INET) { -		ip.ipa_type = IPADDR_V4; -		memcpy(&(ip.ipaddr_v4), &(p->u.prefix4), -		       sizeof(struct in_addr)); -	} else if (p->family == AF_INET6) { -		ip.ipa_type = IPADDR_V6; -		memcpy(&(ip.ipaddr_v6), &(p->u.prefix6), -		       sizeof(struct in6_addr)); -	} - - -	if (add) -		zevpn_gw_macip_add(ifp, zevpn, &macaddr, &ip); -	else -		zevpn_gw_macip_del(ifp, zevpn, &ip); - -	return 0; -} - -/* - * Handle SVI interface going down. - * SVI can be associated to either L3-VNI or L2-VNI. - * For L2-VNI: At this point, this is a NOP since - *	the kernel deletes the neighbor entries on this SVI (if any). - *      We only need to update the vrf corresponding to zevpn. - * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete - *	from bgp - */ -int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if) -{ -	zebra_l3vni_t *zl3vni = NULL; - -	zl3vni = zl3vni_from_svi(ifp, link_if); -	if (zl3vni) { - -		/* process l3-vni down */ -		zebra_vxlan_process_l3vni_oper_down(zl3vni); - -		/* remove association with svi-if */ -		zl3vni->svi_if = NULL; -	} else { -		zebra_evpn_t *zevpn = NULL; - -		/* since we dont have svi corresponding to zevpn, we associate it -		 * to default vrf. Note: the corresponding neigh entries on the -		 * SVI would have already been deleted */ -		zevpn = zevpn_from_svi(ifp, link_if); -		if (zevpn) { -			zevpn->vrf_id = VRF_DEFAULT; - -			/* update the tenant vrf in BGP */ -			zevpn_send_add_to_client(zevpn); -		} -	} -	return 0; -} - -/* - * Handle SVI interface coming up. - * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni - * vxlan intf). - * For L2-VNI: we need to install any remote neighbors entried (used for - * apr-suppression) - * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI - */ -int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if) -{ -	zebra_evpn_t *zevpn = NULL; -	zebra_l3vni_t *zl3vni = NULL; - -	zl3vni = zl3vni_from_svi(ifp, link_if); -	if (zl3vni) { - -		/* associate with svi */ -		zl3vni->svi_if = ifp; - -		/* process oper-up */ -		if (is_l3vni_oper_up(zl3vni)) -			zebra_vxlan_process_l3vni_oper_up(zl3vni); -	} else { - -		/* process SVI up for l2-vni */ -		struct neigh_walk_ctx n_wctx; - -		zevpn = zevpn_from_svi(ifp, link_if); -		if (!zevpn) -			return 0; - -		if (!zevpn->vxlan_if) { -			zlog_debug( -				"VNI %u hash %p doesn't have intf upon SVI up", -				zevpn->vni, zevpn); -			return -1; -		} - -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug( -				"SVI %s(%u) VNI %u VRF %s is UP, installing neighbors", -				ifp->name, ifp->ifindex, zevpn->vni, -				vrf_id_to_name(ifp->vrf_id)); - -		/* update the vrf information for l2-vni and inform bgp */ -		zevpn->vrf_id = ifp->vrf_id; -		zevpn_send_add_to_client(zevpn); - -		/* Install any remote neighbors for this VNI. */ -		memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx)); -		n_wctx.zevpn = zevpn; -		hash_iterate(zevpn->neigh_table, zebra_evpn_install_neigh_hash, -			     &n_wctx); -	} - -	return 0; -} - -/* - * Handle MAC-VLAN interface going down. - * L3VNI: When MAC-VLAN interface goes down, - * find its associated SVI and update type2/type-5 routes - * with SVI as RMAC - */ -void zebra_vxlan_macvlan_down(struct interface *ifp) -{ -	zebra_l3vni_t *zl3vni = NULL; -	struct zebra_if *zif, *link_zif; -	struct interface *link_ifp, *link_if; - -	zif = ifp->info; -	assert(zif); -	link_ifp = zif->link; -	if (!link_ifp) { -		if (IS_ZEBRA_DEBUG_VXLAN) { -			struct interface *ifp; - -			ifp = if_lookup_by_index_all_vrf(zif->link_ifindex); -			zlog_debug("macvlan parent link is not found. Parent index %d ifp %s", -				zif->link_ifindex, ifp ? ifp->name : " "); -		} -		return; -	} -	link_zif = link_ifp->info; -	assert(link_zif); - -	link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), -					    link_zif->link_ifindex); - -	zl3vni = zl3vni_from_svi(link_ifp, link_if); -	if (zl3vni) { -		zl3vni->mac_vlan_if = NULL; -		if (is_l3vni_oper_up(zl3vni)) -			zebra_vxlan_process_l3vni_oper_up(zl3vni); -	} -} - -/* - * Handle MAC-VLAN interface going up. - * L3VNI: When MAC-VLAN interface comes up, - * find its associated SVI and update type-2 routes - * with MAC-VLAN's MAC as RMAC and for type-5 routes - * use SVI's MAC as RMAC. - */ -void zebra_vxlan_macvlan_up(struct interface *ifp) -{ -	zebra_l3vni_t *zl3vni = NULL; -	struct zebra_if *zif, *link_zif; -	struct interface *link_ifp, *link_if; - -	zif = ifp->info; -	assert(zif); -	link_ifp = zif->link; -	link_zif = link_ifp->info; -	assert(link_zif); - -	link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), -					    link_zif->link_ifindex); -	zl3vni = zl3vni_from_svi(link_ifp, link_if); -	if (zl3vni) { -		/* associate with macvlan (VRR) interface */ -		zl3vni->mac_vlan_if = ifp; - -		/* process oper-up */ -		if (is_l3vni_oper_up(zl3vni)) -			zebra_vxlan_process_l3vni_oper_up(zl3vni); -	} -} - -/* - * Handle VxLAN interface down - */ -int zebra_vxlan_if_down(struct interface *ifp) -{ -	vni_t vni; -	struct zebra_if *zif = NULL; -	struct zebra_l2info_vxlan *vxl = NULL; -	zebra_l3vni_t *zl3vni = NULL; -	zebra_evpn_t *zevpn; - -	/* Check if EVPN is enabled. */ -	if (!is_evpn_enabled()) -		return 0; - -	zif = ifp->info; -	assert(zif); -	vxl = &zif->l2info.vxl; -	vni = vxl->vni; - -	zl3vni = zl3vni_lookup(vni); -	if (zl3vni) { -		/* process-if-down for l3-vni */ -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp->name, -				   ifp->ifindex, vni); - -		zebra_vxlan_process_l3vni_oper_down(zl3vni); -	} else { -		/* process if-down for l2-vni */ -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp->name, -				   ifp->ifindex, vni); - -		/* Locate hash entry; it is expected to exist. */ -		zevpn = zevpn_lookup(vni); -		if (!zevpn) { -			zlog_debug( -				"Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u", -				ifp->name, ifp->ifindex, vni); -			return -1; -		} - -		assert(zevpn->vxlan_if == ifp); - -		/* Delete this VNI from BGP. */ -		zevpn_send_del_to_client(zevpn); - -		/* Free up all neighbors and MACs, if any. */ -		zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH); -		zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC); - -		/* Free up all remote VTEPs, if any. */ -		zevpn_vtep_del_all(zevpn, 1); -	} -	return 0; -} - -/* - * Handle VxLAN interface up - update BGP if required. - */ -int zebra_vxlan_if_up(struct interface *ifp) -{ -	vni_t vni; -	struct zebra_if *zif = NULL; -	struct zebra_l2info_vxlan *vxl = NULL; -	zebra_evpn_t *zevpn = NULL; -	zebra_l3vni_t *zl3vni = NULL; - -	/* Check if EVPN is enabled. */ -	if (!is_evpn_enabled()) -		return 0; - -	zif = ifp->info; -	assert(zif); -	vxl = &zif->l2info.vxl; -	vni = vxl->vni; - -	zl3vni = zl3vni_lookup(vni); -	if (zl3vni) { -		/* we need to associate with SVI, if any, we can associate with -		 * svi-if only after association with vxlan-intf is complete -		 */ -		zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni); -		zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni); - -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("Intf %s(%u) L3-VNI %u is UP svi_if %s mac_vlan_if %s" -				, ifp->name, ifp->ifindex, vni, -				zl3vni->svi_if ? zl3vni->svi_if->name : "NIL", -				zl3vni->mac_vlan_if ? -				zl3vni->mac_vlan_if->name : "NIL"); - -		if (is_l3vni_oper_up(zl3vni)) -			zebra_vxlan_process_l3vni_oper_up(zl3vni); -	} else { -		/* Handle L2-VNI add */ -		struct interface *vlan_if = NULL; - -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp->name, -				   ifp->ifindex, vni); - -		/* Locate hash entry; it is expected to exist. */ -		zevpn = zevpn_lookup(vni); -		if (!zevpn) { -			zlog_debug( -				"Failed to locate EVPN hash at UP, IF %s(%u) VNI %u", -				ifp->name, ifp->ifindex, vni); -			return -1; -		} - -		assert(zevpn->vxlan_if == ifp); -		vlan_if = zvni_map_to_svi(vxl->access_vlan, -					  zif->brslave_info.br_if); -		if (vlan_if) { -			zevpn->vrf_id = vlan_if->vrf_id; -			zl3vni = zl3vni_from_vrf(vlan_if->vrf_id); -			if (zl3vni) -				listnode_add_sort(zl3vni->l2vnis, zevpn); -		} - -		/* If part of a bridge, inform BGP about this VNI. */ -		/* Also, read and populate local MACs and neighbors. */ -		if (zif->brslave_info.br_if) { -			zevpn_send_add_to_client(zevpn); -			zevpn_read_mac_neigh(zevpn, ifp); -		} -	} - -	return 0; -} - -/* - * Handle VxLAN interface delete. Locate and remove entry in hash table - * and update BGP, if required. - */ -int zebra_vxlan_if_del(struct interface *ifp) -{ -	vni_t vni; -	struct zebra_if *zif = NULL; -	struct zebra_l2info_vxlan *vxl = NULL; -	zebra_evpn_t *zevpn = NULL; -	zebra_l3vni_t *zl3vni = NULL; - -	/* Check if EVPN is enabled. */ -	if (!is_evpn_enabled()) -		return 0; - -	zif = ifp->info; -	assert(zif); -	vxl = &zif->l2info.vxl; -	vni = vxl->vni; - -	zl3vni = zl3vni_lookup(vni); -	if (zl3vni) { - -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("Del L3-VNI %u intf %s(%u)", vni, ifp->name, -				   ifp->ifindex); - -		/* process oper-down for l3-vni */ -		zebra_vxlan_process_l3vni_oper_down(zl3vni); - -		/* remove the association with vxlan_if */ -		memset(&zl3vni->local_vtep_ip, 0, sizeof(struct in_addr)); -		zl3vni->vxlan_if = NULL; -	} else { - -		/* process if-del for l2-vni*/ -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("Del L2-VNI %u intf %s(%u)", vni, ifp->name, -				   ifp->ifindex); - -		/* Locate hash entry; it is expected to exist. */ -		zevpn = zevpn_lookup(vni); -		if (!zevpn) { -			zlog_debug( -				"Failed to locate VNI hash at del, IF %s(%u) VNI %u", -				ifp->name, ifp->ifindex, vni); -			return 0; -		} - -		/* remove from l3-vni list */ -		zl3vni = zl3vni_from_vrf(zevpn->vrf_id); -		if (zl3vni) -			listnode_delete(zl3vni->l2vnis, zevpn); -		/* Delete VNI from BGP. */ -		zevpn_send_del_to_client(zevpn); - -		/* Free up all neighbors and MAC, if any. */ -		zebra_evpn_neigh_del_all(zevpn, 0, 0, DEL_ALL_NEIGH); -		zebra_evpn_mac_del_all(zevpn, 0, 0, DEL_ALL_MAC); - -		/* Free up all remote VTEPs, if any. */ -		zevpn_vtep_del_all(zevpn, 0); - -		/* Delete the hash entry. */ -		if (zevpn_del(zevpn)) { -			flog_err(EC_ZEBRA_VNI_DEL_FAILED, -				 "Failed to del EVPN hash %p, IF %s(%u) VNI %u", -				 zevpn, ifp->name, ifp->ifindex, zevpn->vni); -			return -1; -		} -	} -	return 0; -} - -/* - * Handle VxLAN interface update - change to tunnel IP, master or VLAN. - */ -int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags) -{ -	vni_t vni; -	struct zebra_if *zif = NULL; -	struct zebra_l2info_vxlan *vxl = NULL; -	zebra_evpn_t *zevpn = NULL; -	zebra_l3vni_t *zl3vni = NULL; - -	/* Check if EVPN is enabled. */ -	if (!is_evpn_enabled()) -		return 0; - -	zif = ifp->info; -	assert(zif); -	vxl = &zif->l2info.vxl; -	vni = vxl->vni; - -	zl3vni = zl3vni_lookup(vni); -	if (zl3vni) { - -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug( -				"Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x", -				vni, ifp->name, ifp->ifindex, vxl->access_vlan, -				inet_ntoa(vxl->vtep_ip), -				zif->brslave_info.bridge_ifindex, chgflags); - -		/* Removed from bridge? Cleanup and return */ -		if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE) -		    && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) { -			zebra_vxlan_process_l3vni_oper_down(zl3vni); -			return 0; -		} - -		/* access-vlan change - process oper down, associate with new -		 * svi_if and then process oper up again -		 */ -		if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) { -			if (if_is_operative(ifp)) { -				zebra_vxlan_process_l3vni_oper_down(zl3vni); -				zl3vni->svi_if = NULL; -				zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni); -				zl3vni->mac_vlan_if = -					zl3vni_map_to_mac_vlan_if(zl3vni); -				zl3vni->local_vtep_ip = vxl->vtep_ip; -				if (is_l3vni_oper_up(zl3vni)) -					zebra_vxlan_process_l3vni_oper_up( -						zl3vni); -			} -		} - -		/* -		 * local-ip change - process oper down, associate with new -		 * local-ip and then process oper up again -		 */ -		if (chgflags & ZEBRA_VXLIF_LOCAL_IP_CHANGE) { -			if (if_is_operative(ifp)) { -				zebra_vxlan_process_l3vni_oper_down(zl3vni); -				zl3vni->local_vtep_ip = vxl->vtep_ip; -				if (is_l3vni_oper_up(zl3vni)) -					zebra_vxlan_process_l3vni_oper_up( -						zl3vni); -			} -		} - -		/* Update local tunnel IP. */ -		zl3vni->local_vtep_ip = vxl->vtep_ip; - -		/* if we have a valid new master, process l3-vni oper up */ -		if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) { -			if (if_is_operative(ifp) && is_l3vni_oper_up(zl3vni)) -				zebra_vxlan_process_l3vni_oper_up(zl3vni); -		} -	} else { - -		/* Update VNI hash. */ -		zevpn = zevpn_lookup(vni); -		if (!zevpn) { -			zlog_debug( -				"Failed to find EVPN hash on update, IF %s(%u) VNI %u", -				ifp->name, ifp->ifindex, vni); -			return -1; -		} - -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug( -				"Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x", -				vni, ifp->name, ifp->ifindex, vxl->access_vlan, -				inet_ntoa(vxl->vtep_ip), -				zif->brslave_info.bridge_ifindex, chgflags); - -		/* Removed from bridge? Cleanup and return */ -		if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE) -		    && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) { -			/* Delete from client, remove all remote VTEPs */ -			/* Also, free up all MACs and neighbors. */ -			zevpn_send_del_to_client(zevpn); -			zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH); -			zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC); -			zevpn_vtep_del_all(zevpn, 1); -			return 0; -		} - -		/* Handle other changes. */ -		if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) { -			/* Remove all existing local neigh and MACs for this VNI -			 * (including from BGP) -			 */ -			zebra_evpn_neigh_del_all(zevpn, 0, 1, DEL_LOCAL_MAC); -			zebra_evpn_mac_del_all(zevpn, 0, 1, DEL_LOCAL_MAC); -		} - -		if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr || -			zevpn->mcast_grp.s_addr != vxl->mcast_grp.s_addr) { -			zebra_vxlan_sg_deref(zevpn->local_vtep_ip, -				zevpn->mcast_grp); -			zebra_vxlan_sg_ref(vxl->vtep_ip, vxl->mcast_grp); -			zevpn->local_vtep_ip = vxl->vtep_ip; -			zevpn->mcast_grp = vxl->mcast_grp; -			/* on local vtep-ip check if ES orig-ip -			 * needs to be updated -			 */ -			zebra_evpn_es_set_base_evpn(zevpn); -		} -		zevpn_vxlan_if_set(zevpn, ifp, true /* set */); -		/* Take further actions needed. -		 * Note that if we are here, there is a change of interest. -		 */ -		/* If down or not mapped to a bridge, we're done. */ -		if (!if_is_operative(ifp) || !zif->brslave_info.br_if) -			return 0; - -		/* Inform BGP, if there is a change of interest. */ -		if (chgflags -			& (ZEBRA_VXLIF_MASTER_CHANGE | -			   ZEBRA_VXLIF_LOCAL_IP_CHANGE | -			   ZEBRA_VXLIF_MCAST_GRP_CHANGE)) -			zevpn_send_add_to_client(zevpn); - -		/* If there is a valid new master or a VLAN mapping change, -		 * read and populate local MACs and neighbors. -		 * Also, reinstall any remote MACs and neighbors -		 * for this VNI (based on new VLAN). -		 */ -		if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) -			zevpn_read_mac_neigh(zevpn, ifp); -		else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) { -			struct mac_walk_ctx m_wctx; -			struct neigh_walk_ctx n_wctx; - -			zevpn_read_mac_neigh(zevpn, ifp); - -			memset(&m_wctx, 0, sizeof(struct mac_walk_ctx)); -			m_wctx.zevpn = zevpn; -			hash_iterate(zevpn->mac_table, zevpn_install_mac_hash, -				     &m_wctx); - -			memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx)); -			n_wctx.zevpn = zevpn; -			hash_iterate(zevpn->neigh_table, -				     zebra_evpn_install_neigh_hash, &n_wctx); -		} -	} - -	return 0; -} - -/* - * Handle VxLAN interface add. - */ -int zebra_vxlan_if_add(struct interface *ifp) -{ -	vni_t vni; -	struct zebra_if *zif = NULL; -	struct zebra_l2info_vxlan *vxl = NULL; -	zebra_evpn_t *zevpn = NULL; -	zebra_l3vni_t *zl3vni = NULL; - -	/* Check if EVPN is enabled. */ -	if (!is_evpn_enabled()) -		return 0; - -	zif = ifp->info; -	assert(zif); -	vxl = &zif->l2info.vxl; -	vni = vxl->vni; - -	zl3vni = zl3vni_lookup(vni); -	if (zl3vni) { - -		/* process if-add for l3-vni*/ -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug( -				"Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u", -				vni, ifp->name, ifp->ifindex, vxl->access_vlan, -				inet_ntoa(vxl->vtep_ip), -				zif->brslave_info.bridge_ifindex); - -		/* associate with vxlan_if */ -		zl3vni->local_vtep_ip = vxl->vtep_ip; -		zl3vni->vxlan_if = ifp; - -		/* Associate with SVI, if any. We can associate with svi-if only -		 * after association with vxlan_if is complete */ -		zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni); - -		zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni); - -		if (is_l3vni_oper_up(zl3vni)) -			zebra_vxlan_process_l3vni_oper_up(zl3vni); -	} else { - -		/* process if-add for l2-vni */ -		struct interface *vlan_if = NULL; - -		/* Create or update EVPN hash. */ -		zevpn = zevpn_lookup(vni); -		if (!zevpn) { -			zevpn = zevpn_add(vni); -			if (!zevpn) { -				flog_err( -					EC_ZEBRA_VNI_ADD_FAILED, -					"Failed to add EVPN hash, IF %s(%u) VNI %u", -					ifp->name, ifp->ifindex, vni); -				return -1; -			} -		} - -		if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr || -			zevpn->mcast_grp.s_addr != vxl->mcast_grp.s_addr) { -			zebra_vxlan_sg_deref(zevpn->local_vtep_ip, -				zevpn->mcast_grp); -			zebra_vxlan_sg_ref(vxl->vtep_ip, vxl->mcast_grp); -			zevpn->local_vtep_ip = vxl->vtep_ip; -			zevpn->mcast_grp = vxl->mcast_grp; -			/* on local vtep-ip check if ES orig-ip -			 * needs to be updated -			 */ -			zebra_evpn_es_set_base_evpn(zevpn); -		} -		zevpn_vxlan_if_set(zevpn, ifp, true /* set */); -		vlan_if = zvni_map_to_svi(vxl->access_vlan, -					  zif->brslave_info.br_if); -		if (vlan_if) { -			zevpn->vrf_id = vlan_if->vrf_id; -			zl3vni = zl3vni_from_vrf(vlan_if->vrf_id); -			if (zl3vni) -				listnode_add_sort(zl3vni->l2vnis, zevpn); -		} - -		if (IS_ZEBRA_DEBUG_VXLAN) { -			char addr_buf1[INET_ADDRSTRLEN]; -			char addr_buf2[INET_ADDRSTRLEN]; - -			inet_ntop(AF_INET, &vxl->vtep_ip, -					addr_buf1, INET_ADDRSTRLEN); -			inet_ntop(AF_INET, &vxl->mcast_grp, -					addr_buf2, INET_ADDRSTRLEN); - -			zlog_debug( -				"Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s mcast_grp %s master %u", -				vni, -				vlan_if ? vrf_id_to_name(vlan_if->vrf_id) -					: VRF_DEFAULT_NAME, -				ifp->name, ifp->ifindex, vxl->access_vlan, -				addr_buf1, addr_buf2, -				zif->brslave_info.bridge_ifindex); -		} - -		/* If down or not mapped to a bridge, we're done. */ -		if (!if_is_operative(ifp) || !zif->brslave_info.br_if) -			return 0; - -		/* Inform BGP */ -		zevpn_send_add_to_client(zevpn); - -		/* Read and populate local MACs and neighbors */ -		zevpn_read_mac_neigh(zevpn, ifp); -	} - -	return 0; -} - -int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni, -				    char *err, int err_str_sz, int filter, -				    int add) -{ -	zebra_l3vni_t *zl3vni = NULL; -	struct zebra_vrf *zvrf_evpn = NULL; - -	zvrf_evpn = zebra_vrf_get_evpn(); -	if (!zvrf_evpn) -		return -1; - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf), vni, -			   add ? "ADD" : "DEL"); - -	if (add) { - -		zebra_vxlan_handle_vni_transition(zvrf, vni, add); - -		/* check if the vni is already present under zvrf */ -		if (zvrf->l3vni) { -			snprintf(err, err_str_sz, -				 "VNI is already configured under the vrf"); -			return -1; -		} - -		/* check if this VNI is already present in the system */ -		zl3vni = zl3vni_lookup(vni); -		if (zl3vni) { -			snprintf(err, err_str_sz, -				 "VNI is already configured as L3-VNI"); -			return -1; -		} - -		/* add the L3-VNI to the global table */ -		zl3vni = zl3vni_add(vni, zvrf_id(zvrf)); -		if (!zl3vni) { -			snprintf(err, err_str_sz, "Could not add L3-VNI"); -			return -1; -		} - -		/* associate the vrf with vni */ -		zvrf->l3vni = vni; - -		/* set the filter in l3vni to denote if we are using l3vni only -		 * for prefix routes -		 */ -		if (filter) -			SET_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY); - -		/* associate with vxlan-intf; -		 * we need to associate with the vxlan-intf first -		 */ -		zl3vni->vxlan_if = zl3vni_map_to_vxlan_if(zl3vni); - -		/* associate with corresponding SVI interface, we can associate -		 * with svi-if only after vxlan interface association is -		 * complete -		 */ -		zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni); - -		zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni); - -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug( -				"%s: l3vni %u svi_if %s mac_vlan_if %s", -				__func__, vni, -				zl3vni->svi_if ? zl3vni->svi_if->name : "NIL", -				zl3vni->mac_vlan_if ? zl3vni->mac_vlan_if->name -						    : "NIL"); - -		/* formulate l2vni list */ -		hash_iterate(zvrf_evpn->evpn_table, zevpn_add_to_l3vni_list, -			     zl3vni); - -		if (is_l3vni_oper_up(zl3vni)) -			zebra_vxlan_process_l3vni_oper_up(zl3vni); - -	} else { -		zl3vni = zl3vni_lookup(vni); -		if (!zl3vni) { -			snprintf(err, err_str_sz, "VNI doesn't exist"); -			return -1; -		} - -		if (zvrf->l3vni != vni) { -			snprintf(err, err_str_sz, -					"VNI %d doesn't exist in VRF: %s", -					vni, zvrf->vrf->name); -			return -1; -		} - -		if (filter && !CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)) { -			snprintf(err, ERR_STR_SZ, -				 "prefix-routes-only is not set for the vni"); -			return -1; -		} - -		zebra_vxlan_process_l3vni_oper_down(zl3vni); - -		/* delete and uninstall all rmacs */ -		hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry, -			     zl3vni); - -		/* delete and uninstall all next-hops */ -		hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry, -			     zl3vni); - -		zvrf->l3vni = 0; -		zl3vni_del(zl3vni); - -		zebra_vxlan_handle_vni_transition(zvrf, vni, add); -	} -	return 0; -} - -int zebra_vxlan_vrf_enable(struct zebra_vrf *zvrf) -{ -	zebra_l3vni_t *zl3vni = NULL; - -	if (zvrf->l3vni) -		zl3vni = zl3vni_lookup(zvrf->l3vni); -	if (!zl3vni) -		return 0; - -	zl3vni->vrf_id = zvrf_id(zvrf); -	if (is_l3vni_oper_up(zl3vni)) -		zebra_vxlan_process_l3vni_oper_up(zl3vni); -	return 0; -} - -int zebra_vxlan_vrf_disable(struct zebra_vrf *zvrf) -{ -	zebra_l3vni_t *zl3vni = NULL; - -	if (zvrf->l3vni) -		zl3vni = zl3vni_lookup(zvrf->l3vni); -	if (!zl3vni) -		return 0; - -	zl3vni->vrf_id = VRF_UNKNOWN; -	zebra_vxlan_process_l3vni_oper_down(zl3vni); -	return 0; -} - -int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf) -{ -	zebra_l3vni_t *zl3vni = NULL; -	vni_t vni; - -	if (zvrf->l3vni) -		zl3vni = zl3vni_lookup(zvrf->l3vni); -	if (!zl3vni) -		return 0; - -	vni = zl3vni->vni; -	zl3vni_del(zl3vni); -	zebra_vxlan_handle_vni_transition(zvrf, vni, 0); - -	return 0; -} - -/* - * Handle message from client to specify the flooding mechanism for - * BUM packets. The default is to do head-end (ingress) replication - * and the other supported option is to disable it. This applies to - * all BUM traffic and disabling it applies to both the transmit and - * receive direction. - */ -void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS) -{ -	struct stream *s; -	enum vxlan_flood_control flood_ctrl; - -	if (!EVPN_ENABLED(zvrf)) { -		zlog_err("EVPN flood control for non-EVPN VRF %u", -			 zvrf_id(zvrf)); -		return; -	} - -	s = msg; -	STREAM_GETC(s, flood_ctrl); - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("EVPN flood control %u, currently %u", -			   flood_ctrl, zvrf->vxlan_flood_ctrl); - -	if (zvrf->vxlan_flood_ctrl == flood_ctrl) -		return; - -	zvrf->vxlan_flood_ctrl = flood_ctrl; - -	/* Install or uninstall flood entries corresponding to -	 * remote VTEPs. -	 */ -	hash_iterate(zvrf->evpn_table, zevpn_handle_flooding_remote_vteps, -		     zvrf); - -stream_failure: -	return; -} - -/* - * Handle message from client to enable/disable advertisement of svi macip - * routes - */ -void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS) -{ -	struct stream *s; -	int advertise; -	vni_t vni = 0; -	zebra_evpn_t *zevpn = NULL; -	struct interface *ifp = NULL; - -	if (!EVPN_ENABLED(zvrf)) { -		zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u", -			  zvrf_id(zvrf)); -		return; -	} - -	s = msg; -	STREAM_GETC(s, advertise); -	STREAM_GETL(s, vni); - -	if (!vni) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("EVPN SVI-MACIP Adv %s, currently %s", -				   advertise ? "enabled" : "disabled", -				   advertise_svi_macip_enabled(NULL) -					   ? "enabled" -					   : "disabled"); - -		if (zvrf->advertise_svi_macip == advertise) -			return; - - -		if (advertise) { -			zvrf->advertise_svi_macip = advertise; -			hash_iterate(zvrf->evpn_table, -				     zevpn_gw_macip_add_for_evpn_hash, NULL); -		} else { -			hash_iterate(zvrf->evpn_table, -				     zevpn_svi_macip_del_for_evpn_hash, NULL); -			zvrf->advertise_svi_macip = advertise; -		} - -	} else { -		struct zebra_if *zif = NULL; -		struct zebra_l2info_vxlan zl2_info; -		struct interface *vlan_if = NULL; - -		zevpn = zevpn_lookup(vni); -		if (!zevpn) -			return; - -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug( -				"EVPN SVI macip Adv %s on VNI %d , currently %s", -				advertise ? "enabled" : "disabled", vni, -				advertise_svi_macip_enabled(zevpn) -					? "enabled" -					: "disabled"); - -		if (zevpn->advertise_svi_macip == advertise) -			return; - -		/* Store flag even though SVI is not present. -		 * Once SVI comes up triggers self MAC-IP route add. -		 */ -		zevpn->advertise_svi_macip = advertise; - -		ifp = zevpn->vxlan_if; -		if (!ifp) -			return; - -		zif = ifp->info; - -		/* If down or not mapped to a bridge, we're done. */ -		if (!if_is_operative(ifp) || !zif->brslave_info.br_if) -			return; - -		zl2_info = zif->l2info.vxl; -		vlan_if = zvni_map_to_svi(zl2_info.access_vlan, -					  zif->brslave_info.br_if); -		if (!vlan_if) -			return; - -		if (advertise) { -			/* Add primary SVI MAC-IP */ -			zevpn_add_macip_for_intf(vlan_if, zevpn); -		} else { -			/* Del primary SVI MAC-IP */ -			zevpn_del_macip_for_intf(vlan_if, zevpn); -		} -	} - -stream_failure: -	return; -} - -/* - * Handle message from client to enable/disable advertisement of g/w macip - * routes - */ -void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS) -{ -	struct stream *s; -	int advertise; -	vni_t vni = 0; -	zebra_evpn_t *zevpn = NULL; -	struct interface *ifp = NULL; -	struct zebra_if *zif = NULL; -	struct zebra_l2info_vxlan zl2_info; -	struct interface *vlan_if = NULL; - -	if (!EVPN_ENABLED(zvrf)) { -		zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u", -			  zvrf_id(zvrf)); -		return; -	} - -	s = msg; -	STREAM_GETC(s, advertise); -	STREAM_GET(&vni, s, 3); - -	zevpn = zevpn_lookup(vni); -	if (!zevpn) -		return; - -	if (zevpn->advertise_subnet == advertise) -		return; - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s", -			   advertise ? "enabled" : "disabled", vni, -			   zevpn->advertise_subnet ? "enabled" : "disabled"); - - -	zevpn->advertise_subnet = advertise; - -	ifp = zevpn->vxlan_if; -	if (!ifp) -		return; - -	zif = ifp->info; - -	/* If down or not mapped to a bridge, we're done. */ -	if (!if_is_operative(ifp) || !zif->brslave_info.br_if) -		return; - -	zl2_info = zif->l2info.vxl; - -	vlan_if = -		zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if); -	if (!vlan_if) -		return; - -	if (zevpn->advertise_subnet) -		zevpn_advertise_subnet(zevpn, vlan_if, 1); -	else -		zevpn_advertise_subnet(zevpn, vlan_if, 0); - -stream_failure: -	return; -} - -/* - * Handle message from client to enable/disable advertisement of g/w macip - * routes - */ -void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS) -{ -	struct stream *s; -	int advertise; -	vni_t vni = 0; -	zebra_evpn_t *zevpn = NULL; -	struct interface *ifp = NULL; - -	if (!EVPN_ENABLED(zvrf)) { -		zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u", -			   zvrf_id(zvrf)); -		return; -	} - -	s = msg; -	STREAM_GETC(s, advertise); -	STREAM_GETL(s, vni); - -	if (!vni) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("EVPN gateway macip Adv %s, currently %s", -				   advertise ? "enabled" : "disabled", -				   advertise_gw_macip_enabled(NULL) -					   ? "enabled" -					   : "disabled"); - -		if (zvrf->advertise_gw_macip == advertise) -			return; - -		zvrf->advertise_gw_macip = advertise; - -		if (advertise_gw_macip_enabled(zevpn)) -			hash_iterate(zvrf->evpn_table, -				     zevpn_gw_macip_add_for_evpn_hash, NULL); -		else -			hash_iterate(zvrf->evpn_table, -				     zevpn_gw_macip_del_for_evpn_hash, NULL); - -	} else { -		struct zebra_if *zif = NULL; -		struct zebra_l2info_vxlan zl2_info; -		struct interface *vlan_if = NULL; -		struct interface *vrr_if = NULL; - -		zevpn = zevpn_lookup(vni); -		if (!zevpn) -			return; - -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug( -				"EVPN gateway macip Adv %s on VNI %d , currently %s", -				advertise ? "enabled" : "disabled", vni, -				advertise_gw_macip_enabled(zevpn) ? "enabled" -								 : "disabled"); - -		if (zevpn->advertise_gw_macip == advertise) -			return; - -		zevpn->advertise_gw_macip = advertise; - -		ifp = zevpn->vxlan_if; -		if (!ifp) -			return; - -		zif = ifp->info; - -		/* If down or not mapped to a bridge, we're done. */ -		if (!if_is_operative(ifp) || !zif->brslave_info.br_if) -			return; - -		zl2_info = zif->l2info.vxl; - -		vlan_if = zvni_map_to_svi(zl2_info.access_vlan, -					  zif->brslave_info.br_if); -		if (!vlan_if) -			return; - -		if (advertise_gw_macip_enabled(zevpn)) { -			/* Add primary SVI MAC-IP */ -			zevpn_add_macip_for_intf(vlan_if, zevpn); - -			/* Add VRR MAC-IP - if any*/ -			vrr_if = zebra_get_vrr_intf_for_svi(vlan_if); -			if (vrr_if) -				zevpn_add_macip_for_intf(vrr_if, zevpn); -		} else { -			/* Del primary MAC-IP */ -			zevpn_del_macip_for_intf(vlan_if, zevpn); - -			/* Del VRR MAC-IP - if any*/ -			vrr_if = zebra_get_vrr_intf_for_svi(vlan_if); -			if (vrr_if) -				zevpn_del_macip_for_intf(vrr_if, zevpn); -		} -	} - -stream_failure: -	return; -} - - -/* - * Handle message from client to learn (or stop learning) about VNIs and MACs. - * When enabled, the VNI hash table will be built and MAC FDB table read; - * when disabled, the entries should be deleted and remote VTEPs and MACs - * uninstalled from the kernel. - * This also informs the setting for BUM handling at the time this change - * occurs; it is relevant only when specifying "learn". - */ -void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS) -{ -	struct stream *s = NULL; -	int advertise = 0; -	enum vxlan_flood_control flood_ctrl; - -	/* Mismatch between EVPN VRF and current VRF (should be prevented by -	 * bgpd's cli) */ -	if (is_evpn_enabled() && !EVPN_ENABLED(zvrf)) -		return; - -	s = msg; -	STREAM_GETC(s, advertise); -	STREAM_GETC(s, flood_ctrl); - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u", -			   zvrf_name(zvrf), zvrf_id(zvrf), -			   advertise ? "enabled" : "disabled", -			   is_evpn_enabled() ? "enabled" : "disabled", -			   flood_ctrl); - -	if (zvrf->advertise_all_vni == advertise) -		return; - -	zvrf->advertise_all_vni = advertise; -	if (EVPN_ENABLED(zvrf)) { -		zrouter.evpn_vrf = zvrf; - -		/* Note BUM handling */ -		zvrf->vxlan_flood_ctrl = flood_ctrl; - -		/* Replay all ESs */ -		zebra_evpn_es_send_all_to_client(true /* add */); - -		/* Build EVPN hash table and inform BGP. */ -		zevpn_build_hash_table(); - -		/* Add all SVI (L3 GW) MACs to BGP*/ -		hash_iterate(zvrf->evpn_table, zevpn_gw_macip_add_for_evpn_hash, -			     NULL); - -		/* Read the MAC FDB */ -		macfdb_read(zvrf->zns); - -		/* Read neighbors */ -		neigh_read(zvrf->zns); -	} else { -		/* Cleanup VTEPs for all EVPNs - uninstall from -		 * kernel and free entries. -		 */ -		hash_iterate(zvrf->evpn_table, zevpn_cleanup_all, zvrf); - -		/* Delete all ESs in BGP */ -		zebra_evpn_es_send_all_to_client(false /* add */); - -		/* cleanup all l3vnis */ -		hash_iterate(zrouter.l3vni_table, zl3vni_cleanup_all, NULL); - -		/* Mark as "no EVPN VRF" */ -		zrouter.evpn_vrf = NULL; -	} - -stream_failure: -	return; -} - -/* - * Allocate EVPN hash table for this VRF and do other initialization. - * NOTE: Currently supported only for default VRF. - */ -void zebra_vxlan_init_tables(struct zebra_vrf *zvrf) -{ -	if (!zvrf) -		return; -	zvrf->evpn_table = hash_create(evpn_hash_keymake, vni_hash_cmp, -				      "Zebra VRF EVPN Table"); -	zvrf->vxlan_sg_table = hash_create(zebra_vxlan_sg_hash_key_make, -			zebra_vxlan_sg_hash_eq, "Zebra VxLAN SG Table"); -} - -/* Cleanup EVPN info, but don't free the table. */ -void zebra_vxlan_cleanup_tables(struct zebra_vrf *zvrf) -{ -	struct zebra_vrf *evpn_zvrf = zebra_vrf_get_evpn(); - -	if (!zvrf) -		return; -	hash_iterate(zvrf->evpn_table, zevpn_cleanup_all, zvrf); -	hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_sg_cleanup, NULL); - -	if (zvrf == evpn_zvrf) -		zebra_evpn_es_cleanup(); -} - -/* Close all EVPN handling */ -void zebra_vxlan_close_tables(struct zebra_vrf *zvrf) -{ -	if (!zvrf) -		return; -	hash_iterate(zvrf->evpn_table, zevpn_cleanup_all, zvrf); -	hash_free(zvrf->evpn_table); -} - -/* init the l3vni table */ -void zebra_vxlan_init(void) -{ -	zrouter.l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp, -					  "Zebra VRF L3 VNI table"); -	zrouter.evpn_vrf = NULL; -	zebra_evpn_mh_init(); -} - -/* free l3vni table */ -void zebra_vxlan_disable(void) -{ -	hash_free(zrouter.l3vni_table); -	zebra_evpn_mh_terminate(); -} - -/* get the l3vni svi ifindex */ -ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id) -{ -	zebra_l3vni_t *zl3vni = NULL; - -	zl3vni = zl3vni_from_vrf(vrf_id); -	if (!zl3vni || !is_l3vni_oper_up(zl3vni)) -		return 0; - -	return zl3vni->svi_if->ifindex; -} - -/************************** vxlan SG cache management ************************/ -/* Inform PIM about the mcast group */ -static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf, -		struct prefix_sg *sg, -		char *sg_str, uint16_t cmd) -{ -	struct zserv *client = NULL; -	struct stream *s = NULL; - -	client = zserv_find_client(ZEBRA_ROUTE_PIM, 0); -	if (!client) -		return 0; - -	if (!CHECK_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG)) -		return 0; - -	s = stream_new(ZEBRA_MAX_PACKET_SIZ); - -	zclient_create_header(s, cmd, VRF_DEFAULT); -	stream_putl(s, IPV4_MAX_BYTELEN); -	stream_put(s, &sg->src.s_addr, IPV4_MAX_BYTELEN); -	stream_put(s, &sg->grp.s_addr, IPV4_MAX_BYTELEN); - -	/* Write packet size. */ -	stream_putw_at(s, 0, stream_get_endp(s)); - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug( -			"Send %s %s to %s", -			(cmd == ZEBRA_VXLAN_SG_ADD) ? "add" : "del", sg_str, -			zebra_route_string(client->proto)); - -	if (cmd == ZEBRA_VXLAN_SG_ADD) -		client->vxlan_sg_add_cnt++; -	else -		client->vxlan_sg_del_cnt++; - -	return zserv_send_message(client, s); -} - -static unsigned int zebra_vxlan_sg_hash_key_make(const void *p) -{ -	const zebra_vxlan_sg_t *vxlan_sg = p; - -	return (jhash_2words(vxlan_sg->sg.src.s_addr, -				vxlan_sg->sg.grp.s_addr, 0)); -} - -static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2) -{ -	const zebra_vxlan_sg_t *sg1 = p1; -	const zebra_vxlan_sg_t *sg2 = p2; - -	return ((sg1->sg.src.s_addr == sg2->sg.src.s_addr) -		&& (sg1->sg.grp.s_addr == sg2->sg.grp.s_addr)); -} - -static zebra_vxlan_sg_t *zebra_vxlan_sg_new(struct zebra_vrf *zvrf, -		struct prefix_sg *sg) -{ -	zebra_vxlan_sg_t *vxlan_sg; - -	vxlan_sg = XCALLOC(MTYPE_ZVXLAN_SG, sizeof(*vxlan_sg)); - -	vxlan_sg->zvrf = zvrf; -	vxlan_sg->sg = *sg; -	prefix_sg2str(sg, vxlan_sg->sg_str); - -	vxlan_sg = hash_get(zvrf->vxlan_sg_table, vxlan_sg, hash_alloc_intern); - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("vxlan SG %s created", vxlan_sg->sg_str); - -	return vxlan_sg; -} - -static zebra_vxlan_sg_t *zebra_vxlan_sg_find(struct zebra_vrf *zvrf, -					    struct prefix_sg *sg) -{ -	zebra_vxlan_sg_t lookup; - -	lookup.sg = *sg; -	return hash_lookup(zvrf->vxlan_sg_table, &lookup); -} - -static zebra_vxlan_sg_t *zebra_vxlan_sg_add(struct zebra_vrf *zvrf, -					   struct prefix_sg *sg) -{ -	zebra_vxlan_sg_t *vxlan_sg; -	zebra_vxlan_sg_t *parent = NULL; -	struct in_addr sip; - -	vxlan_sg = zebra_vxlan_sg_find(zvrf, sg); -	if (vxlan_sg) -		return vxlan_sg; - -	/* create a *G entry for every BUM group implicitly - -	 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute -	 * 2. the XG entry is used by pimd to setup the -	 * vxlan-termination-mroute -	 */ -	if (sg->src.s_addr != INADDR_ANY) { -		memset(&sip, 0, sizeof(sip)); -		parent = zebra_vxlan_sg_do_ref(zvrf, sip, sg->grp); -		if (!parent) -			return NULL; -	} - -	vxlan_sg = zebra_vxlan_sg_new(zvrf, sg); -	if (!vxlan_sg) { -		if (parent) -			zebra_vxlan_sg_do_deref(zvrf, sip, sg->grp); -		return vxlan_sg; -	} - -	zebra_vxlan_sg_send(zvrf, sg, vxlan_sg->sg_str, -			ZEBRA_VXLAN_SG_ADD); - -	return vxlan_sg; -} - -static void zebra_vxlan_sg_del(zebra_vxlan_sg_t *vxlan_sg) -{ -	struct in_addr sip; -	struct zebra_vrf *zvrf; - -	zvrf = vrf_info_lookup(VRF_DEFAULT); -	if (!zvrf) -		return; - -	/* On SG entry deletion remove the reference to its parent XG -	 * entry -	 */ -	if (vxlan_sg->sg.src.s_addr != INADDR_ANY) { -		memset(&sip, 0, sizeof(sip)); -		zebra_vxlan_sg_do_deref(zvrf, sip, vxlan_sg->sg.grp); -	} - -	zebra_vxlan_sg_send(zvrf, &vxlan_sg->sg, -			vxlan_sg->sg_str, ZEBRA_VXLAN_SG_DEL); - -	hash_release(vxlan_sg->zvrf->vxlan_sg_table, vxlan_sg); - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("VXLAN SG %s deleted", vxlan_sg->sg_str); - -	XFREE(MTYPE_ZVXLAN_SG, vxlan_sg); -} - -static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf, -		struct in_addr sip, struct in_addr mcast_grp) -{ -	zebra_vxlan_sg_t *vxlan_sg; -	struct prefix_sg sg; - -	sg.family = AF_INET; -	sg.prefixlen = IPV4_MAX_BYTELEN; -	sg.src = sip; -	sg.grp = mcast_grp; -	vxlan_sg = zebra_vxlan_sg_find(zvrf, &sg); -	if (!vxlan_sg) -		return; - -	if (vxlan_sg->ref_cnt) -		--vxlan_sg->ref_cnt; - -	if (!vxlan_sg->ref_cnt) -		zebra_vxlan_sg_del(vxlan_sg); -} - -static zebra_vxlan_sg_t *zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf, -				struct in_addr sip, struct in_addr mcast_grp) -{ -	zebra_vxlan_sg_t *vxlan_sg; -	struct prefix_sg sg; - -	sg.family = AF_INET; -	sg.prefixlen = IPV4_MAX_BYTELEN; -	sg.src = sip; -	sg.grp = mcast_grp; -	vxlan_sg = zebra_vxlan_sg_add(zvrf, &sg); -	if (vxlan_sg) -		++vxlan_sg->ref_cnt; - -	return vxlan_sg; -} - -static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip, -		struct in_addr mcast_grp) -{ -	struct zebra_vrf *zvrf; - -	if (local_vtep_ip.s_addr == INADDR_ANY -	    || mcast_grp.s_addr == INADDR_ANY) -		return; - -	zvrf = vrf_info_lookup(VRF_DEFAULT); -	if (!zvrf) -		return; - -	zebra_vxlan_sg_do_deref(zvrf, local_vtep_ip, mcast_grp); -} - -static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip, -				struct in_addr mcast_grp) -{ -	struct zebra_vrf *zvrf; - -	if (local_vtep_ip.s_addr == INADDR_ANY -	    || mcast_grp.s_addr == INADDR_ANY) -		return; - -	zvrf = vrf_info_lookup(VRF_DEFAULT); -	if (!zvrf) -		return; -	zebra_vxlan_sg_do_ref(zvrf, local_vtep_ip, mcast_grp); -} - -static void zebra_vxlan_sg_cleanup(struct hash_bucket *backet, void *arg) -{ -	zebra_vxlan_sg_t *vxlan_sg = (zebra_vxlan_sg_t *)backet->data; - -	zebra_vxlan_sg_del(vxlan_sg); -} - -static void zebra_vxlan_sg_replay_send(struct hash_bucket *backet, void *arg) -{ -	zebra_vxlan_sg_t *vxlan_sg = (zebra_vxlan_sg_t *)backet->data; - -	zebra_vxlan_sg_send(vxlan_sg->zvrf, &vxlan_sg->sg, -			vxlan_sg->sg_str, ZEBRA_VXLAN_SG_ADD); -} - -/* Handle message from client to replay vxlan SG entries */ -void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS) -{ -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("VxLAN SG updates to PIM, start"); - -	SET_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG); - -	if (!EVPN_ENABLED(zvrf)) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("VxLAN SG replay request on unexpected vrf %d", -				   zvrf->vrf->vrf_id); -		return; -	} - -	hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_sg_replay_send, NULL); -} -  /************************** EVPN BGP config management ************************/ -static void zevpn_cfg_cleanup(struct hash_bucket *bucket, void *ctxt) +void zebra_evpn_cfg_cleanup(struct hash_bucket *bucket, void *ctxt)  {  	zebra_evpn_t *zevpn = NULL; @@ -7297,83 +1444,5 @@ static void zevpn_cfg_cleanup(struct hash_bucket *bucket, void *ctxt)  				 DEL_REMOTE_NEIGH | DEL_REMOTE_NEIGH_FROM_VTEP);  	zebra_evpn_mac_del_all(zevpn, 1, 0,  			       DEL_REMOTE_MAC | DEL_REMOTE_MAC_FROM_VTEP); -	zevpn_vtep_del_all(zevpn, 1); -} - -/* Cleanup EVPN configuration of a specific VRF */ -static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf *zvrf) -{ -	zebra_l3vni_t *zl3vni = NULL; - -	zvrf->advertise_all_vni = 0; -	zvrf->advertise_gw_macip = 0; -	zvrf->advertise_svi_macip = 0; -	zvrf->vxlan_flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL; - -	hash_iterate(zvrf->evpn_table, zevpn_cfg_cleanup, NULL); - -	if (zvrf->l3vni) -		zl3vni = zl3vni_lookup(zvrf->l3vni); -	if (zl3vni) { -		/* delete and uninstall all rmacs */ -		hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry, -			     zl3vni); -		/* delete and uninstall all next-hops */ -		hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry, -			     zl3vni); -	} -} - -/* Cleanup BGP EVPN configuration upon client disconnect */ -static int zebra_evpn_bgp_cfg_clean_up(struct zserv *client) -{ -	struct vrf *vrf; -	struct zebra_vrf *zvrf; - -	RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { -		zvrf = vrf->info; -		if (zvrf) -			zebra_evpn_vrf_cfg_cleanup(zvrf); -	} - -	return 0; -} - -static int zebra_evpn_pim_cfg_clean_up(struct zserv *client) -{ -	struct zebra_vrf *zvrf = zebra_vrf_get_evpn(); - -	if (zvrf && CHECK_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG)) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("VxLAN SG updates to PIM, stop"); -		UNSET_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG); -	} - -	return 0; -} - -static int zebra_evpn_cfg_clean_up(struct zserv *client) -{ -	if (client->proto == ZEBRA_ROUTE_BGP) -		return zebra_evpn_bgp_cfg_clean_up(client); - -	if (client->proto == ZEBRA_ROUTE_PIM) -		return zebra_evpn_pim_cfg_clean_up(client); - -	return 0; -} - -/* - * Handle results for vxlan dataplane operations. - */ -extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx *ctx) -{ -	/* TODO -- anything other than freeing the context? */ -	dplane_ctx_fini(&ctx); -} - -/* Cleanup BGP EVPN configuration upon client disconnect */ -extern void zebra_evpn_init(void) -{ -	hook_register(zserv_client_close, zebra_evpn_cfg_clean_up); +	zebra_evpn_vtep_del_all(zevpn, 1);  } diff --git a/zebra/zebra_evpn.h b/zebra/zebra_evpn.h index 007d6013f9..3b6a5b21e8 100644 --- a/zebra/zebra_evpn.h +++ b/zebra/zebra_evpn.h @@ -45,6 +45,14 @@ RB_HEAD(zebra_es_evi_rb_head, zebra_evpn_es_evi);  RB_PROTOTYPE(zebra_es_evi_rb_head, zebra_evpn_es_evi, rb_node,  	     zebra_es_evi_rb_cmp); +/* Private Structure to pass callback data for hash iterator */ +struct zebra_evpn_show { +	struct vty *vty; +	json_object *json; +	struct zebra_vrf *zvrf; +	bool use_json; +}; +  /*   * VTEP info   * @@ -139,6 +147,59 @@ static inline struct interface *zevpn_map_to_svi(zebra_evpn_t *zevpn)  int advertise_gw_macip_enabled(zebra_evpn_t *zevpn);  int advertise_svi_macip_enabled(zebra_evpn_t *zevpn); +void zebra_evpn_print(zebra_evpn_t *zevpn, void **ctxt); +void zebra_evpn_print_hash(struct hash_bucket *bucket, void *ctxt[]); +void zebra_evpn_print_hash_detail(struct hash_bucket *bucket, void *data); +int zebra_evpn_add_macip_for_intf(struct interface *ifp, zebra_evpn_t *zevpn); +int zebra_evpn_del_macip_for_intf(struct interface *ifp, zebra_evpn_t *zevpn); +int zebra_evpn_advertise_subnet(zebra_evpn_t *zevpn, struct interface *ifp, +				int advertise); +int zebra_evpn_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn, +			    struct ethaddr *macaddr, struct ipaddr *ip); +int zebra_evpn_gw_macip_del(struct interface *ifp, zebra_evpn_t *zevpn, +			    struct ipaddr *ip); +void zebra_evpn_gw_macip_del_for_evpn_hash(struct hash_bucket *bucket, +					   void *ctxt); +void zebra_evpn_gw_macip_add_for_evpn_hash(struct hash_bucket *bucket, +					   void *ctxt); +void zebra_evpn_svi_macip_del_for_evpn_hash(struct hash_bucket *bucket, +					    void *ctxt); +zebra_evpn_t *zebra_evpn_map_vlan(struct interface *ifp, +				  struct interface *br_if, vlanid_t vid); +zebra_evpn_t *zebra_evpn_from_svi(struct interface *ifp, +				  struct interface *br_if); +struct interface *zebra_evpn_map_to_macvlan(struct interface *br_if, +					    struct interface *svi_if); +void zebra_evpn_install_mac_hash(struct hash_bucket *bucket, void *ctxt); +void zebra_evpn_read_mac_neigh(zebra_evpn_t *zevpn, struct interface *ifp); +unsigned int zebra_evpn_hash_keymake(const void *p); +bool zebra_evpn_hash_cmp(const void *p1, const void *p2); +int zebra_evpn_list_cmp(void *p1, void *p2); +void *zebra_evpn_alloc(void *p); +zebra_evpn_t *zebra_evpn_lookup(vni_t vni); +zebra_evpn_t *zebra_evpn_add(vni_t vni); +int zebra_evpn_del(zebra_evpn_t *zevpn); +int zebra_evpn_send_add_to_client(zebra_evpn_t *zevpn); +int zebra_evpn_send_del_to_client(zebra_evpn_t *zevpn); +zebra_vtep_t *zebra_evpn_vtep_find(zebra_evpn_t *zevpn, +				   struct in_addr *vtep_ip); +zebra_vtep_t *zebra_evpn_vtep_add(zebra_evpn_t *zevpn, struct in_addr *vtep_ip, +				  int flood_control); +int zebra_evpn_vtep_del(zebra_evpn_t *zevpn, zebra_vtep_t *zvtep); +int zebra_evpn_vtep_del_all(zebra_evpn_t *zevpn, int uninstall); +int zebra_evpn_vtep_install(zebra_evpn_t *zevpn, zebra_vtep_t *zvtep); +int zebra_evpn_vtep_uninstall(zebra_evpn_t *zevpn, struct in_addr *vtep_ip); +void zebra_evpn_handle_flooding_remote_vteps(struct hash_bucket *bucket, +					     void *zvrf); +void zebra_evpn_cleanup_all(struct hash_bucket *bucket, void *arg); +void process_remote_macip_add(vni_t vni, struct ethaddr *macaddr, +			      uint16_t ipa_len, struct ipaddr *ipaddr, +			      uint8_t flags, uint32_t seq, +			      struct in_addr vtep_ip, esi_t *esi); +void process_remote_macip_del(vni_t vni, struct ethaddr *macaddr, +			      uint16_t ipa_len, struct ipaddr *ipaddr, +			      struct in_addr vtep_ip); +void zebra_evpn_cfg_cleanup(struct hash_bucket *bucket, void *ctxt);  #ifdef __cplusplus  } diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c index 085dc9c661..a74fdd2243 100644 --- a/zebra/zebra_evpn_mac.c +++ b/zebra/zebra_evpn_mac.c @@ -271,7 +271,7 @@ static int zebra_evpn_dad_mac_auto_recovery_exp(struct thread *t)  	if (!zvrf)  		return 0; -	zevpn = zevpn_lookup(mac->zevpn->vni); +	zevpn = zebra_evpn_lookup(mac->zevpn->vni);  	if (!zevpn)  		return 0; diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c index de6081c3dc..ffd47418aa 100644 --- a/zebra/zebra_evpn_mh.c +++ b/zebra/zebra_evpn_mh.c @@ -349,7 +349,7 @@ void zebra_evpn_es_evi_show_vni(struct vty *vty, bool uj, vni_t vni, int detail)  	json_object *json = NULL;  	zebra_evpn_t *zevpn; -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (zevpn) {  		if (!detail && !json) {  			vty_out(vty, "Type: L local, R remote\n"); @@ -557,7 +557,7 @@ void zebra_evpn_vl_vxl_ref(uint16_t vid, struct zebra_if *vxlan_zif)  		return;  	old_zevpn = acc_bd->zevpn; -	acc_bd->zevpn = zevpn_lookup(vxlan_zif->l2info.vxl.vni); +	acc_bd->zevpn = zebra_evpn_lookup(vxlan_zif->l2info.vxl.vni);  	if (acc_bd->zevpn == old_zevpn)  		return; diff --git a/zebra/zebra_evpn_neigh.c b/zebra/zebra_evpn_neigh.c index 767cbf7aa2..12e9831d2d 100644 --- a/zebra/zebra_evpn_neigh.c +++ b/zebra/zebra_evpn_neigh.c @@ -1180,7 +1180,7 @@ static int zebra_evpn_dad_ip_auto_recovery_exp(struct thread *t)  	if (!zvrf)  		return 0; -	zevpn = zevpn_lookup(nbr->zevpn->vni); +	zevpn = zebra_evpn_lookup(nbr->zevpn->vni);  	if (!zevpn)  		return 0; diff --git a/zebra/zebra_evpn_vxlan.h b/zebra/zebra_evpn_vxlan.h new file mode 100644 index 0000000000..bf8904d492 --- /dev/null +++ b/zebra/zebra_evpn_vxlan.h @@ -0,0 +1,71 @@ +/* + * Zebra EVPN for VxLAN code + * Copyright (C) 2016, 2017 Cumulus Networks, Inc. + * + * This file is part of FRR. + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FRR; see the file COPYING.  If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +/* Get the VRR interface for SVI if any */ +static inline struct interface * +zebra_get_vrr_intf_for_svi(struct interface *ifp) +{ +	struct zebra_vrf *zvrf = NULL; +	struct interface *tmp_if = NULL; +	struct zebra_if *zif = NULL; + +	zvrf = vrf_info_lookup(ifp->vrf_id); +	assert(zvrf); + +	FOR_ALL_INTERFACES (zvrf->vrf, tmp_if) { +		zif = tmp_if->info; +		if (!zif) +			continue; + +		if (!IS_ZEBRA_IF_MACVLAN(tmp_if)) +			continue; + +		if (zif->link == ifp) +			return tmp_if; +	} + +	return NULL; +} + +/* EVPN<=>vxlan_zif association */ +static inline void zevpn_vxlan_if_set(zebra_evpn_t *zevpn, +				      struct interface *ifp, bool set) +{ +	struct zebra_if *zif; + +	if (set) { +		if (zevpn->vxlan_if == ifp) +			return; +		zevpn->vxlan_if = ifp; +	} else { +		if (!zevpn->vxlan_if) +			return; +		zevpn->vxlan_if = NULL; +	} + +	if (ifp) +		zif = ifp->info; +	else +		zif = NULL; + +	zebra_evpn_vxl_evpn_set(zif, zevpn, set); +} diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index b014034d6f..c27be4743e 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -54,13 +54,11 @@  #include "zebra/zebra_evpn_neigh.h"  #include "zebra/zebra_vxlan_private.h"  #include "zebra/zebra_evpn_mh.h" +#include "zebra/zebra_evpn_vxlan.h"  #include "zebra/zebra_router.h" -//comment for cloning  DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix"); -DEFINE_MTYPE_STATIC(ZEBRA, ZEVPN, "EVPN hash");  DEFINE_MTYPE_STATIC(ZEBRA, ZL3VNI, "L3 VNI hash"); -DEFINE_MTYPE_STATIC(ZEBRA, ZEVPN_VTEP, "EVPN remote VTEP/PTUN");  DEFINE_MTYPE_STATIC(ZEBRA, L3VNI_MAC, "EVPN L3VNI MAC");  DEFINE_MTYPE_STATIC(ZEBRA, L3NEIGH, "EVPN Neighbor");  DEFINE_MTYPE_STATIC(ZEBRA, ZVXLAN_SG, "zebra VxLAN multicast group"); @@ -68,20 +66,7 @@ DEFINE_MTYPE_STATIC(ZEBRA, ZVXLAN_SG, "zebra VxLAN multicast group");  DEFINE_HOOK(zebra_rmac_update, (zebra_mac_t *rmac, zebra_l3vni_t *zl3vni,  	    bool delete, const char *reason), (rmac, zl3vni, delete, reason)) -/* definitions */ -/* PMSI strings. */ -#define VXLAN_FLOOD_STR_NO_INFO "-" -#define VXLAN_FLOOD_STR_DEFAULT VXLAN_FLOOD_STR_NO_INFO -static const struct message zvtep_flood_str[] = { -	{VXLAN_FLOOD_DISABLED, VXLAN_FLOOD_STR_NO_INFO}, -	{VXLAN_FLOOD_PIM_SM, "PIM-SM"}, -	{VXLAN_FLOOD_HEAD_END_REPL, "HER"}, -	{0} -}; -  /* static function declarations */ -static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p, -				    uint16_t cmd);  static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket *bucket,  					    void **args);  static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty, @@ -89,13 +74,6 @@ static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty,  static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty,  			      json_object *json);  static void zevpn_print_mac_hash_all_evpn(struct hash_bucket *bucket, void *ctxt); -static void zevpn_print(zebra_evpn_t *zevpn, void **ctxt); -static void zevpn_print_hash(struct hash_bucket *bucket, void *ctxt[]); - -static zebra_evpn_t *zevpn_from_svi(struct interface *ifp, -				  struct interface *br_if); -static struct interface *zevpn_map_to_macvlan(struct interface *br_if, -					     struct interface *svi_if);  /* l3-vni next-hop neigh related APIs */  static zebra_neigh_t *zl3vni_nh_lookup(zebra_l3vni_t *zl3vni, @@ -126,32 +104,7 @@ static int zl3vni_del(zebra_l3vni_t *zl3vni);  static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni);  static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni); -static zebra_evpn_t *zevpn_map_vlan(struct interface *ifp, -				  struct interface *br_if, vlanid_t vid); -static void zevpn_install_mac_hash(struct hash_bucket *bucket, void *ctxt); - -static unsigned int evpn_hash_keymake(const void *p); -static void *zevpn_alloc(void *p); -static zebra_evpn_t *zevpn_add(vni_t vni); -static int zevpn_del(zebra_evpn_t *zevpn); -static int zevpn_send_add_to_client(zebra_evpn_t *zevpn); -static int zevpn_send_del_to_client(zebra_evpn_t *zevpn);  static void zevpn_build_hash_table(void); -static int zevpn_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep); -static zebra_vtep_t *zevpn_vtep_find(zebra_evpn_t *zevpn, struct in_addr *vtep_ip); -static zebra_vtep_t *zevpn_vtep_add(zebra_evpn_t *zevpn, struct in_addr *vtep_ip, -		int flood_control); -static int zevpn_vtep_del(zebra_evpn_t *zevpn, zebra_vtep_t *zvtep); -static int zevpn_vtep_del_all(zebra_evpn_t *zevpn, int uninstall); -static int zevpn_vtep_install(zebra_evpn_t *zevpn, zebra_vtep_t *zvtep); -static int zevpn_vtep_uninstall(zebra_evpn_t *zevpn, struct in_addr *vtep_ip); -static int zevpn_del_macip_for_intf(struct interface *ifp, zebra_evpn_t *zevpn); -static int zevpn_add_macip_for_intf(struct interface *ifp, zebra_evpn_t *zevpn); -static int zevpn_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn, -			     struct ethaddr *macaddr, struct ipaddr *ip); -static int zevpn_gw_macip_del(struct interface *ifp, zebra_evpn_t *zevpn, -			     struct ipaddr *ip); -struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp);  static unsigned int zebra_vxlan_sg_hash_key_make(const void *p);  static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2);  static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf, @@ -210,34 +163,6 @@ static uint32_t rb_host_count(struct host_rb_tree_entry *hrbe)  	return count;  } -int advertise_gw_macip_enabled(zebra_evpn_t *zevpn) -{ -	struct zebra_vrf *zvrf; - -	zvrf = zebra_vrf_get_evpn(); -	if (zvrf && zvrf->advertise_gw_macip) -		return 1; - -	if (zevpn && zevpn->advertise_gw_macip) -		return 1; - -	return 0; -} - -int advertise_svi_macip_enabled(zebra_evpn_t *zevpn) -{ -	struct zebra_vrf *zvrf; - -	zvrf = zebra_vrf_get_evpn(); -	if (zvrf && zvrf->advertise_svi_macip) -		return 1; - -	if (zevpn && zevpn->advertise_svi_macip) -		return 1; - -	return 0; -} -  /*   * Print neighbors for all EVPN.   */ @@ -796,100 +721,6 @@ static void zl3vni_print(zebra_l3vni_t *zl3vni, void **ctx)  	}  } -/* - * Print a specific EVPN entry. - */ -static void zevpn_print(zebra_evpn_t *zevpn, void **ctxt) -{ -	struct vty *vty; -	zebra_vtep_t *zvtep; -	uint32_t num_macs; -	uint32_t num_neigh; -	json_object *json = NULL; -	json_object *json_vtep_list = NULL; -	json_object *json_ip_str = NULL; - -	vty = ctxt[0]; -	json = ctxt[1]; - -	if (json == NULL) { -		vty_out(vty, "VNI: %u\n", zevpn->vni); -		vty_out(vty, " Type: %s\n", "L2"); -		vty_out(vty, " Tenant VRF: %s\n", vrf_id_to_name(zevpn->vrf_id)); -	} else { -		json_object_int_add(json, "vni", zevpn->vni); -		json_object_string_add(json, "type", "L2"); -		json_object_string_add(json, "vrf", -				       vrf_id_to_name(zevpn->vrf_id)); -	} - -	if (!zevpn->vxlan_if) { // unexpected -		if (json == NULL) -			vty_out(vty, " VxLAN interface: unknown\n"); -		return; -	} -	num_macs = num_valid_macs(zevpn); -	num_neigh = hashcount(zevpn->neigh_table); -	if (json == NULL) { -		vty_out(vty, " VxLAN interface: %s\n", zevpn->vxlan_if->name); -		vty_out(vty, " VxLAN ifIndex: %u\n", zevpn->vxlan_if->ifindex); -		vty_out(vty, " Local VTEP IP: %s\n", -			inet_ntoa(zevpn->local_vtep_ip)); -		vty_out(vty, " Mcast group: %s\n", -				inet_ntoa(zevpn->mcast_grp)); -	} else { -		json_object_string_add(json, "vxlanInterface", -				       zevpn->vxlan_if->name); -		json_object_int_add(json, "ifindex", zevpn->vxlan_if->ifindex); -		json_object_string_add(json, "vtepIp", -				       inet_ntoa(zevpn->local_vtep_ip)); -		json_object_string_add(json, "mcastGroup", -				inet_ntoa(zevpn->mcast_grp)); -		json_object_string_add(json, "advertiseGatewayMacip", -				       zevpn->advertise_gw_macip ? "Yes" : "No"); -		json_object_int_add(json, "numMacs", num_macs); -		json_object_int_add(json, "numArpNd", num_neigh); -	} -	if (!zevpn->vteps) { -		if (json == NULL) -			vty_out(vty, " No remote VTEPs known for this VNI\n"); -	} else { -		if (json == NULL) -			vty_out(vty, " Remote VTEPs for this VNI:\n"); -		else -			json_vtep_list = json_object_new_array(); -		for (zvtep = zevpn->vteps; zvtep; zvtep = zvtep->next) { -			const char *flood_str = lookup_msg(zvtep_flood_str, -					zvtep->flood_control, -					VXLAN_FLOOD_STR_DEFAULT); - -			if (json == NULL) { -				vty_out(vty, "  %s flood: %s\n", -						inet_ntoa(zvtep->vtep_ip), -						flood_str); -			} else { -				json_ip_str = json_object_new_string( -						inet_ntoa(zvtep->vtep_ip)); -				json_object_array_add(json_vtep_list, -						json_ip_str); -			} -		} -		if (json) -			json_object_object_add(json, "numRemoteVteps", -					       json_vtep_list); -	} -	if (json == NULL) { -		vty_out(vty, -			" Number of MACs (local and remote) known for this VNI: %u\n", -			num_macs); -		vty_out(vty, -			" Number of ARPs (IPv4 and IPv6, local and remote) known for this VNI: %u\n", -			num_neigh); -		vty_out(vty, " Advertise-gw-macip: %s\n", -			zevpn->advertise_gw_macip ? "Yes" : "No"); -	} -} -  /* print a L3 VNI hash entry */  static void zl3vni_print_hash(struct hash_bucket *bucket, void *ctx[])  { @@ -929,14 +760,6 @@ static void zl3vni_print_hash(struct hash_bucket *bucket, void *ctx[])  	}  } -/* Private Structure to pass callback data for hash iterator */ -struct zevpn_show { -	struct vty *vty; -	json_object *json; -	struct zebra_vrf *zvrf; -	bool use_json; -}; -  /* print a L3 VNI hash entry in detail*/  static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data)  { @@ -944,7 +767,7 @@ static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data)  	zebra_l3vni_t *zl3vni = NULL;  	json_object *json_array = NULL;  	bool use_json = false; -	struct zevpn_show *zes = data; +	struct zebra_evpn_show *zes = data;  	vty = zes->vty;  	json_array = zes->json; @@ -959,554 +782,6 @@ static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data)  		vty_out(vty, "\n");  } - -/* - * Print an EVPN hash entry - called for display of all VNIs. - */ -static void zevpn_print_hash(struct hash_bucket *bucket, void *ctxt[]) -{ -	struct vty *vty; -	zebra_evpn_t *zevpn; -	zebra_vtep_t *zvtep; -	uint32_t num_vteps = 0; -	uint32_t num_macs = 0; -	uint32_t num_neigh = 0; -	json_object *json = NULL; -	json_object *json_evpn = NULL; -	json_object *json_ip_str = NULL; -	json_object *json_vtep_list = NULL; - -	vty = ctxt[0]; -	json = ctxt[1]; - -	zevpn = (zebra_evpn_t *)bucket->data; - -	zvtep = zevpn->vteps; -	while (zvtep) { -		num_vteps++; -		zvtep = zvtep->next; -	} - -	num_macs = num_valid_macs(zevpn); -	num_neigh = hashcount(zevpn->neigh_table); -	if (json == NULL) -		vty_out(vty, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n", -			zevpn->vni, "L2", -			zevpn->vxlan_if ? zevpn->vxlan_if->name : "unknown", -			num_macs, num_neigh, num_vteps, -			vrf_id_to_name(zevpn->vrf_id)); -	else { -		char vni_str[VNI_STR_LEN]; -		snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni); -		json_evpn = json_object_new_object(); -		json_object_int_add(json_evpn, "vni", zevpn->vni); -		json_object_string_add(json_evpn, "type", "L2"); -		json_object_string_add(json_evpn, "vxlanIf", -				       zevpn->vxlan_if ? zevpn->vxlan_if->name -						      : "unknown"); -		json_object_int_add(json_evpn, "numMacs", num_macs); -		json_object_int_add(json_evpn, "numArpNd", num_neigh); -		json_object_int_add(json_evpn, "numRemoteVteps", num_vteps); -		json_object_string_add(json_evpn, "tenantVrf", -				       vrf_id_to_name(zevpn->vrf_id)); -		if (num_vteps) { -			json_vtep_list = json_object_new_array(); -			for (zvtep = zevpn->vteps; zvtep; zvtep = zvtep->next) { -				json_ip_str = json_object_new_string( -					inet_ntoa(zvtep->vtep_ip)); -				json_object_array_add(json_vtep_list, -						      json_ip_str); -			} -			json_object_object_add(json_evpn, "remoteVteps", -					       json_vtep_list); -		} -		json_object_object_add(json, vni_str, json_evpn); -	} -} - -/* - * Print an EVPN hash entry in detail - called for display of all EVPNs. - */ -static void zevpn_print_hash_detail(struct hash_bucket *bucket, void *data) -{ -	struct vty *vty; -	zebra_evpn_t *zevpn; -	json_object *json_array = NULL; -	bool use_json = false; -	struct zevpn_show *zes = data; - -	vty = zes->vty; -	json_array = zes->json; -	use_json = zes->use_json; - -	zevpn = (zebra_evpn_t *)bucket->data; - -	zebra_vxlan_print_vni(vty, zes->zvrf, zevpn->vni, use_json, json_array); - -	if (!use_json) -		vty_out(vty, "\n"); -} - -/* Get the VRR interface for SVI if any */ -struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp) -{ -	struct zebra_vrf *zvrf = NULL; -	struct interface *tmp_if = NULL; -	struct zebra_if *zif = NULL; - -	zvrf = vrf_info_lookup(ifp->vrf_id); -	assert(zvrf); - -	FOR_ALL_INTERFACES (zvrf->vrf, tmp_if) { -		zif = tmp_if->info; -		if (!zif) -			continue; - -		if (!IS_ZEBRA_IF_MACVLAN(tmp_if)) -			continue; - -		if (zif->link == ifp) -			return tmp_if; -	} - -	return NULL; -} - -static int zevpn_del_macip_for_intf(struct interface *ifp, zebra_evpn_t *zevpn) -{ -	struct listnode *cnode = NULL, *cnnode = NULL; -	struct connected *c = NULL; -	struct ethaddr macaddr; - -	memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN); - -	for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) { -		struct ipaddr ip; - -		memset(&ip, 0, sizeof(struct ipaddr)); -		if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL)) -			continue; - -		if (c->address->family == AF_INET) { -			ip.ipa_type = IPADDR_V4; -			memcpy(&(ip.ipaddr_v4), &(c->address->u.prefix4), -			       sizeof(struct in_addr)); -		} else if (c->address->family == AF_INET6) { -			ip.ipa_type = IPADDR_V6; -			memcpy(&(ip.ipaddr_v6), &(c->address->u.prefix6), -			       sizeof(struct in6_addr)); -		} else { -			continue; -		} - -		zevpn_gw_macip_del(ifp, zevpn, &ip); -	} - -	return 0; -} - -static int zevpn_add_macip_for_intf(struct interface *ifp, zebra_evpn_t *zevpn) -{ -	struct listnode *cnode = NULL, *cnnode = NULL; -	struct connected *c = NULL; -	struct ethaddr macaddr; - -	memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN); - -	for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) { -		struct ipaddr ip; - -		memset(&ip, 0, sizeof(struct ipaddr)); -		if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL)) -			continue; - -		if (c->address->family == AF_INET) { -			ip.ipa_type = IPADDR_V4; -			memcpy(&(ip.ipaddr_v4), &(c->address->u.prefix4), -			       sizeof(struct in_addr)); -		} else if (c->address->family == AF_INET6) { -			ip.ipa_type = IPADDR_V6; -			memcpy(&(ip.ipaddr_v6), &(c->address->u.prefix6), -			       sizeof(struct in6_addr)); -		} else { -			continue; -		} - -		zevpn_gw_macip_add(ifp, zevpn, &macaddr, &ip); -	} -	return 0; -} - - -static int zevpn_advertise_subnet(zebra_evpn_t *zevpn, struct interface *ifp, -				 int advertise) -{ -	struct listnode *cnode = NULL, *cnnode = NULL; -	struct connected *c = NULL; -	struct ethaddr macaddr; - -	memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN); - -	for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) { -		struct prefix p; - -		memcpy(&p, c->address, sizeof(struct prefix)); - -		/* skip link local address */ -		if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) -			continue; - -		apply_mask(&p); -		if (advertise) -			ip_prefix_send_to_client(ifp->vrf_id, &p, -						 ZEBRA_IP_PREFIX_ROUTE_ADD); -		else -			ip_prefix_send_to_client(ifp->vrf_id, &p, -						 ZEBRA_IP_PREFIX_ROUTE_DEL); -	} -	return 0; -} - -/* - * zevpn_gw_macip_add_to_client - */ -static int zevpn_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn, -			     struct ethaddr *macaddr, struct ipaddr *ip) -{ -	zebra_mac_t *mac = NULL; -	struct zebra_if *zif = NULL; -	struct zebra_l2info_vxlan *vxl = NULL; - -	zif = zevpn->vxlan_if->info; -	if (!zif) -		return -1; - -	vxl = &zif->l2info.vxl; - -	if (zebra_evpn_mac_gw_macip_add(ifp, zevpn, ip, &mac, macaddr, -					vxl->access_vlan) -	    != 0) -		return -1; - -	return zebra_evpn_neigh_gw_macip_add(ifp, zevpn, ip, mac); -} - -/* - * zevpn_gw_macip_del_from_client - */ -static int zevpn_gw_macip_del(struct interface *ifp, zebra_evpn_t *zevpn, -			     struct ipaddr *ip) -{ -	char buf1[ETHER_ADDR_STRLEN]; -	char buf2[INET6_ADDRSTRLEN]; -	zebra_neigh_t *n = NULL; -	zebra_mac_t *mac = NULL; - -	/* If the neigh entry is not present nothing to do*/ -	n = zebra_evpn_neigh_lookup(zevpn, ip); -	if (!n) -		return 0; - -	/* mac entry should be present */ -	mac = zebra_evpn_mac_lookup(zevpn, &n->emac); -	if (!mac) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u", -				   prefix_mac2str(&n->emac, -						  buf1, sizeof(buf1)), -				   ipaddr2str(ip, buf2, sizeof(buf2)), -				   zevpn->vni); -		return -1; -	} - -	/* If the entry is not local nothing to do*/ -	if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) -		return -1; - -	/* only need to delete the entry from bgp if we sent it before */ -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug( -			"%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP", -			ifp->vrf_id, ifp->name, ifp->ifindex, zevpn->vni, -			prefix_mac2str(&(n->emac), buf1, sizeof(buf1)), -			ipaddr2str(ip, buf2, sizeof(buf2))); - -	/* Remove neighbor from BGP. */ -	zebra_evpn_neigh_send_del_to_client(zevpn->vni, &n->ip, &n->emac, -					    n->flags, ZEBRA_NEIGH_ACTIVE, -					    false /*force*/); - -	/* Delete this neighbor entry. */ -	zebra_evpn_neigh_del(zevpn, n); - -	/* see if the mac needs to be deleted as well*/ -	if (mac) -		zebra_evpn_deref_ip2mac(zevpn, mac); - -	return 0; -} - -static void zevpn_gw_macip_del_for_evpn_hash(struct hash_bucket *bucket, -					   void *ctxt) -{ -	zebra_evpn_t *zevpn = NULL; -	struct zebra_if *zif = NULL; -	struct zebra_l2info_vxlan zl2_info; -	struct interface *vlan_if = NULL; -	struct interface *vrr_if = NULL; -	struct interface *ifp; - -	/* Add primary SVI MAC*/ -	zevpn = (zebra_evpn_t *)bucket->data; - -	/* Global (Zvrf) advertise-default-gw is disabled, -	 * but zevpn advertise-default-gw is enabled -	 */ -	if (zevpn->advertise_gw_macip) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip", -				   zevpn->vni); -		return; -	} - -	ifp = zevpn->vxlan_if; -	if (!ifp) -		return; -	zif = ifp->info; - -	/* If down or not mapped to a bridge, we're done. */ -	if (!if_is_operative(ifp) || !zif->brslave_info.br_if) -		return; - -	zl2_info = zif->l2info.vxl; - -	vlan_if = -		zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if); -	if (!vlan_if) -		return; - -	/* Del primary MAC-IP */ -	zevpn_del_macip_for_intf(vlan_if, zevpn); - -	/* Del VRR MAC-IP - if any*/ -	vrr_if = zebra_get_vrr_intf_for_svi(vlan_if); -	if (vrr_if) -		zevpn_del_macip_for_intf(vrr_if, zevpn); - -	return; -} - -static void zevpn_gw_macip_add_for_evpn_hash(struct hash_bucket *bucket, -					   void *ctxt) -{ -	zebra_evpn_t *zevpn = NULL; -	struct zebra_if *zif = NULL; -	struct zebra_l2info_vxlan zl2_info; -	struct interface *vlan_if = NULL; -	struct interface *vrr_if = NULL; -	struct interface *ifp = NULL; - -	zevpn = (zebra_evpn_t *)bucket->data; - -	ifp = zevpn->vxlan_if; -	if (!ifp) -		return; -	zif = ifp->info; - -	/* If down or not mapped to a bridge, we're done. */ -	if (!if_is_operative(ifp) || !zif->brslave_info.br_if) -		return; -	zl2_info = zif->l2info.vxl; - -	vlan_if = -		zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if); -	if (!vlan_if) -		return; - -	/* Add primary SVI MAC-IP */ -	zevpn_add_macip_for_intf(vlan_if, zevpn); - -	if (advertise_gw_macip_enabled(zevpn)) { -		/* Add VRR MAC-IP - if any*/ -		vrr_if = zebra_get_vrr_intf_for_svi(vlan_if); -		if (vrr_if) -			zevpn_add_macip_for_intf(vrr_if, zevpn); -	} - -	return; -} - -static void zevpn_svi_macip_del_for_evpn_hash(struct hash_bucket *bucket, -					   void *ctxt) -{ -	zebra_evpn_t *zevpn = NULL; -	struct zebra_if *zif = NULL; -	struct zebra_l2info_vxlan zl2_info; -	struct interface *vlan_if = NULL; -	struct interface *ifp; - -	/* Add primary SVI MAC*/ -	zevpn = (zebra_evpn_t *)bucket->data; -	if (!zevpn) -		return; - -	/* Global(vrf) advertise-svi-ip disabled, but zevpn advertise-svi-ip -	 * enabled -	 */ -	if (zevpn->advertise_svi_macip) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("VNI: %u SVI-MACIP enabled, retain svi-macip", -				   zevpn->vni); -		return; -	} - -	ifp = zevpn->vxlan_if; -	if (!ifp) -		return; -	zif = ifp->info; - -	/* If down or not mapped to a bridge, we're done. */ -	if (!if_is_operative(ifp) || !zif->brslave_info.br_if) -		return; - -	zl2_info = zif->l2info.vxl; - -	vlan_if = -		zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if); -	if (!vlan_if) -		return; - -	/* Del primary MAC-IP */ -	zevpn_del_macip_for_intf(vlan_if, zevpn); - -	return; -} - -/* - * Map port or (port, VLAN) to an EVPN. This is invoked upon getting MAC - * notifications, to see if they are of interest. - */ -static zebra_evpn_t *zevpn_map_vlan(struct interface *ifp, -				  struct interface *br_if, vlanid_t vid) -{ -	struct zebra_ns *zns; -	struct route_node *rn; -	struct interface *tmp_if = NULL; -	struct zebra_if *zif; -	struct zebra_l2info_bridge *br; -	struct zebra_l2info_vxlan *vxl = NULL; -	uint8_t bridge_vlan_aware; -	zebra_evpn_t *zevpn; -	int found = 0; - -	/* Determine if bridge is VLAN-aware or not */ -	zif = br_if->info; -	assert(zif); -	br = &zif->l2info.br; -	bridge_vlan_aware = br->vlan_aware; - -	/* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ -	/* TODO: Optimize with a hash. */ -	zns = zebra_ns_lookup(NS_DEFAULT); -	for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { -		tmp_if = (struct interface *)rn->info; -		if (!tmp_if) -			continue; -		zif = tmp_if->info; -		if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) -			continue; -		if (!if_is_operative(tmp_if)) -			continue; -		vxl = &zif->l2info.vxl; - -		if (zif->brslave_info.br_if != br_if) -			continue; - -		if (!bridge_vlan_aware || vxl->access_vlan == vid) { -			found = 1; -			break; -		} -	} - -	if (!found) -		return NULL; - -	zevpn = zevpn_lookup(vxl->vni); -	return zevpn; -} - -/* - * Map SVI and associated bridge to a VNI. This is invoked upon getting - * neighbor notifications, to see if they are of interest. - */ -static zebra_evpn_t *zevpn_from_svi(struct interface *ifp, -				  struct interface *br_if) -{ -	struct zebra_ns *zns; -	struct route_node *rn; -	struct interface *tmp_if = NULL; -	struct zebra_if *zif; -	struct zebra_l2info_bridge *br; -	struct zebra_l2info_vxlan *vxl = NULL; -	uint8_t bridge_vlan_aware; -	vlanid_t vid = 0; -	zebra_evpn_t *zevpn; -	int found = 0; - -	if (!br_if) -		return NULL; - -	/* Make sure the linked interface is a bridge. */ -	if (!IS_ZEBRA_IF_BRIDGE(br_if)) -		return NULL; - -	/* Determine if bridge is VLAN-aware or not */ -	zif = br_if->info; -	assert(zif); -	br = &zif->l2info.br; -	bridge_vlan_aware = br->vlan_aware; -	if (bridge_vlan_aware) { -		struct zebra_l2info_vlan *vl; - -		if (!IS_ZEBRA_IF_VLAN(ifp)) -			return NULL; - -		zif = ifp->info; -		assert(zif); -		vl = &zif->l2info.vl; -		vid = vl->vid; -	} - -	/* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ -	/* TODO: Optimize with a hash. */ -	zns = zebra_ns_lookup(NS_DEFAULT); -	for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { -		tmp_if = (struct interface *)rn->info; -		if (!tmp_if) -			continue; -		zif = tmp_if->info; -		if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) -			continue; -		if (!if_is_operative(tmp_if)) -			continue; -		vxl = &zif->l2info.vxl; - -		if (zif->brslave_info.br_if != br_if) -			continue; - -		if (!bridge_vlan_aware || vxl->access_vlan == vid) { -			found = 1; -			break; -		} -	} - -	if (!found) -		return NULL; - -	zevpn = zevpn_lookup(vxl->vni); -	return zevpn; -} -  /* Map to SVI on bridge corresponding to specified VLAN. This can be one   * of two cases:   * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface @@ -1562,328 +837,15 @@ struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)  	return found ? tmp_if : NULL;  } -/* Map to MAC-VLAN interface corresponding to specified SVI interface. - */ -static struct interface *zevpn_map_to_macvlan(struct interface *br_if, -					     struct interface *svi_if) -{ -	struct zebra_ns *zns; -	struct route_node *rn; -	struct interface *tmp_if = NULL; -	struct zebra_if *zif; -	int found = 0; - -	/* Defensive check, caller expected to invoke only with valid bridge. */ -	if (!br_if) -		return NULL; - -	if (!svi_if) { -		zlog_debug("svi_if is not passed."); -		return NULL; -	} - -	/* Determine if bridge is VLAN-aware or not */ -	zif = br_if->info; -	assert(zif); - -	/* Identify corresponding VLAN interface. */ -	zns = zebra_ns_lookup(NS_DEFAULT); -	for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { -		tmp_if = (struct interface *)rn->info; -		/* Check oper status of the SVI. */ -		if (!tmp_if || !if_is_operative(tmp_if)) -			continue; -		zif = tmp_if->info; - -		if (!zif || zif->zif_type != ZEBRA_IF_MACVLAN) -			continue; - -		if (zif->link == svi_if) { -			found = 1; -			break; -		} -	} - -	return found ? tmp_if : NULL; -} - -/* - * Install MAC hash entry - called upon access VLAN change. - */ -static void zevpn_install_mac_hash(struct hash_bucket *bucket, void *ctxt) -{ -	zebra_mac_t *mac; -	struct mac_walk_ctx *wctx = ctxt; - -	mac = (zebra_mac_t *)bucket->data; - -	if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) -		zebra_evpn_rem_mac_install(wctx->zevpn, mac, false); -} - -/* - * Read and populate local MACs and neighbors corresponding to this EVPN. - */ -static void zevpn_read_mac_neigh(zebra_evpn_t *zevpn, struct interface *ifp) -{ -	struct zebra_ns *zns; -	struct zebra_if *zif; -	struct interface *vlan_if; -	struct zebra_l2info_vxlan *vxl; -	struct interface *vrr_if; - -	zif = ifp->info; -	vxl = &zif->l2info.vxl; -	zns = zebra_ns_lookup(NS_DEFAULT); - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug( -			"Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u", -			ifp->name, ifp->ifindex, zevpn->vni, -			zif->brslave_info.bridge_ifindex); - -	macfdb_read_for_bridge(zns, ifp, zif->brslave_info.br_if); -	vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if); -	if (vlan_if) { - -		/* Add SVI MAC-IP */ -		zevpn_add_macip_for_intf(vlan_if, zevpn); - -		/* Add VRR MAC-IP - if any*/ -		vrr_if = zebra_get_vrr_intf_for_svi(vlan_if); -		if (vrr_if) -			zevpn_add_macip_for_intf(vrr_if, zevpn); - -		neigh_read_for_vlan(zns, vlan_if); -	} -} - -/* - * Hash function for VNI. - */ -static unsigned int evpn_hash_keymake(const void *p) -{ -	const zebra_evpn_t *zevpn = p; - -	return (jhash_1word(zevpn->vni, 0)); -} - -/* - * Compare 2 VNI hash entries. - */ -static bool vni_hash_cmp(const void *p1, const void *p2) -{ -	const zebra_evpn_t *zevpn1 = p1; -	const zebra_evpn_t *zevpn2 = p2; - -	return (zevpn1->vni == zevpn2->vni); -} - -int vni_list_cmp(void *p1, void *p2) -{ -	const zebra_evpn_t *zevpn1 = p1; -	const zebra_evpn_t *zevpn2 = p2; - -	if (zevpn1->vni == zevpn2->vni) -		return 0; -	return (zevpn1->vni < zevpn2->vni) ? -1 : 1; -} - -/* - * Callback to allocate VNI hash entry. - */ -static void *zevpn_alloc(void *p) -{ -	const zebra_evpn_t *tmp_vni = p; -	zebra_evpn_t *zevpn; - -	zevpn = XCALLOC(MTYPE_ZEVPN, sizeof(zebra_evpn_t)); -	zevpn->vni = tmp_vni->vni; -	return ((void *)zevpn); -} - -/* - * Look up EVPN hash entry. - */ -zebra_evpn_t *zevpn_lookup(vni_t vni) -{ -	struct zebra_vrf *zvrf; -	zebra_evpn_t tmp_vni; -	zebra_evpn_t *zevpn = NULL; - -	zvrf = zebra_vrf_get_evpn(); -	assert(zvrf); -	memset(&tmp_vni, 0, sizeof(zebra_evpn_t)); -	tmp_vni.vni = vni; -	zevpn = hash_lookup(zvrf->evpn_table, &tmp_vni); - -	return zevpn; -} - -/* - * Add EVPN hash entry. - */ -static zebra_evpn_t *zevpn_add(vni_t vni) -{ -	struct zebra_vrf *zvrf; -	zebra_evpn_t tmp_zevpn; -	zebra_evpn_t *zevpn = NULL; - -	zvrf = zebra_vrf_get_evpn(); -	assert(zvrf); -	memset(&tmp_zevpn, 0, sizeof(zebra_evpn_t)); -	tmp_zevpn.vni = vni; -	zevpn = hash_get(zvrf->evpn_table, &tmp_zevpn, zevpn_alloc); -	assert(zevpn); - -	zebra_evpn_evpn_es_init(zevpn); - -	/* Create hash table for MAC */ -	zevpn->mac_table = zebra_mac_db_create("Zebra EVPN MAC Table"); - -	/* Create hash table for neighbors */ -	zevpn->neigh_table = zebra_neigh_db_create("Zebra EVPN Neighbor Table"); - -	return zevpn; -} - -/* EVPN<=>vxlan_zif association */ -static void zevpn_vxlan_if_set(zebra_evpn_t *zevpn, struct interface *ifp, -		bool set) -{ -	struct zebra_if *zif; - -	if (set) { -		if (zevpn->vxlan_if == ifp) -			return; -		zevpn->vxlan_if = ifp; -	} else { -		if (!zevpn->vxlan_if) -			return; -		zevpn->vxlan_if = NULL; -	} - -	if (ifp) -		zif = ifp->info; -	else -		zif = NULL; - -	zebra_evpn_vxl_evpn_set(zif, zevpn, set); -} - -/* - * Delete EVPN hash entry. - */ -static int zevpn_del(zebra_evpn_t *zevpn) +static int zebra_evpn_vxlan_del(zebra_evpn_t *zevpn)  { -	struct zebra_vrf *zvrf; -	zebra_evpn_t *tmp_zevpn; - -	zvrf = zebra_vrf_get_evpn(); -	assert(zvrf); -  	zevpn_vxlan_if_set(zevpn, zevpn->vxlan_if, false /* set */);  	/* Remove references to the BUM mcast grp */  	zebra_vxlan_sg_deref(zevpn->local_vtep_ip, zevpn->mcast_grp); -	/* Free the neighbor hash table. */ -	hash_free(zevpn->neigh_table); -	zevpn->neigh_table = NULL; - -	/* Free the MAC hash table. */ -	hash_free(zevpn->mac_table); -	zevpn->mac_table = NULL; - -	zebra_evpn_evpn_es_cleanup(zevpn); - -	/* Free the EVPN hash entry and allocated memory. */ -	tmp_zevpn = hash_release(zvrf->evpn_table, zevpn); -	XFREE(MTYPE_ZEVPN, tmp_zevpn); - -	return 0; -} - -/* - * Inform BGP about local EVPN addition. - */ -static int zevpn_send_add_to_client(zebra_evpn_t *zevpn) -{ -	struct zserv *client; -	struct stream *s; -	int rc; - -	client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); -	/* BGP may not be running. */ -	if (!client) -		return 0; - -	s = stream_new(ZEBRA_MAX_PACKET_SIZ); - -	zclient_create_header(s, ZEBRA_VNI_ADD, zebra_vrf_get_evpn_id()); -	stream_putl(s, zevpn->vni); -	stream_put_in_addr(s, &zevpn->local_vtep_ip); -	stream_put(s, &zevpn->vrf_id, sizeof(vrf_id_t)); /* tenant vrf */ -	stream_put_in_addr(s, &zevpn->mcast_grp); - -	/* Write packet size. */ -	stream_putw_at(s, 0, stream_get_endp(s)); - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("Send EVPN_ADD %u %s tenant vrf %s to %s", zevpn->vni, -			   inet_ntoa(zevpn->local_vtep_ip), -			   vrf_id_to_name(zevpn->vrf_id), -			   zebra_route_string(client->proto)); - -	client->vniadd_cnt++; -	rc = zserv_send_message(client, s); - -	if (!(zevpn->flags & ZEVPN_READY_FOR_BGP)) { -		zevpn->flags |= ZEVPN_READY_FOR_BGP; -		/* once the EVPN is sent the ES-EVIs can also be replayed -		 * to BGP -		 */ -		zebra_evpn_update_all_es(zevpn); -	} -	return rc; -} - -/* - * Inform BGP about local EVPN deletion. - */ -static int zevpn_send_del_to_client(zebra_evpn_t *zevpn) -{ -	struct zserv *client; -	struct stream *s; - -	client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); -	/* BGP may not be running. */ -	if (!client) -		return 0; - -	if (zevpn->flags & ZEVPN_READY_FOR_BGP) { -		zevpn->flags &= ~ZEVPN_READY_FOR_BGP; -		/* the ES-EVIs must be removed from BGP before the EVPN is */ -		zebra_evpn_update_all_es(zevpn); -	} - -	s = stream_new(ZEBRA_MAX_PACKET_SIZ); -	stream_reset(s); - -	zclient_create_header(s, ZEBRA_VNI_DEL, zebra_vrf_get_evpn_id()); -	stream_putl(s, zevpn->vni); - -	/* Write packet size. */ -	stream_putw_at(s, 0, stream_get_endp(s)); - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("Send EVPN_DEL %u to %s", zevpn->vni, -			   zebra_route_string(client->proto)); - -	client->vnidel_cnt++; -	return zserv_send_message(client, s); +	return zebra_evpn_del(zevpn);  } -  /*   * Build the VNI hash table by going over the VxLAN interfaces. This   * is called when EVPN (advertise-all-vni) is enabled. @@ -1956,7 +918,7 @@ static void zevpn_build_hash_table(void)  					inet_ntoa(vxl->vtep_ip));  			/* EVPN hash entry is expected to exist, if the BGP process is killed */ -			zevpn = zevpn_lookup(vni); +			zevpn = zebra_evpn_lookup(vni);  			if (zevpn) {  				zlog_debug(  					"EVPN hash already present for IF %s(%u) L2-VNI %u", @@ -1968,7 +930,7 @@ static void zevpn_build_hash_table(void)  				 */  				if (if_is_operative(ifp) &&  					zif->brslave_info.br_if) -					zevpn_send_add_to_client(zevpn); +					zebra_evpn_send_add_to_client(zevpn);  				/* Send Local MAC-entries to client */  				zebra_evpn_send_mac_list_to_client(zevpn); @@ -1976,7 +938,7 @@ static void zevpn_build_hash_table(void)  				/* Send Loval Neighbor entries to client */  				zebra_evpn_send_neigh_to_client(zevpn);  			} else { -				zevpn = zevpn_add(vni); +				zevpn = zebra_evpn_add(vni);  				if (!zevpn) {  					zlog_debug(  						"Failed to add EVPN hash, IF %s(%u) L2-VNI %u", @@ -2019,160 +981,16 @@ static void zevpn_build_hash_table(void)  				 */  				if (if_is_operative(ifp) &&  					zif->brslave_info.br_if) -					zevpn_send_add_to_client(zevpn); +					zebra_evpn_send_add_to_client(zevpn);  			}  		}  	}  }  /* - * See if remote VTEP matches with prefix. - */ -static int zevpn_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep) -{ -	return (IPV4_ADDR_SAME(vtep_ip, &zvtep->vtep_ip)); -} - -/* - * Locate remote VTEP in EVPN hash table. - */ -static zebra_vtep_t *zevpn_vtep_find(zebra_evpn_t *zevpn, struct in_addr *vtep_ip) -{ -	zebra_vtep_t *zvtep; - -	if (!zevpn) -		return NULL; - -	for (zvtep = zevpn->vteps; zvtep; zvtep = zvtep->next) { -		if (zevpn_vtep_match(vtep_ip, zvtep)) -			break; -	} - -	return zvtep; -} - -/* - * Add remote VTEP to EVPN hash table. - */ -static zebra_vtep_t *zevpn_vtep_add(zebra_evpn_t *zevpn, struct in_addr *vtep_ip, -		int flood_control) - -{ -	zebra_vtep_t *zvtep; - -	zvtep = XCALLOC(MTYPE_ZEVPN_VTEP, sizeof(zebra_vtep_t)); - -	zvtep->vtep_ip = *vtep_ip; -	zvtep->flood_control = flood_control; - -	if (zevpn->vteps) -		zevpn->vteps->prev = zvtep; -	zvtep->next = zevpn->vteps; -	zevpn->vteps = zvtep; - -	return zvtep; -} - -/* - * Remove remote VTEP from EVPN hash table. - */ -static int zevpn_vtep_del(zebra_evpn_t *zevpn, zebra_vtep_t *zvtep) -{ -	if (zvtep->next) -		zvtep->next->prev = zvtep->prev; -	if (zvtep->prev) -		zvtep->prev->next = zvtep->next; -	else -		zevpn->vteps = zvtep->next; - -	zvtep->prev = zvtep->next = NULL; -	XFREE(MTYPE_ZEVPN_VTEP, zvtep); - -	return 0; -} - -/* - * Delete all remote VTEPs for this EVPN (upon VNI delete). Also - * uninstall from kernel if asked to. - */ -static int zevpn_vtep_del_all(zebra_evpn_t *zevpn, int uninstall) -{ -	zebra_vtep_t *zvtep, *zvtep_next; - -	if (!zevpn) -		return -1; - -	for (zvtep = zevpn->vteps; zvtep; zvtep = zvtep_next) { -		zvtep_next = zvtep->next; -		if (uninstall) -			zevpn_vtep_uninstall(zevpn, &zvtep->vtep_ip); -		zevpn_vtep_del(zevpn, zvtep); -	} - -	return 0; -} - -/* - * Install remote VTEP into the kernel if the remote VTEP has asked - * for head-end-replication. - */ -static int zevpn_vtep_install(zebra_evpn_t *zevpn, zebra_vtep_t *zvtep) -{ -	if (is_vxlan_flooding_head_end() && -	    (zvtep->flood_control == VXLAN_FLOOD_HEAD_END_REPL)) { -		if (ZEBRA_DPLANE_REQUEST_FAILURE == -		    dplane_vtep_add(zevpn->vxlan_if, -				    &zvtep->vtep_ip, zevpn->vni)) -			return -1; -	} - -	return 0; -} - -/* - * Uninstall remote VTEP from the kernel. - */ -static int zevpn_vtep_uninstall(zebra_evpn_t *zevpn, struct in_addr *vtep_ip) -{ -	if (!zevpn->vxlan_if) { -		zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf", -			   zevpn->vni, zevpn); -		return -1; -	} - -	if (ZEBRA_DPLANE_REQUEST_FAILURE == -	    dplane_vtep_delete(zevpn->vxlan_if, vtep_ip, zevpn->vni)) -		return -1; - -	return 0; -} - -/* - * Install or uninstall flood entries in the kernel corresponding to - * remote VTEPs. This is invoked upon change to BUM handling. - */ -static void zevpn_handle_flooding_remote_vteps(struct hash_bucket *bucket, -					      void *zvrf) -{ -	zebra_evpn_t *zevpn; -	zebra_vtep_t *zvtep; - -	zevpn = (zebra_evpn_t *)bucket->data; -	if (!zevpn) -		return; - -	for (zvtep = zevpn->vteps; zvtep; zvtep = zvtep->next) { -		if (is_vxlan_flooding_head_end()) -			zevpn_vtep_install(zevpn, zvtep); -		else -			zevpn_vtep_uninstall(zevpn, &zvtep->vtep_ip); -	} -} - -/*   * Cleanup EVPN/VTEP and update kernel   */ -static void zevpn_cleanup_all(struct hash_bucket *bucket, void *arg) +static void zebra_evpn_vxlan_cleanup_all(struct hash_bucket *bucket, void *arg)  {  	zebra_evpn_t *zevpn = NULL;  	zebra_l3vni_t *zl3vni = NULL; @@ -2186,15 +1004,7 @@ static void zevpn_cleanup_all(struct hash_bucket *bucket, void *arg)  	if (zl3vni)  		listnode_delete(zl3vni->l2vnis, zevpn); -	/* Free up all neighbors and MACs, if any. */ -	zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH); -	zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC); - -	/* Free up all remote VTEPs, if any. */ -	zevpn_vtep_del_all(zevpn, 1); - -	/* Delete the hash entry. */ -	zevpn_del(zevpn); +	zebra_evpn_cleanup_all(bucket, arg);  }  /* cleanup L3VNI */ @@ -2770,7 +1580,7 @@ static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id)  	zl3vni->svi_if = NULL;  	zl3vni->vxlan_if = NULL;  	zl3vni->l2vnis = list_new(); -	zl3vni->l2vnis->cmp = vni_list_cmp; +	zl3vni->l2vnis->cmp = zebra_evpn_list_cmp;  	/* Create hash table for remote RMAC */  	zl3vni->rmac_table = zebra_mac_db_create("Zebra L3-VNI RMAC-Table"); @@ -2872,7 +1682,8 @@ struct interface *zl3vni_map_to_mac_vlan_if(zebra_l3vni_t *zl3vni)  	if (!zif)  		return NULL; -	return zevpn_map_to_macvlan(zif->brslave_info.br_if, zl3vni->svi_if); +	return zebra_evpn_map_to_macvlan(zif->brslave_info.br_if, +					 zl3vni->svi_if);  } @@ -3112,7 +1923,7 @@ static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,  	 */  	if (add) {  		/* Locate hash entry */ -		zevpn = zevpn_lookup(vni); +		zevpn = zebra_evpn_lookup(vni);  		if (!zevpn)  			return 0; @@ -3120,16 +1931,16 @@ static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,  			zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni);  		/* Delete EVPN from BGP. */ -		zevpn_send_del_to_client(zevpn); +		zebra_evpn_send_del_to_client(zevpn);  		zebra_evpn_neigh_del_all(zevpn, 0, 0, DEL_ALL_NEIGH);  		zebra_evpn_mac_del_all(zevpn, 0, 0, DEL_ALL_MAC);  		/* Free up all remote VTEPs, if any. */ -		zevpn_vtep_del_all(zevpn, 0); +		zebra_evpn_vtep_del_all(zevpn, 0);  		/* Delete the hash entry. */ -		if (zevpn_del(zevpn)) { +		if (zebra_evpn_vxlan_del(zevpn)) {  			flog_err(EC_ZEBRA_VNI_DEL_FAILED,  				 "Failed to del EVPN hash %p, VNI %u", zevpn,  				 zevpn->vni); @@ -3174,40 +1985,6 @@ static void zl3vni_del_nh_hash_entry(struct hash_bucket *bucket, void *ctx)  	zl3vni_nh_del(zl3vni, n);  } -static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p, -				    uint16_t cmd) -{ -	struct zserv *client = NULL; -	struct stream *s = NULL; -	char buf[PREFIX_STRLEN]; - -	client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); -	/* BGP may not be running. */ -	if (!client) -		return 0; - -	s = stream_new(ZEBRA_MAX_PACKET_SIZ); - -	zclient_create_header(s, cmd, vrf_id); -	stream_put(s, p, sizeof(struct prefix)); - -	/* Write packet size. */ -	stream_putw_at(s, 0, stream_get_endp(s)); - -	if (IS_ZEBRA_DEBUG_VXLAN) -		zlog_debug("Send ip prefix %s %s on vrf %s", -			   prefix2str(p, buf, sizeof(buf)), -			   (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) ? "ADD" : "DEL", -			   vrf_id_to_name(vrf_id)); - -	if (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) -		client->prefixadd_cnt++; -	else -		client->prefixdel_cnt++; - -	return zserv_send_message(client, s); -} -  /* re-add remote rmac if needed */  static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t *zl3vni,  					 struct ethaddr *rmac) @@ -3227,245 +2004,6 @@ static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t *zl3vni,  	return 0;  } -static void zebra_vxlan_process_sync_macip_add(zebra_evpn_t *zevpn, -				     struct ethaddr *macaddr, -				     uint16_t ipa_len, -				     struct ipaddr *ipaddr, -				     uint8_t flags, -				     uint32_t seq, -				     esi_t *esi) -{ -	struct sync_mac_ip_ctx ctx; -	char macbuf[ETHER_ADDR_STRLEN]; -	char ipbuf[INET6_ADDRSTRLEN]; -	bool sticky; -	bool remote_gw; -	zebra_neigh_t *n = NULL; - -	sticky = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); -	remote_gw = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW); -	/* if sticky or remote-gw ignore updates from the peer */ -	if (sticky || remote_gw) { -		if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_NEIGH || -				IS_ZEBRA_DEBUG_EVPN_MH_MAC) -			zlog_debug("Ignore sync-macip vni %u mac %s%s%s%s%s", -				zevpn->vni, -				prefix_mac2str(macaddr, macbuf, sizeof(macbuf)), -				ipa_len ? " IP " : "", -				ipa_len ? -				ipaddr2str(ipaddr, ipbuf, sizeof(ipbuf)) : "", -				sticky ? " sticky" : "", -				remote_gw ? " remote_gw" : ""); -		return; -	} - -	if (ipa_len) { -		n = zebra_evpn_neigh_lookup(zevpn, ipaddr); -		if (n -		    && !zebra_evpn_neigh_is_bgp_seq_ok(zevpn, n, macaddr, seq)) -			return; -	} - -	memset(&ctx, 0, sizeof(ctx)); -	ctx.mac = zebra_evpn_proc_sync_mac_update( -		zevpn, macaddr, ipa_len, ipaddr, flags, seq, esi, &ctx); -	if (ctx.ignore_macip || !ctx.mac || !ipa_len) -		return; - -	zebra_evpn_proc_sync_neigh_update(zevpn, n, ipa_len, ipaddr, flags, seq, -					  esi, &ctx); -} - -/************************** remote mac-ip handling **************************/ -/* Process a remote MACIP add from BGP. */ -static void process_remote_macip_add(vni_t vni, -				     struct ethaddr *macaddr, -				     uint16_t ipa_len, -				     struct ipaddr *ipaddr, -				     uint8_t flags, -				     uint32_t seq, -				     struct in_addr vtep_ip, -				     esi_t *esi) -{ -	zebra_evpn_t *zevpn; -	zebra_vtep_t *zvtep; -	zebra_mac_t *mac = NULL; -	struct interface *ifp = NULL; -	struct zebra_if *zif = NULL; -	struct zebra_vrf *zvrf; - -	/* Locate EVPN hash entry - expected to exist. */ -	zevpn = zevpn_lookup(vni); -	if (!zevpn) { -		zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni); -		return; -	} - -	ifp = zevpn->vxlan_if; -	if (ifp) -		zif = ifp->info; -	if (!ifp || -	    !if_is_operative(ifp) || -	    !zif || -	    !zif->brslave_info.br_if) { -		zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info", -			  vni); -		return; -	} - -	/* Type-2 routes from another PE can be interpreted as remote or -	 * SYNC based on the destination ES - -	 * SYNC - if ES is local -	 * REMOTE - if ES is not local -	 */ -	if (flags & ZEBRA_MACIP_TYPE_SYNC_PATH) { -		zebra_vxlan_process_sync_macip_add(zevpn, macaddr, ipa_len, -				ipaddr, flags, seq, esi); -		return; -	} - -	/* The remote VTEP specified should normally exist, but it is -	 * possible that when peering comes up, peer may advertise MACIP -	 * routes before advertising type-3 routes. -	 */ -	if (vtep_ip.s_addr) { -		zvtep = zevpn_vtep_find(zevpn, &vtep_ip); -		if (!zvtep) { -			zvtep = zevpn_vtep_add(zevpn, &vtep_ip, -					VXLAN_FLOOD_DISABLED); -			if (!zvtep) { -				flog_err( -					EC_ZEBRA_VTEP_ADD_FAILED, -					"Failed to add remote VTEP, VNI %u zevpn %p upon remote MACIP ADD", -					vni, zevpn); -				return; -			} - -			zevpn_vtep_install(zevpn, zvtep); -		} -	} - -	zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id); -	if (!zvrf) -		return; - - -	if (process_mac_remote_macip_add(zevpn, zvrf, macaddr, ipa_len, ipaddr, -					 &mac, vtep_ip, flags, seq, esi) -	    != 0) -		return; - -	process_neigh_remote_macip_add(zevpn, zvrf, ipaddr, mac, vtep_ip, flags, -				       seq); -} - -/* Process a remote MACIP delete from BGP. */ -static void process_remote_macip_del(vni_t vni, -				     struct ethaddr *macaddr, -				     uint16_t ipa_len, -				     struct ipaddr *ipaddr, -				     struct in_addr vtep_ip) -{ -	zebra_evpn_t *zevpn; -	zebra_mac_t *mac = NULL; -	zebra_neigh_t *n = NULL; -	struct interface *ifp = NULL; -	struct zebra_if *zif = NULL; -	struct zebra_ns *zns; -	struct zebra_l2info_vxlan *vxl; -	struct zebra_vrf *zvrf; -	char buf[ETHER_ADDR_STRLEN]; -	char buf1[INET6_ADDRSTRLEN]; - -	/* Locate EVPN hash entry - expected to exist. */ -	zevpn = zevpn_lookup(vni); -	if (!zevpn) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni); -		return; -	} - -	ifp = zevpn->vxlan_if; -	if (ifp) -		zif = ifp->info; -	if (!ifp || -	    !if_is_operative(ifp) || -	    !zif || -	    !zif->brslave_info.br_if) { -		if (IS_ZEBRA_DEBUG_VXLAN) -			zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info", -				   vni); -		return; -	} -	zns = zebra_ns_lookup(NS_DEFAULT); -	vxl = &zif->l2info.vxl; - -	mac = zebra_evpn_mac_lookup(zevpn, macaddr); -	if (ipa_len) -		n = zebra_evpn_neigh_lookup(zevpn, ipaddr); - -	if (n && !mac) { -		zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL", -			  prefix_mac2str(macaddr, buf, sizeof(buf)), -			  ipaddr2str(ipaddr, buf1, sizeof(buf1)), vni); -		return; -	} - -	/* If the remote mac or neighbor doesn't exist there is nothing -	 * more to do. Otherwise, uninstall the entry and then remove it. -	 */ -	if (!mac && !n) -		return; - -	zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id); - -	/* Ignore the delete if this mac is a gateway mac-ip */ -	if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) -	    && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) { -		zlog_warn( -			"Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC", -			vni, -			prefix_mac2str(macaddr, buf, sizeof(buf)), -			ipa_len ? " IP " : "", -			ipa_len ? -			ipaddr2str(ipaddr, buf1, sizeof(buf1)) : ""); -		return; -	} - -	/* Uninstall remote neighbor or MAC. */ -	if (n) -		zebra_evpn_neigh_remote_uninstall(zevpn, zvrf, n, mac, ipaddr); -	else { -		/* DAD: when MAC is freeze state as remote learn event, -		 * remote mac-ip delete event is received will result in freeze -		 * entry removal, first fetch kernel for the same entry present -		 * as LOCAL and reachable, avoid deleting this entry instead -		 * use kerenel local entry to update during unfreeze time. -		 */ -		if (zvrf->dad_freeze && -		    CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) && -		    CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { -			if (IS_ZEBRA_DEBUG_VXLAN) -				zlog_debug( -					"%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry", -					__func__, -					prefix_mac2str(macaddr, buf, -						       sizeof(buf)), -					mac->flags); -			macfdb_read_specific_mac(zns, zif->brslave_info.br_if, -						 macaddr, vxl->access_vlan); -		} - -		if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { -			if (!ipa_len) -				zebra_evpn_sync_mac_del(mac); -		} else if (CHECK_FLAG(mac->flags, ZEBRA_NEIGH_REMOTE)) { -			zebra_evpn_rem_mac_del(zevpn, mac); -		} -	} -} - -  /* Public functions */  int is_l3vni_for_prefix_routes_only(vni_t vni) @@ -3866,7 +2404,7 @@ void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,  	if (!is_evpn_enabled())  		return; -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn) {  		if (use_json)  			vty_out(vty, "{}\n"); @@ -3983,7 +2521,7 @@ void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,  	if (!is_evpn_enabled())  		return; -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn) {  		if (use_json)  			vty_out(vty, "{}\n"); @@ -4026,7 +2564,7 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,  	if (!is_evpn_enabled())  		return; -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn) {  		if (use_json)  			vty_out(vty, "{}\n"); @@ -4076,7 +2614,7 @@ void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,  	if (!is_evpn_enabled())  		return; -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn) {  		vty_out(vty, "%% VNI %u does not exist\n", vni);  		return; @@ -4139,7 +2677,7 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,  	if (!is_evpn_enabled())  		return; -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn) {  		if (use_json)  			vty_out(vty, "{}\n"); @@ -4289,7 +2827,7 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,  	if (!is_evpn_enabled())  		return; -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn) {  		if (use_json)  			vty_out(vty, "{}\n"); @@ -4333,7 +2871,7 @@ void zebra_vxlan_print_macs_vni_dad(struct vty *vty,  	if (!is_evpn_enabled())  		return; -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn) {  		vty_out(vty, "%% VNI %u does not exist\n", vni);  		return; @@ -4388,7 +2926,7 @@ int zebra_vxlan_clear_dup_detect_vni_mac(struct zebra_vrf *zvrf, vni_t vni,  	if (!is_evpn_enabled())  		return 0; -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn) {  		zlog_warn("VNI %u does not exist\n", vni);  		return -1; @@ -4474,7 +3012,7 @@ int zebra_vxlan_clear_dup_detect_vni_ip(struct zebra_vrf *zvrf, vni_t vni,  	if (!is_evpn_enabled())  		return 0; -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn) {  		zlog_debug("VNI %u does not exist\n", vni);  		return -1; @@ -4637,7 +3175,7 @@ int zebra_vxlan_clear_dup_detect_vni(struct zebra_vrf *zvrf, vni_t vni)  	if (!is_evpn_enabled())  		return 0; -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn) {  		zlog_warn("VNI %u does not exist\n", vni);  		return CMD_WARNING; @@ -4676,7 +3214,7 @@ void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,  	if (!is_evpn_enabled())  		return; -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn) {  		if (use_json)  			vty_out(vty, "{}\n"); @@ -4741,9 +3279,9 @@ void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,  	if (zl3vni) {  		zl3vni_print(zl3vni, (void *)args);  	} else { -		zevpn = zevpn_lookup(vni); +		zevpn = zebra_evpn_lookup(vni);  		if (zevpn) -			zevpn_print(zevpn, (void *)args); +			zebra_evpn_print(zevpn, (void *)args);  		else if (!json)  			vty_out(vty, "%% VNI %u does not exist\n", vni);  	} @@ -4853,9 +3391,10 @@ void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,  	args[1] = json;  	/* Display all L2-VNIs */ -	hash_iterate(zvrf->evpn_table, -		     (void (*)(struct hash_bucket *, void *))zevpn_print_hash, -		     args); +	hash_iterate( +		zvrf->evpn_table, +		(void (*)(struct hash_bucket *, void *))zebra_evpn_print_hash, +		args);  	/* Display all L3-VNIs */  	hash_iterate(zrouter.l3vni_table, @@ -4919,7 +3458,7 @@ void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,  {  	json_object *json_array = NULL;  	struct zebra_ns *zns = NULL; -	struct zevpn_show zes; +	struct zebra_evpn_show zes;  	if (!is_evpn_enabled())  		return; @@ -4937,10 +3476,10 @@ void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,  	zes.use_json = use_json;  	/* Display all L2-VNIs */ -	hash_iterate( -		zvrf->evpn_table, -		(void (*)(struct hash_bucket *, void *))zevpn_print_hash_detail, -		&zes); +	hash_iterate(zvrf->evpn_table, +		     (void (*)(struct hash_bucket *, +			       void *))zebra_evpn_print_hash_detail, +		     &zes);  	/* Display all L3-VNIs */  	hash_iterate(zrouter.l3vni_table, @@ -4980,7 +3519,7 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,  	/* We are only interested in neighbors on an SVI that resides on top  	 * of a VxLAN bridge.  	 */ -	zevpn = zevpn_from_svi(ifp, link_if); +	zevpn = zebra_evpn_from_svi(ifp, link_if);  	if (!zevpn) {  		if (IS_ZEBRA_DEBUG_VXLAN)  			zlog_debug( @@ -5035,7 +3574,7 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,  	/* We are only interested in neighbors on an SVI that resides on top  	 * of a VxLAN bridge.  	 */ -	zevpn = zevpn_from_svi(ifp, link_if); +	zevpn = zebra_evpn_from_svi(ifp, link_if);  	if (!zevpn)  		return 0; @@ -5251,12 +3790,12 @@ int zebra_vxlan_check_readd_vtep(struct interface *ifp,  		return -1;  	/* Locate hash entry; it is expected to exist. */ -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn)  		return 0;  	/* If the remote vtep entry doesn't exists nothing to do */ -	zvtep = zevpn_vtep_find(zevpn, &vtep_ip); +	zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);  	if (!zvtep)  		return 0; @@ -5265,7 +3804,7 @@ int zebra_vxlan_check_readd_vtep(struct interface *ifp,  			"Del MAC for remote VTEP %s intf %s(%u) VNI %u - readd",  			inet_ntoa(vtep_ip), ifp->name, ifp->ifindex, vni); -	zevpn_vtep_install(zevpn, zvtep); +	zebra_evpn_vtep_install(zevpn, zvtep);  	return 0;  } @@ -5295,7 +3834,7 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp,  		return 0;  	/* Locate hash entry; it is expected to exist. */ -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn)  		return 0; @@ -5365,7 +3904,7 @@ int zebra_vxlan_check_readd_remote_mac(struct interface *ifp,  		return zebra_vxlan_readd_remote_rmac(zl3vni, macaddr);  	/* Locate hash entry; it is expected to exist. */ -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn)  		return 0; @@ -5398,7 +3937,7 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,  	/* We are interested in MACs only on ports or (port, VLAN) that  	 * map to a VNI.  	 */ -	zevpn = zevpn_map_vlan(ifp, br_if, vid); +	zevpn = zebra_evpn_map_vlan(ifp, br_if, vid);  	if (!zevpn)  		return 0;  	if (!zevpn->vxlan_if) { @@ -5430,7 +3969,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,  	/* We are interested in MACs only on ports or (port, VLAN) that  	 * map to an EVPN.  	 */ -	zevpn = zevpn_map_vlan(ifp, br_if, vid); +	zevpn = zebra_evpn_map_vlan(ifp, br_if, vid);  	if (!zevpn) {  		if (IS_ZEBRA_DEBUG_VXLAN)  			zlog_debug( @@ -5510,7 +4049,7 @@ void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS)  				   zebra_route_string(client->proto));  		/* Locate VNI hash entry - expected to exist. */ -		zevpn = zevpn_lookup(vni); +		zevpn = zebra_evpn_lookup(vni);  		if (!zevpn) {  			if (IS_ZEBRA_DEBUG_VXLAN)  				zlog_debug( @@ -5538,12 +4077,12 @@ void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS)  		 * and  		 * then, the VTEP entry itself and remove it.  		 */ -		zvtep = zevpn_vtep_find(zevpn, &vtep_ip); +		zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);  		if (!zvtep)  			continue; -		zevpn_vtep_uninstall(zevpn, &vtep_ip); -		zevpn_vtep_del(zevpn, zvtep); +		zebra_evpn_vtep_uninstall(zevpn, &vtep_ip); +		zebra_evpn_vtep_del(zevpn, zvtep);  	}  stream_failure: @@ -5594,7 +4133,7 @@ void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)  					zebra_route_string(client->proto));  		/* Locate VNI hash entry - expected to exist. */ -		zevpn = zevpn_lookup(vni); +		zevpn = zebra_evpn_lookup(vni);  		if (!zevpn) {  			flog_err(  				EC_ZEBRA_VTEP_ADD_FAILED, @@ -5618,7 +4157,7 @@ void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)  		if (!if_is_operative(ifp) || !zif->brslave_info.br_if)  			continue; -		zvtep = zevpn_vtep_find(zevpn, &vtep_ip); +		zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);  		if (zvtep) {  			/* If the remote VTEP already exists check if  			 * the flood mode has changed @@ -5630,14 +4169,16 @@ void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)  					 * is no longer; get rid of the HER fdb  					 * entry installed before  					 */ -					zevpn_vtep_uninstall(zevpn, &vtep_ip); +					zebra_evpn_vtep_uninstall(zevpn, +								  &vtep_ip);  				zvtep->flood_control = flood_control; -				zevpn_vtep_install(zevpn, zvtep); +				zebra_evpn_vtep_install(zevpn, zvtep);  			}  		} else { -			zvtep = zevpn_vtep_add(zevpn, &vtep_ip, flood_control); +			zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip, +						    flood_control);  			if (zvtep) -				zevpn_vtep_install(zevpn, zvtep); +				zebra_evpn_vtep_install(zevpn, zvtep);  			else  				flog_err(EC_ZEBRA_VTEP_ADD_FAILED,  					"Failed to add remote VTEP, VNI %u zevpn %p", @@ -5706,14 +4247,15 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,  				svi_if_link = if_lookup_by_index_per_ns(  					zebra_ns_lookup(NS_DEFAULT),  					svi_if_zif->link_ifindex); -				zevpn = zevpn_from_svi(svi_if, svi_if_link); +				zevpn = zebra_evpn_from_svi(svi_if, +							    svi_if_link);  			}  		} else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {  			/*  			 * If it is a vlan unaware bridge then svi is the bridge  			 * itself  			 */ -			zevpn = zevpn_from_svi(svi_if, svi_if); +			zevpn = zebra_evpn_from_svi(svi_if, svi_if);  		}  	} else if (IS_ZEBRA_IF_VLAN(ifp)) {  		struct zebra_if *svi_if_zif = @@ -5727,10 +4269,10 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,  				zebra_ns_lookup(NS_DEFAULT),  				svi_if_zif->link_ifindex);  			if (svi_if_link) -				zevpn = zevpn_from_svi(ifp, svi_if_link); +				zevpn = zebra_evpn_from_svi(ifp, svi_if_link);  		}  	} else if (IS_ZEBRA_IF_BRIDGE(ifp)) { -		zevpn = zevpn_from_svi(ifp, ifp); +		zevpn = zebra_evpn_from_svi(ifp, ifp);  	}  	if (!zevpn) @@ -5757,9 +4299,9 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,  	if (add) -		zevpn_gw_macip_add(ifp, zevpn, &macaddr, &ip); +		zebra_evpn_gw_macip_add(ifp, zevpn, &macaddr, &ip);  	else -		zevpn_gw_macip_del(ifp, zevpn, &ip); +		zebra_evpn_gw_macip_del(ifp, zevpn, &ip);  	return 0;  } @@ -5791,12 +4333,12 @@ int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)  		/* since we dont have svi corresponding to zevpn, we associate it  		 * to default vrf. Note: the corresponding neigh entries on the  		 * SVI would have already been deleted */ -		zevpn = zevpn_from_svi(ifp, link_if); +		zevpn = zebra_evpn_from_svi(ifp, link_if);  		if (zevpn) {  			zevpn->vrf_id = VRF_DEFAULT;  			/* update the tenant vrf in BGP */ -			zevpn_send_add_to_client(zevpn); +			zebra_evpn_send_add_to_client(zevpn);  		}  	}  	return 0; @@ -5829,7 +4371,7 @@ int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)  		/* process SVI up for l2-vni */  		struct neigh_walk_ctx n_wctx; -		zevpn = zevpn_from_svi(ifp, link_if); +		zevpn = zebra_evpn_from_svi(ifp, link_if);  		if (!zevpn)  			return 0; @@ -5848,7 +4390,7 @@ int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)  		/* update the vrf information for l2-vni and inform bgp */  		zevpn->vrf_id = ifp->vrf_id; -		zevpn_send_add_to_client(zevpn); +		zebra_evpn_send_add_to_client(zevpn);  		/* Install any remote neighbors for this VNI. */  		memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx)); @@ -5966,7 +4508,7 @@ int zebra_vxlan_if_down(struct interface *ifp)  				   ifp->ifindex, vni);  		/* Locate hash entry; it is expected to exist. */ -		zevpn = zevpn_lookup(vni); +		zevpn = zebra_evpn_lookup(vni);  		if (!zevpn) {  			zlog_debug(  				"Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u", @@ -5977,14 +4519,14 @@ int zebra_vxlan_if_down(struct interface *ifp)  		assert(zevpn->vxlan_if == ifp);  		/* Delete this VNI from BGP. */ -		zevpn_send_del_to_client(zevpn); +		zebra_evpn_send_del_to_client(zevpn);  		/* Free up all neighbors and MACs, if any. */  		zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);  		zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);  		/* Free up all remote VTEPs, if any. */ -		zevpn_vtep_del_all(zevpn, 1); +		zebra_evpn_vtep_del_all(zevpn, 1);  	}  	return 0;  } @@ -6035,7 +4577,7 @@ int zebra_vxlan_if_up(struct interface *ifp)  				   ifp->ifindex, vni);  		/* Locate hash entry; it is expected to exist. */ -		zevpn = zevpn_lookup(vni); +		zevpn = zebra_evpn_lookup(vni);  		if (!zevpn) {  			zlog_debug(  				"Failed to locate EVPN hash at UP, IF %s(%u) VNI %u", @@ -6056,8 +4598,8 @@ int zebra_vxlan_if_up(struct interface *ifp)  		/* If part of a bridge, inform BGP about this VNI. */  		/* Also, read and populate local MACs and neighbors. */  		if (zif->brslave_info.br_if) { -			zevpn_send_add_to_client(zevpn); -			zevpn_read_mac_neigh(zevpn, ifp); +			zebra_evpn_send_add_to_client(zevpn); +			zebra_evpn_read_mac_neigh(zevpn, ifp);  		}  	} @@ -6106,7 +4648,7 @@ int zebra_vxlan_if_del(struct interface *ifp)  				   ifp->ifindex);  		/* Locate hash entry; it is expected to exist. */ -		zevpn = zevpn_lookup(vni); +		zevpn = zebra_evpn_lookup(vni);  		if (!zevpn) {  			zlog_debug(  				"Failed to locate VNI hash at del, IF %s(%u) VNI %u", @@ -6119,17 +4661,17 @@ int zebra_vxlan_if_del(struct interface *ifp)  		if (zl3vni)  			listnode_delete(zl3vni->l2vnis, zevpn);  		/* Delete VNI from BGP. */ -		zevpn_send_del_to_client(zevpn); +		zebra_evpn_send_del_to_client(zevpn);  		/* Free up all neighbors and MAC, if any. */  		zebra_evpn_neigh_del_all(zevpn, 0, 0, DEL_ALL_NEIGH);  		zebra_evpn_mac_del_all(zevpn, 0, 0, DEL_ALL_MAC);  		/* Free up all remote VTEPs, if any. */ -		zevpn_vtep_del_all(zevpn, 0); +		zebra_evpn_vtep_del_all(zevpn, 0);  		/* Delete the hash entry. */ -		if (zevpn_del(zevpn)) { +		if (zebra_evpn_vxlan_del(zevpn)) {  			flog_err(EC_ZEBRA_VNI_DEL_FAILED,  				 "Failed to del EVPN hash %p, IF %s(%u) VNI %u",  				 zevpn, ifp->name, ifp->ifindex, zevpn->vni); @@ -6218,7 +4760,7 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)  	} else {  		/* Update VNI hash. */ -		zevpn = zevpn_lookup(vni); +		zevpn = zebra_evpn_lookup(vni);  		if (!zevpn) {  			zlog_debug(  				"Failed to find EVPN hash on update, IF %s(%u) VNI %u", @@ -6238,10 +4780,10 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)  		    && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {  			/* Delete from client, remove all remote VTEPs */  			/* Also, free up all MACs and neighbors. */ -			zevpn_send_del_to_client(zevpn); +			zebra_evpn_send_del_to_client(zevpn);  			zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);  			zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC); -			zevpn_vtep_del_all(zevpn, 1); +			zebra_evpn_vtep_del_all(zevpn, 1);  			return 0;  		} @@ -6279,7 +4821,7 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)  			& (ZEBRA_VXLIF_MASTER_CHANGE |  			   ZEBRA_VXLIF_LOCAL_IP_CHANGE |  			   ZEBRA_VXLIF_MCAST_GRP_CHANGE)) -			zevpn_send_add_to_client(zevpn); +			zebra_evpn_send_add_to_client(zevpn);  		/* If there is a valid new master or a VLAN mapping change,  		 * read and populate local MACs and neighbors. @@ -6287,17 +4829,17 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)  		 * for this VNI (based on new VLAN).  		 */  		if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) -			zevpn_read_mac_neigh(zevpn, ifp); +			zebra_evpn_read_mac_neigh(zevpn, ifp);  		else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {  			struct mac_walk_ctx m_wctx;  			struct neigh_walk_ctx n_wctx; -			zevpn_read_mac_neigh(zevpn, ifp); +			zebra_evpn_read_mac_neigh(zevpn, ifp);  			memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));  			m_wctx.zevpn = zevpn; -			hash_iterate(zevpn->mac_table, zevpn_install_mac_hash, -				     &m_wctx); +			hash_iterate(zevpn->mac_table, +				     zebra_evpn_install_mac_hash, &m_wctx);  			memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));  			n_wctx.zevpn = zevpn; @@ -6358,9 +4900,9 @@ int zebra_vxlan_if_add(struct interface *ifp)  		struct interface *vlan_if = NULL;  		/* Create or update EVPN hash. */ -		zevpn = zevpn_lookup(vni); +		zevpn = zebra_evpn_lookup(vni);  		if (!zevpn) { -			zevpn = zevpn_add(vni); +			zevpn = zebra_evpn_add(vni);  			if (!zevpn) {  				flog_err(  					EC_ZEBRA_VNI_ADD_FAILED, @@ -6416,10 +4958,10 @@ int zebra_vxlan_if_add(struct interface *ifp)  			return 0;  		/* Inform BGP */ -		zevpn_send_add_to_client(zevpn); +		zebra_evpn_send_add_to_client(zevpn);  		/* Read and populate local MACs and neighbors */ -		zevpn_read_mac_neigh(zevpn, ifp); +		zebra_evpn_read_mac_neigh(zevpn, ifp);  	}  	return 0; @@ -6627,7 +5169,7 @@ void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS)  	/* Install or uninstall flood entries corresponding to  	 * remote VTEPs.  	 */ -	hash_iterate(zvrf->evpn_table, zevpn_handle_flooding_remote_vteps, +	hash_iterate(zvrf->evpn_table, zebra_evpn_handle_flooding_remote_vteps,  		     zvrf);  stream_failure: @@ -6671,10 +5213,12 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)  		if (advertise) {  			zvrf->advertise_svi_macip = advertise;  			hash_iterate(zvrf->evpn_table, -				     zevpn_gw_macip_add_for_evpn_hash, NULL); +				     zebra_evpn_gw_macip_add_for_evpn_hash, +				     NULL);  		} else {  			hash_iterate(zvrf->evpn_table, -				     zevpn_svi_macip_del_for_evpn_hash, NULL); +				     zebra_evpn_svi_macip_del_for_evpn_hash, +				     NULL);  			zvrf->advertise_svi_macip = advertise;  		} @@ -6683,7 +5227,7 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)  		struct zebra_l2info_vxlan zl2_info;  		struct interface *vlan_if = NULL; -		zevpn = zevpn_lookup(vni); +		zevpn = zebra_evpn_lookup(vni);  		if (!zevpn)  			return; @@ -6721,10 +5265,10 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)  		if (advertise) {  			/* Add primary SVI MAC-IP */ -			zevpn_add_macip_for_intf(vlan_if, zevpn); +			zebra_evpn_add_macip_for_intf(vlan_if, zevpn);  		} else {  			/* Del primary SVI MAC-IP */ -			zevpn_del_macip_for_intf(vlan_if, zevpn); +			zebra_evpn_del_macip_for_intf(vlan_if, zevpn);  		}  	} @@ -6757,7 +5301,7 @@ void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)  	STREAM_GETC(s, advertise);  	STREAM_GET(&vni, s, 3); -	zevpn = zevpn_lookup(vni); +	zevpn = zebra_evpn_lookup(vni);  	if (!zevpn)  		return; @@ -6790,9 +5334,9 @@ void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)  		return;  	if (zevpn->advertise_subnet) -		zevpn_advertise_subnet(zevpn, vlan_if, 1); +		zebra_evpn_advertise_subnet(zevpn, vlan_if, 1);  	else -		zevpn_advertise_subnet(zevpn, vlan_if, 0); +		zebra_evpn_advertise_subnet(zevpn, vlan_if, 0);  stream_failure:  	return; @@ -6835,10 +5379,12 @@ void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)  		if (advertise_gw_macip_enabled(zevpn))  			hash_iterate(zvrf->evpn_table, -				     zevpn_gw_macip_add_for_evpn_hash, NULL); +				     zebra_evpn_gw_macip_add_for_evpn_hash, +				     NULL);  		else  			hash_iterate(zvrf->evpn_table, -				     zevpn_gw_macip_del_for_evpn_hash, NULL); +				     zebra_evpn_gw_macip_del_for_evpn_hash, +				     NULL);  	} else {  		struct zebra_if *zif = NULL; @@ -6846,7 +5392,7 @@ void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)  		struct interface *vlan_if = NULL;  		struct interface *vrr_if = NULL; -		zevpn = zevpn_lookup(vni); +		zevpn = zebra_evpn_lookup(vni);  		if (!zevpn)  			return; @@ -6881,20 +5427,20 @@ void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)  		if (advertise_gw_macip_enabled(zevpn)) {  			/* Add primary SVI MAC-IP */ -			zevpn_add_macip_for_intf(vlan_if, zevpn); +			zebra_evpn_add_macip_for_intf(vlan_if, zevpn);  			/* Add VRR MAC-IP - if any*/  			vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);  			if (vrr_if) -				zevpn_add_macip_for_intf(vrr_if, zevpn); +				zebra_evpn_add_macip_for_intf(vrr_if, zevpn);  		} else {  			/* Del primary MAC-IP */ -			zevpn_del_macip_for_intf(vlan_if, zevpn); +			zebra_evpn_del_macip_for_intf(vlan_if, zevpn);  			/* Del VRR MAC-IP - if any*/  			vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);  			if (vrr_if) -				zevpn_del_macip_for_intf(vrr_if, zevpn); +				zebra_evpn_del_macip_for_intf(vrr_if, zevpn);  		}  	} @@ -6950,8 +5496,8 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)  		zevpn_build_hash_table();  		/* Add all SVI (L3 GW) MACs to BGP*/ -		hash_iterate(zvrf->evpn_table, zevpn_gw_macip_add_for_evpn_hash, -			     NULL); +		hash_iterate(zvrf->evpn_table, +			     zebra_evpn_gw_macip_add_for_evpn_hash, NULL);  		/* Read the MAC FDB */  		macfdb_read(zvrf->zns); @@ -6962,7 +5508,8 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)  		/* Cleanup VTEPs for all EVPNs - uninstall from  		 * kernel and free entries.  		 */ -		hash_iterate(zvrf->evpn_table, zevpn_cleanup_all, zvrf); +		hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all, +			     zvrf);  		/* Delete all ESs in BGP */  		zebra_evpn_es_send_all_to_client(false /* add */); @@ -6986,8 +5533,9 @@ void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)  {  	if (!zvrf)  		return; -	zvrf->evpn_table = hash_create(evpn_hash_keymake, vni_hash_cmp, -				      "Zebra VRF EVPN Table"); +	zvrf->evpn_table = +		hash_create(zebra_evpn_hash_keymake, zebra_evpn_hash_cmp, +			    "Zebra VRF EVPN Table");  	zvrf->vxlan_sg_table = hash_create(zebra_vxlan_sg_hash_key_make,  			zebra_vxlan_sg_hash_eq, "Zebra VxLAN SG Table");  } @@ -6999,7 +5547,7 @@ void zebra_vxlan_cleanup_tables(struct zebra_vrf *zvrf)  	if (!zvrf)  		return; -	hash_iterate(zvrf->evpn_table, zevpn_cleanup_all, zvrf); +	hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all, zvrf);  	hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_sg_cleanup, NULL);  	if (zvrf == evpn_zvrf) @@ -7011,7 +5559,7 @@ void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)  {  	if (!zvrf)  		return; -	hash_iterate(zvrf->evpn_table, zevpn_cleanup_all, zvrf); +	hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all, zvrf);  	hash_free(zvrf->evpn_table);  } @@ -7294,22 +5842,6 @@ void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS)  	hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_sg_replay_send, NULL);  } -/************************** EVPN BGP config management ************************/ -static void zevpn_cfg_cleanup(struct hash_bucket *bucket, void *ctxt) -{ -	zebra_evpn_t *zevpn = NULL; - -	zevpn = (zebra_evpn_t *)bucket->data; -	zevpn->advertise_gw_macip = 0; -	zevpn->advertise_svi_macip = 0; -	zevpn->advertise_subnet = 0; - -	zebra_evpn_neigh_del_all(zevpn, 1, 0, -				 DEL_REMOTE_NEIGH | DEL_REMOTE_NEIGH_FROM_VTEP); -	zebra_evpn_mac_del_all(zevpn, 1, 0, -			       DEL_REMOTE_MAC | DEL_REMOTE_MAC_FROM_VTEP); -	zevpn_vtep_del_all(zevpn, 1); -}  /* Cleanup EVPN configuration of a specific VRF */  static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf *zvrf) @@ -7321,7 +5853,7 @@ static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf *zvrf)  	zvrf->advertise_svi_macip = 0;  	zvrf->vxlan_flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL; -	hash_iterate(zvrf->evpn_table, zevpn_cfg_cleanup, NULL); +	hash_iterate(zvrf->evpn_table, zebra_evpn_cfg_cleanup, NULL);  	if (zvrf->l3vni)  		zl3vni = zl3vni_lookup(zvrf->l3vni);  | 
