diff --git a/src/agent.c b/src/agent.c
index 0cd52ae13dd3130d91f6d928a3b991da5b891ef6..5683844f272627318412d4a4016919ccefc24d65 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -590,6 +590,19 @@ struct netif_bk *find_bkhaul_by_bssid(struct agent *a, uint8_t *bssid)
 	return NULL;
 }
 
+/* find wds by interface name */
+struct netif_wds *find_wds_by_ifname(struct agent *a, const char *ifname)
+{
+	struct netif_wds *p;
+
+	list_for_each_entry(p, &a->wdslist, list) {
+		if (!strncmp(p->name, ifname, sizeof(p->name)))
+			return p;
+	}
+
+	return NULL;
+}
+
 void agent_link_ap_to_cfg(struct agent *a)
 {
 	struct netif_fhcfg *fcfg;
@@ -2132,7 +2145,7 @@ static uint16_t wifi_process_pvid_assoc_frame(struct agent *a, uint8_t *frame,
 static void wifi_sta_event_handler(void *c, struct blob_attr *msg)
 {
 	struct agent *a = (struct agent *)c;
-	char ifname[16] = {0}, event[16] = {0};
+	char ifname[16] = {0}, event[24] = {0};
 	struct blob_attr *tb[3];
 	static const struct blobmsg_policy ev_attr[3] = {
 		[0] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING },
@@ -2322,8 +2335,44 @@ static void wifi_sta_event_handler(void *c, struct blob_attr *msg)
 
 		if (!s->supports_bcnreport)
 			s->supports_bcnreport = true;
-	} else if (!strcmp(event, "wds-station-add")) {
-		/* TODO: wds handling */
+	} else if (!strcmp(event, "wds-station-added") ||
+		   !strcmp(event, "wds-station-removed")) {
+		struct blob_attr *data[1];
+		static const struct blobmsg_policy data_attr[1] = {
+			[0] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING },
+		};
+		char wdsname[16] = {0};
+		struct ts_context *ts = &a->ts;
+		struct netif_fh *fh = NULL;
+		bool add = !strcmp(event, "wds-station-added");
+		uint16_t vid;
+
+		if (a->cfg.brcm_setup)
+			return;
+
+		blobmsg_parse(data_attr, 1, data, blobmsg_data(tb[2]),
+				blobmsg_data_len(tb[2]));
+
+		if (!data[0])
+			return;
+
+		strncpy(wdsname, blobmsg_data(data[0]), sizeof(wdsname) - 1);
+
+		if (add)
+			netif_alloc_wds(a, wdsname);
+		else
+			netif_free_wds_by_ifname(a, wdsname);
+
+		list_for_each_entry(fh, &a->fhlist, list) {
+			vid = fh->cfg->vid;
+			if (!is_vid_valid(vid))
+				vid = ts->primary_vid;
+
+			if (a->cfg.guest_isolation && (vid != 1 && vid != ts->primary_vid)) {
+				dbg("/lib/wifi/multiap ts isolate_wds %s %s %s\n", (add ? "add" : "del"), fh->name, wdsname);
+				runCmd("/lib/wifi/multiap ts isolate_wds %s %s %s", (add ? "add" : "del"), fh->name, wdsname);
+			}
+		}
 	} else if (!strcmp(event, "action")) { /* TODO: this event belongs under wifi.iface handler */
 		struct blob_attr *data[2];
 		static const struct blobmsg_policy data_attr[2] = {
@@ -5172,6 +5221,38 @@ static struct netif_bk *netif_alloc_bk(const char *ifname)
 	return n;
 }
 
+struct netif_wds *netif_alloc_wds(struct agent *a, const char *ifname)
+{
+	struct netif_wds *n = NULL;
+
+	n = calloc(1, sizeof(struct netif_wds));
+	if (!n)
+		return NULL;
+
+	snprintf(n->name, 15, "%s", ifname);
+
+	list_add(&n->list, &a->wdslist);
+
+	return n;
+}
+
+void netif_free_wds(struct netif_wds *n)
+{
+	list_del(&n->list);
+	free(n);
+}
+
+void netif_free_wds_by_ifname(struct agent *a, const char *ifname)
+{
+	struct netif_wds *n = NULL;
+
+	n = find_wds_by_ifname(a, ifname);
+	if (!n)
+		return;
+
+	netif_free_wds(n);
+}
+
 /* get first ap on the radio */
 // TODO: fixme: get base interface based on macaddr instead?
 struct netif_fh *wifi_radio_to_ap(struct agent *a, const char *radio)
@@ -6429,6 +6510,14 @@ void clear_bklist(struct agent *a)
 	}
 }
 
+void clear_wdslist(struct agent *a)
+{
+	struct netif_wds *p, *tmp;
+
+	list_for_each_entry_safe(p, tmp,  &a->wdslist, list) {
+		netif_free_wds(p);
+	}
+}
 
 int agent_map_sub_cb(void *bus, void *priv, void *data)
 {
@@ -6540,6 +6629,7 @@ int agent_init_defaults(struct agent *a)
 	INIT_LIST_HEAD(&a->ethlist);
 	INIT_LIST_HEAD(&a->framelist);
 	INIT_LIST_HEAD(&a->nodelist);
+	INIT_LIST_HEAD(&a->wdslist);
 #if (EASYMESH_VERSION > 2)
 	INIT_LIST_HEAD(&a->dpp_ctx.enrolleelist);
 	INIT_LIST_HEAD(&a->dpp_ctx.chirplist);
@@ -6738,6 +6828,7 @@ void run_agent(void)
 	cmdu_ackq_free(&w->cmdu_ack_q);
 	clear_fhlist(w);
 	clear_bklist(w);
+	clear_wdslist(w);
 	ubus_unregister_event_handler(ctx, &w->evh);
 #ifdef VENDOR_EXTENSION
 	agent_unload_extensions(w);
diff --git a/src/agent.h b/src/agent.h
index 9bdb7e90f7c4ca8f0f15791877d21ab17cb4c54b..07d58bb07ace6ec217519433883be1f509e956f4 100644
--- a/src/agent.h
+++ b/src/agent.h
@@ -339,6 +339,12 @@ struct netif_bk {
 	uint8_t blacklist_bssid[16][6];
 };
 
+/* wds wifi (ap vlan) interface */
+struct netif_wds {
+	char name[16];
+	struct list_head list;
+};
+
 #if 0
 struct agent_msg {
 	void *ctx;
@@ -672,6 +678,7 @@ struct agent {
 	struct list_head bklist;
 	struct list_head framelist;
 	struct list_head ethlist;
+	struct list_head wdslist;
 
 #if (EASYMESH_VERSION > 2)
 	struct dpp_context dpp_ctx;
@@ -870,6 +877,7 @@ void agent_free_radios(struct agent *a);
 void agent_free_cntlr_sync(struct agent *a);
 void clear_fhlist(struct agent *a);
 void clear_bklist(struct agent *a);
+void clear_wdslist(struct agent *a);
 bool agent_has_active_backhaul(struct agent *a);
 int agent_radio_scanresults(struct agent *a, struct wifi_radio_element *re);
 int agent_init_interfaces(struct agent *a);
@@ -892,6 +900,9 @@ int agent_send_ch_scan_response(struct agent *a, struct wifi_netdev *ndev,
 		struct wifi_scan_request_radio *req);
 bool agent_ch_scan_succesful(struct agent *a);
 struct netif_fh *netif_alloc_fh(const char *ifname);
-
+struct netif_wds *netif_alloc_wds(struct agent *a, const char *ifname);
+void netif_free_wds(struct netif_wds *n);
+void netif_free_wds_by_ifname(struct agent *a, const char *ifname);
+struct netif_wds *find_wds_by_ifname(struct agent *a, const char *ifname);
 
 #endif /* AGENT_H */
diff --git a/src/agent_tlv.c b/src/agent_tlv.c
index 4e83a1c5e41386be3cd7063effba1ccf7fb1238b..a2c0f95c07b344120f45985a39094cc7adf09b8f 100644
--- a/src/agent_tlv.c
+++ b/src/agent_tlv.c
@@ -2748,7 +2748,7 @@ int agent_clear_traffic_sep(struct agent *a)
 
 	list_for_each_entry(fcfg, &a->cfg.fhlist, list) {
 		char fmt[68] = {0};
-		char fif_prefix[IFNAMSIZ] = {0}; /* 4addr ifname prefix */
+		int band = 0;
 
 		snprintf(fmt, sizeof(fmt), "ts cleanup %u", fcfg->vid);
 		agent_exec_platform_scripts(fmt);
@@ -2758,26 +2758,30 @@ int agent_clear_traffic_sep(struct agent *a)
 		if (!is_vid_valid(vid))
 			vid = a->ts.primary_vid;
 
-		if (a->cfg.brcm_setup)
-			strncpy(fif_prefix, "wds", sizeof(fif_prefix) - 1);
-		else
-			strncpy(fif_prefix, "TODO", sizeof(fif_prefix) - 1); /* FIXME: non brcm platforms, one for each bbss */
-
 		if (a->cfg.brcm_setup) {
-			int band = 0;
-
-			if (fcfg->band == BAND_2)
-				band = 2;
-			else if (fcfg->band == BAND_5)
-				band = 5;
-			else if (fcfg->band == BAND_6)
-				band = 6;
-			else
-				continue;
+			dbg("/lib/wifi/multiap ts isolate_wds %s %s wds+\n", "del", fcfg->name);
+			runCmd("/lib/wifi/multiap ts isolate_wds %s %s wds+", "del", fcfg->name);
+		}
+		else {
+			struct netif_wds *wds = NULL;
 
-			dbg("/lib/wifi/multiap ts isolate %s %d %d %d %s %s\n", "del", a->ts.primary_vid, fcfg->vid, band, fcfg->name, fif_prefix);
-			runCmd("/lib/wifi/multiap ts isolate %s %d %d %d %s %s", "del", a->ts.primary_vid, fcfg->vid, band, fcfg->name, fif_prefix);
+			list_for_each_entry(wds, &a->wdslist, list) {
+				dbg("/lib/wifi/multiap ts isolate_wds %s %s %s\n", "del", fcfg->name, wds->name);
+				runCmd("/lib/wifi/multiap ts isolate_wds %s %s %s", "del", fcfg->name, wds->name);
+			}
 		}
+
+		if (fcfg->band == BAND_2)
+			band = 2;
+		else if (fcfg->band == BAND_5)
+			band = 5;
+		else if (fcfg->band == BAND_6)
+			band = 6;
+		else
+			continue;
+
+		dbg("/lib/wifi/multiap ts isolate_ap %s %d %d %d %s\n", "del", a->ts.primary_vid, fcfg->vid, band, fcfg->name);
+		runCmd("/lib/wifi/multiap ts isolate_ap %s %d %d %d %s", "del", a->ts.primary_vid, fcfg->vid, band, fcfg->name);
 	}
 	/* if pvid was previously enabled, disable and wake nl */
 	if (a->cfg.pcfg) {
diff --git a/src/nl.c b/src/nl.c
index fbb86ac014284694d9dd4a5040e08209cc22ccd2..54395ce45552f1c0165b222f3528ad7e898df16d 100644
--- a/src/nl.c
+++ b/src/nl.c
@@ -315,11 +315,11 @@ static void ts_set_system(struct ts_context *ts)
 	Cmd(buf, sizeof(buf), "/lib/wifi/multiap ts reload");
 }
 
-static void ts_check_ifi(struct ts_context *ts, struct ifinfomsg *ifi, const char *ifname)
+static void ts_check_ifi(struct agent *a, struct ifinfomsg *ifi, const char *ifname)
 {
+	struct ts_context *ts = &a->ts;
 	struct ts_iface *tsif;
 
-
 	if (ts->primary_vid == 0)
 		return;
 
@@ -338,7 +338,8 @@ static void ts_check_ifi(struct ts_context *ts, struct ifinfomsg *ifi, const cha
 		return;
 	}
 
-	if (!strstr(ifname, "wds") && !strstr(ifname, "sta"))
+	if (!strstr(ifname, "wds") && !strstr(ifname, "sta") &&
+	    find_wds_by_ifname(a, ifname) == NULL)
 		return;
 
 	tsif = ts_configure_iface(ts, ifname, 0);
@@ -390,7 +391,6 @@ int nl_main_cb(struct nl_msg *msg, void *arg)
 {
 	struct nlmsghdr *nlh = nlmsg_hdr(msg);
 	struct agent *a = (struct agent *) arg;
-	struct ts_context *ts = &a->ts;
 	const char *bridge = a->cfg.al_bridge;
 	bool brcm_setup = a->cfg.brcm_setup;
 
@@ -423,7 +423,7 @@ int nl_main_cb(struct nl_msg *msg, void *arg)
 			if (!(ifi->ifi_flags & IFF_UP))
 				break;
 */
-			ts_check_ifi(ts, ifi, ifname);
+			ts_check_ifi(a, ifi, ifname);
 
 			if (!brcm_setup)
 				break;
@@ -512,8 +512,8 @@ static void ts_configure(struct agent *a)
 
 	/* Fronthaul/Backhaul APs */
 	list_for_each_entry(fh, &a->fhlist, list) {
-		char fif_prefix[IFNAMSIZ] = {0}; /* 4addr ifname prefix */
 		bool add = false;
+		int band = 0;
 
 		dbg("FH/BH AP name %s multi_ap %d\n", fh->name, fh->cfg->multi_ap);
 		vid = fh->cfg->vid;
@@ -521,28 +521,33 @@ static void ts_configure(struct agent *a)
 			vid = ts->primary_vid;
 
 		ts_configure_iface(ts, fh->name, vid);
-		if (a->cfg.brcm_setup)
-			strncpy(fif_prefix, "wds", sizeof(fif_prefix) - 1);
-		else
-			strncpy(fif_prefix, "TODO", sizeof(fif_prefix) - 1); /* FIXME: non brcm platforms, one for each bbss */
 
 		add = (a->cfg.guest_isolation && (vid != 1 && vid != ts->primary_vid) ? true : false);
 
 		if (a->cfg.brcm_setup) {
-			int band = 0;
-
-			if (fh->cfg->band == BAND_2)
-				band = 2;
-			else if (fh->cfg->band == BAND_5)
-				band = 5;
-			else if (fh->cfg->band == BAND_6)
-				band = 6;
-			else
-				continue;
+			dbg("/lib/wifi/multiap ts isolate_wds %s %s wds+\n", (add ? "add" : "del"), fh->name);
+			runCmd("/lib/wifi/multiap ts isolate_wds %s %s wds+", (add ? "add" : "del"), fh->name);
+		}
+		else {
+			struct netif_wds *wds = NULL;
 
-			dbg("/lib/wifi/multiap ts isolate %s %d %u %d %s %s\n", (add ? "add" : "del"), ts->primary_vid, fh->cfg->vid, band, fh->name, fif_prefix);
-			runCmd("/lib/wifi/multiap ts isolate %s %d %u %d %s %s", (add ? "add" : "del"), ts->primary_vid, fh->cfg->vid, band, fh->name, fif_prefix);
+			list_for_each_entry(wds, &a->wdslist, list) {
+				dbg("/lib/wifi/multiap ts isolate_wds %s %s %s\n", (add ? "add" : "del"), fh->name, wds->name);
+				runCmd("/lib/wifi/multiap ts isolate_wds %s %s %s", (add ? "add" : "del"), fh->name, wds->name);
+			}
 		}
+
+		if (fh->cfg->band == BAND_2)
+			band = 2;
+		else if (fh->cfg->band == BAND_5)
+			band = 5;
+		else if (fh->cfg->band == BAND_6)
+			band = 6;
+		else
+			continue;
+
+		dbg("/lib/wifi/multiap ts isolate_ap %s %d %u %d %s\n", (add ? "add" : "del"), ts->primary_vid, fh->cfg->vid, band, fh->name);
+		runCmd("/lib/wifi/multiap ts isolate_ap %s %d %u %d %s", (add ? "add" : "del"), ts->primary_vid, fh->cfg->vid, band, fh->name);
 	}
 
 	/* Backhaul stations */
diff --git a/src/script/traffic_separation b/src/script/traffic_separation
index a0c812a320aa29183acf053ae50d3241ba691210..509eab2dcd8cd4f73f7f670466fd601f7a2c0e7f 100755
--- a/src/script/traffic_separation
+++ b/src/script/traffic_separation
@@ -435,7 +435,22 @@ EOF
 		fcctl flush
 	}
 
-	ts_isolate() {
+	ts_isolate_wds() {
+		local action=$1 # add/del
+		local ifname=$2 # guest fbss name
+		local wds=$3 # 4addr interface name or prefix+
+
+		[ -z "$wds" -o -z "$ifname" ] && return
+
+		ebtables -D FORWARD -i $ifname -o $wds -j DROP > /dev/null 2>&1
+		ebtables -D FORWARD -i $wds -o $ifname -j DROP > /dev/null 2>&1
+
+		[ "$action" != "add" ] && return
+		ebtables -A FORWARD -i $ifname -o $wds -j DROP > /dev/null 2>&1
+		ebtables -A FORWARD -i $wds -o $ifname -j DROP > /dev/null 2>&1
+        }
+
+	ts_isolate_ap() {
 		ts_isolate_radio() {
 			local section=$1
 			local action=$2
@@ -452,11 +467,11 @@ EOF
 			config_get apifname "$section" ifname
 			[ "$ifname" = "$apifname" ] && continue # this should never happen
 
-			ebtables -D FORWARD -i $ifname --o $apifname -j DROP > /dev/null 2>&1
+			ebtables -D FORWARD -i $ifname -o $apifname -j DROP > /dev/null 2>&1
 
 			[ "$action" != "add" ] && continue
 
-			ebtables -A FORWARD -i $ifname --o $apifname -j DROP > /dev/null 2>&1
+			ebtables -A FORWARD -i $ifname -o $apifname -j DROP > /dev/null 2>&1
 		}
 		local action=$1
 		shift
@@ -468,10 +483,9 @@ EOF
 		shift
 		local ifname=$1 # guest fbss name
 		shift
-		local ifprefix=$1 # 4addr mode ifname prefix
 		local br_dev="${AL_BRIDGE/-/_}"
 
-		[ -z "$pvid" -o -z "$ifprefix" -o -z "$ifname" ] && return
+		[ -z "$pvid" -o -z "$ifname" ] && return
 
 		config_load mapagent
 		config_foreach ts_isolate_radio ap $action $band $vid $ifname
@@ -481,23 +495,14 @@ EOF
 		json_get_var bk_ifname ifname
 		json_cleanup
 
-		for prefix in $@; do
-			ebtables -D FORWARD -i $ifname --o ${prefix}+ -j DROP > /dev/null 2>&1
-			ebtables -D FORWARD -i ${prefix}+ --o $ifname -j DROP > /dev/null 2>&1
+		# isolate eth interfaces
+		for port in $(uci -q get network.${br_dev}.ports) ; do
+			ebtables -D FORWARD -i $ifname -o $port -j DROP > /dev/null 2>&1
+			ebtables -D FORWARD -i $port -o $ifname -j DROP  > /dev/null 2>&1
 
-			# isolate eth interfaces
-			for port in $(uci -q get network.${br_dev}.ports) ; do
-					ebtables -D FORWARD -i $ifname --o $port -j DROP > /dev/null 2>&1
-					ebtables -D FORWARD -i $port --o $ifname -j DROP  > /dev/null 2>&1
-
-					[ "$action" != "add" -o "$port" = "$bk_ifname" ] && continue
-					ebtables -A FORWARD -i $ifname --o $port -j DROP > /dev/null 2>&1
-					ebtables -A FORWARD -i $port --o $ifname -j DROP > /dev/null 2>&1
-			done
-
-			[ "$action" != "add" ] && continue
-			ebtables -A FORWARD -i $ifname --o ${prefix}+ -j DROP > /dev/null 2>&1
-			ebtables -A FORWARD -i ${prefix}+ --o $ifname -j DROP > /dev/null 2>&1
+			[ "$action" != "add" -o "$port" = "$bk_ifname" ] && continue
+			ebtables -A FORWARD -i $ifname -o $port -j DROP > /dev/null 2>&1
+			ebtables -A FORWARD -i $port -o $ifname -j DROP > /dev/null 2>&1
 		done
 	}
 
@@ -509,7 +514,8 @@ EOF
 		keep) ts_dbg "keep $@"; ts_keep $@;;
 		reload) ts_dbg "reload $@"; ts_reload $@;;
 		cleanup) ts_dbg "cleanup $@"; ts_cleanup $@;;
-		isolate) ts_dbg "isolate $@"; ts_isolate $@;;
+		isolate_ap) ts_dbg "isolate_ap $@"; ts_isolate_ap $@;;
+		isolate_wds) ts_dbg "isolate_wds $@"; ts_isolate_wds $@;;
 		--help|help) ts_usage;;
 		*) ts_usage; exit 1;;
 	esac