diff --git a/src/core/agent.c b/src/core/agent.c
index defc7d25e56c9a0144898a3621017b8bc590fcdd..a6a955addfc61e797002c3c0f4e3ba5e2a431c93 100644
--- a/src/core/agent.c
+++ b/src/core/agent.c
@@ -1226,7 +1226,7 @@ static int wifi_send_sta_report(struct agent *a, const char *vif,
 		return -1;
 
 	//TODO use the cntl ifname and origin address
-	strcpy(ifname, "br-lan");
+	strncpy(ifname, a->cfg.al_bridge, sizeof(ifname));
 	memcpy(origin, a->cntlr_almac, 6);
 
 	/* Here we get need to send the steering report */
@@ -1890,10 +1890,10 @@ static void agent_add_to_bridge(struct agent *a, char *ifname)
 	}
 }
 
-static void wifi_bsta_event_handler(void *c, struct blob_attr *msg)
+static void wifi_bsta_event_handler(void *agent, struct blob_attr *msg)
 {
 	char ifname[16] = {0}, event[16] = {0}, bssid_str[18] = {0};
-	struct agent *a = (struct agent *) c;
+	struct agent *a = (struct agent *) agent;
 	struct blob_attr *tb[3];
 	static const struct blobmsg_policy ev_attr[3] = {
 		[0] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING },
@@ -1911,7 +1911,6 @@ static void wifi_bsta_event_handler(void *c, struct blob_attr *msg)
 	if (!tb[0] || !tb[1] || !tb[2])
 		return;
 
-
 	strncpy(ifname,	blobmsg_data(tb[0]), sizeof(ifname) - 1);
 	strncpy(event, blobmsg_data(tb[1]), sizeof(event) - 1);
 
@@ -1933,19 +1932,51 @@ static void wifi_bsta_event_handler(void *c, struct blob_attr *msg)
 
 		strncpy(bssid_str, blobmsg_data(data[0]),
 				sizeof(bssid_str) - 1);
+
+		hwaddr_aton(bssid_str, bssid);
 	}
 
 	if (add) {
+		int i;
+		time_t now;
+		char pid[8] = {0};
+
+		time(&now);
+
 		bk->connected = true;
-		if (!a->configured) {
-			time(&a->autocfg);
-			uloop_timeout_set(&a->autocfg_dispatcher, 2 * 1000); // 2 seconds
-		} else {
-			trace("Autoconfig already completed, will not trigger" \
-					" again on bsta connection\n");
-			/* if (a->cfg.brcm_setup) */
-				agent_add_to_bridge(a, ifname);
+
+		/** TODO: use pidfile */
+		chrCmd(pid, sizeof(pid), "pidof mapcontroller");
+		if (strlen(pid)) {
+			set_value_by_string("mapcontroller", "controller", "enabled", "0",
+				UCI_TYPE_STRING);
+			trace("found pid %s of mapcontroller, sending SIGHUP\n", pid);
+			kill(atoi(pid), SIGHUP);
+		}
+
+		dbg("|%s:%d| connect event received\n", __func__, __LINE__);
+
+		dbg("|%s:%d| new bssid " MACFMT " old bssid " MACFMT ","\
+				" difftime %.2f(s)\n", __func__, __LINE__,
+				MAC2STR(bssid),	MAC2STR(bk->wan_bssid),
+				difftime(now, bk->connect_t));
+
+		if (memcmp(bssid, bk->wan_bssid, 6) ||
+				difftime(now, bk->connect_t) > 15) {
+			dbg("|%s:%d| new bssid or difftime exceeded 15s,"\
+					"setting radio states to ACTIVE\n",
+					__func__, __LINE__);
+			/** upon connecting to new network - allow radios to be
+			 * reconfigured
+			 */
+			for (i = 0; i < a->num_radios; i++)
+				a->radios[i].state = ACS_ACTIVE;
 		}
+		hwaddr_aton(bssid_str, bk->wan_bssid);
+
+		time(&bk->connect_t);
+		uloop_timeout_set(&a->autocfg_dispatcher, 5 * 1000);
+		agent_add_to_bridge(a, ifname);
 	} else if (del) {
 		bk->connected = false;
 		wifi_mod_bridge(a, ifname, "remove");
@@ -1960,8 +1991,6 @@ static void wifi_bsta_event_handler(void *c, struct blob_attr *msg)
 	if (!p)
 		goto fail_cmdu;
 
-	hwaddr_aton(bssid_str, bssid);
-
 	/**
 	 * if event bssid and tlv target bssid differ, that means steering
 	 * failed, add an error TLV prior to sending response
@@ -2035,7 +2064,7 @@ static void wifi_wps_creds_event_handler(void *c, struct blob_attr *msg)
 			return;
 	}
 
-	uci_reload_services();
+	uci_reload_services("wireless");
 
 	radio = wifi_ifname_to_radio_element(a, ifname);
 	if (!radio)
@@ -2641,7 +2670,7 @@ static void parse_radio(struct ubus_request *req, int type,
 		re->rx_streams = blobmsg_get_u8(tb[3]);
 
 	if (tb[4])
-		re->rx_streams = blobmsg_get_u8(tb[4]);
+		re->tx_streams = blobmsg_get_u8(tb[4]);
 
 	if (tb[5]) {
 		struct blob_attr *cur, *cur1;
@@ -3470,7 +3499,7 @@ static void agent_steering_opp_timeout(struct uloop_timeout *t)
 	char ifname[IFNAMESIZE] = { 0 };
 	uint8_t origin[6] = { 0 };
 
-	strncpy(ifname, "br-lan", sizeof(ifname));
+	strncpy(ifname, a->cfg.al_bridge, sizeof(ifname));
 	memcpy(origin, a->cntlr_almac, 6);
 	send_sta_steer_complete((void *)a, origin, ifname);
 }
@@ -3480,23 +3509,21 @@ static void agent_dispatch_autoconfig(struct uloop_timeout *t)
 {
 	struct agent *a = container_of(t, struct agent, autocfg_dispatcher);
 	int diff;
-	time_t now;
 	struct netif_bk *bk;
 	int i;
 
-	time(&now);
-
-	trace("|%s:%d| Attempting to trigger AP-Autoconfig\n", __func__, __LINE__);
+	trace("|%s:%d| Triggering AP-Autoconfig Search\n", __func__, __LINE__);
 
+#if 0
 	diff = difftime(now, a->autocfg);
 	dbg("|%s:%d| Time since AP-Auotconfig was triggered %d(s)\n", __func__, __LINE__, diff);
 	/* if more than 2 minutes has passed since triggered, stop */
-	if (a->configured && diff > 2 * 60) {
+	if (diff > 2 * 60) {
 		dbg("|%s:%d| Diff exceeds 2 minutes and agent is configured, "\
 				"will not retrigger\n", __func__, __LINE__);
 		return;
 	}
-
+#endif
 	/* Only applicable for bSTA interfaces */
 	list_for_each_entry(bk, &a->bklist, list) {
 		if (!bk->connected)
@@ -3508,14 +3535,14 @@ static void agent_dispatch_autoconfig(struct uloop_timeout *t)
 	for (i = 0; i < a->num_radios; i++) {
 		struct cmdu_cstruct *cmdu;
 		struct wifi_radio_element *radio = &a->radios[i];
-
-		if (radio->onboarded || radio->configured) {
-			dbg("radio %s has been onboarded, don't trigger search\n",
+		int mid;
+#if 0
+		if (/* radio->onboarded || */radio->configured) {
+			dbg("radio %s has been configured, don't trigger search\n",
 					radio->name);
 			continue;
 		}
-
-
+#endif
 		cmdu = agent_gen_ap_autoconfig_search(a, radio, NULL, 0x02);
 		if (!cmdu)
 			continue;
@@ -3523,7 +3550,9 @@ static void agent_dispatch_autoconfig(struct uloop_timeout *t)
 		trace("|%s:%d| Sending Autoconfig Search for radio %s(%s)\n",
 				__func__, __LINE__, radio->name,
 				(radio->band == BAND_2 ? "2.4GHz" : "5GHz"));
-		agent_send_cmdu(a, cmdu);
+		mid = agent_send_cmdu(a, cmdu);
+		if (mid >= 0)
+			radio->mid = mid;
 		map_free_cmdu(cmdu);
 	}
 
@@ -3651,7 +3680,7 @@ int start_agent(void)
 
 		/* TODO: memory management of thread on cleaup */
 		ret = pthread_create(&(tid[0]), NULL, (void *)&brcm_nl_loop,
-				NULL);
+				w->cfg.al_bridge);
 		if (ret) {
 			fprintf(stderr, "Failed to create thread\n");
 			return -1;
@@ -3675,6 +3704,7 @@ int start_agent(void)
 			if (flags & IFF_UP)
 				break;
 
+			trace("Interface %s (found in mapagent UCI) is not up, waiting for it to come up\n", f->name);
 			sleep(2);
 		}
 	}
@@ -3703,8 +3733,7 @@ int start_agent(void)
 	w->sta_steerlist_count = 0;
 	w->sta_steer_req_timer.cb = agent_steering_opp_timeout;
 
-	time(&w->autocfg);
-	uloop_timeout_set(&w->autocfg_dispatcher, 2 * 1000); // 2 seconds
+	uloop_timeout_set(&w->autocfg_dispatcher, 0 * 1000);
 
 	uloop_run();
 
diff --git a/src/core/agent.h b/src/core/agent.h
index f6e5eb6d71727ba63d3b5cb7893f02803d811145..4336fb777b07093b32f1cb4a8bb25a31e25edd41 100644
--- a/src/core/agent.h
+++ b/src/core/agent.h
@@ -201,8 +201,10 @@ struct netif_bk {
 	char name[16];
 	int channel;
 	unsigned char bssid[6];
+	unsigned char wan_bssid[6];
 	char ssid[33];
 	bool connected;
+	time_t connect_t;
 	struct netif_bkcfg *cfg;
 	/* enum netif_type iftype; */
 	struct list_head list;
@@ -347,12 +349,15 @@ struct wsc_data {
 	struct wsc_key *key;
 };
 
+enum acs_state {
+	ACS_ACTIVE,
+	ACS_HEARTBEAT
+};
+
 struct wifi_radio_element {
 	char name[16];
 	uint8_t macaddr[6];
 	uint8_t country_code[2];
-	bool onboarded;
-	bool configured;
 	enum wifi_band band;
 	bool enabled;
 	int anpi;
@@ -368,7 +373,6 @@ struct wifi_radio_element {
 	uint8_t transmit_power_limit; /* set in the channel selection message */
 	uint8_t max_bss;
 
-
 	uint32_t num_supp_opclass;
 	uint32_t num_curr_opclass;
 	uint32_t num_unassoc_sta;
@@ -384,6 +388,11 @@ struct wifi_radio_element {
 	struct wifi_scanres_element *scanlist;
 	struct wifi_unassoc_sta_element *unassoc_stalist;
 
+	/** AP-Autoconfig */
+	enum acs_state state;
+	bool onboarded;
+	bool configured;
+	uint16_t mid;
 	struct wsc_data autconfig;
 };
 
@@ -406,8 +415,6 @@ struct agent {
 	uint8_t almac[6];
 	uint8_t cntlr_almac[6];
 	struct uloop_timeout heartbeat;
-	bool configured;
-	time_t autocfg;
 	struct uloop_timeout autocfg_dispatcher;
 	struct list_head fhlist;
 	struct list_head bklist;
diff --git a/src/core/agent_cmdu_generator.c b/src/core/agent_cmdu_generator.c
index 7d5680a532a209b9db29dfca7ff8f77d8c6e1e03..fd442e8d96e343d78d341b315bd7734bf900156c 100644
--- a/src/core/agent_cmdu_generator.c
+++ b/src/core/agent_cmdu_generator.c
@@ -71,7 +71,7 @@ struct cmdu_cstruct *agent_gen_ap_autoconfig_search(struct agent *a,
 		strncpy(cmdu->intf_name, intf_name,
 				sizeof(cmdu->intf_name) - 1);
 	else
-		strncpy(cmdu->intf_name, "br-lan", sizeof(cmdu->intf_name) - 1);
+		strncpy(cmdu->intf_name, a->cfg.al_bridge, sizeof(cmdu->intf_name) - 1);
 
 	cmdu->message_type = CMDU_TYPE_AP_AUTOCONFIGURATION_SEARCH;
 
@@ -120,7 +120,7 @@ struct cmdu_cstruct *agent_gen_ap_autoconfig_search(struct agent *a,
 	cmdu->num_tlvs++;
 
 	band = wifi_band_to_ieee1905band(radio->band);
-
+	trace("radio band = %d, band = %d\n", radio->band, band);
 	p4 = agent_gen_autoconf_freq_band(a, band);
 	if (!p4)
 		goto fail_p3;
diff --git a/src/core/agent_map.c b/src/core/agent_map.c
index eefabba146dc5b6eab2e29b3c2a325aade73081d..41cccfead27866a75da456b424ac1bae1cd6fcb6 100644
--- a/src/core/agent_map.c
+++ b/src/core/agent_map.c
@@ -135,8 +135,8 @@ int build_ap_autoconfig_wsc(void *agent, struct cmdu_cstruct *rec_cmdu,
 	int tlv_index = 0;
 
 	/* don't trigger autoconfig for bSTA radios */
-	if (radio->onboarded)
-		return -1;
+	//if (radio->onboarded)
+	//	return -1;
 
 	cmdu = (struct cmdu_cstruct *)calloc(1, sizeof(struct cmdu_cstruct));
 	if (!cmdu) {
@@ -150,7 +150,7 @@ int build_ap_autoconfig_wsc(void *agent, struct cmdu_cstruct *rec_cmdu,
 	strncpy(cmdu->intf_name, rec_cmdu->intf_name,
 			sizeof(cmdu->intf_name) - 1);
 
-	p = agent_gen_ap_radio_basic_cap(a, cmdu, idx);
+	p = agent_gen_ap_radio_basic_cap(a, cmdu, radio);
 	if (!p)
 		goto fail_cmdu;
 	cmdu->num_tlvs++;
@@ -531,13 +531,28 @@ int handle_ap_autoconfig_response(void *agent, struct cmdu_cstruct *cmdu)
 {
 	trace("agent: %s: --->\n", __func__);
 	struct agent *a = (struct agent *) agent;
-	struct wifi_radio_element *radio;
+	struct wifi_radio_element *radio = NULL;
 	struct tlv_supp_service *supp_serv;
 	struct tlv_supported_freq_band *supp_freq;
 	char mac_str[18] = {0};
 	bool cntlr = false;
+	uint8_t band;
 	int i;
 
+	trace("%s %d mid = %d\n", __func__, __LINE__, cmdu->message_id);
+
+	/* If MID is not the one we sent, discard response */
+	for (i = 0; i < a->num_radios; i++) {
+		trace("radio %s has mid %d\n", a->radios[i].name, a->radios[i].mid);
+		if (a->radios[i].mid != cmdu->message_id)
+			continue;
+
+		radio = &a->radios[i];
+		break;
+	}
+	if (!radio)
+		return -1;
+
 	supp_serv = (struct tlv_supp_service *) extract_tlv_by_type(cmdu,
 			MAP_TLV_SUPPORTED_SERVICE);
 	if (!supp_serv)
@@ -555,27 +570,40 @@ int handle_ap_autoconfig_response(void *agent, struct cmdu_cstruct *cmdu)
 		return -1;
 	}
 
-	memcpy(a->cntlr_almac, cmdu->origin, 6);
-	if (!hwaddr_ntoa(a->cntlr_almac, mac_str))
-		return -1;
+	dbg("cntlr_almac " MACFMT " origin " MACFMT "\n",
+			MAC2STR(a->cntlr_almac), MAC2STR(cmdu->origin));
 
-	set_value_by_string("mapagent", "agent", "controller_mac", mac_str,
-			UCI_TYPE_STRING);
-	uloop_timeout_cancel(&a->autocfg_dispatcher);
+	/* if it is a new controller, update cntlr_almac and uci */
+	if (memcmp(a->cntlr_almac, cmdu->origin, 6)) {
+		memcpy(a->cntlr_almac, cmdu->origin, 6);
+		if (!hwaddr_ntoa(a->cntlr_almac, mac_str))
+			return -1;
 
-	supp_freq = (struct tlv_supported_freq_band *) extract_tlv_by_type(cmdu,
-			TLV_TYPE_SUPPORTED_FREQ_BAND);
-	if (!supp_freq)
-		return -1;
+		set_value_by_string("mapagent", "agent", "controller_mac", mac_str,
+			UCI_TYPE_STRING);
+		dbg("|%s:%d| new controller found! Activate ACS configuration"\
+				" for all radios\n", __func__, __LINE__);
+		for (i = 0; i < a->num_radios; i++)
+			a->radios[i].state = ACS_ACTIVE;
+	}
 
-	for (i = 0; i < a->num_radios; i++) {
-		uint8_t band;
+	/* return if it was just heartbeat and no activity */
+	if (radio->state == ACS_HEARTBEAT) {
+		/** TODO: active own controller if no controller has been
+		 * observed for certain time period
+		 */
+	} else if (radio->state == ACS_ACTIVE) {
+		supp_freq = (struct tlv_supported_freq_band *) extract_tlv_by_type(cmdu,
+				TLV_TYPE_SUPPORTED_FREQ_BAND);
+		if (!supp_freq)
+			return -1;
 
-		radio = a->radios + i;
 		band = wifi_band_to_ieee1905band(radio->band);
 		if (band != supp_freq->freq_band)
-			continue;
+			return -1;
 
+		dbg("|%s:%d| generate wsc for radio %s\n", __func__, __LINE__,
+				radio->name);
 		build_ap_autoconfig_wsc(a, cmdu, radio, i);
 	}
 
@@ -652,14 +680,6 @@ int wifi_teardown_map_ifaces_by_radio(struct agent *a, char *device)
 		clean_fh(fh);
 	}
 
-	list_for_each_entry_safe(bk, bk_tmp, &a->cfg.bklist, list) {
-		if (strncmp(bk->device, device, sizeof(bk->device) - 1))
-			continue;
-
-		wifi_teardown_iface(bk->name);
-		clean_bk(bk);
-	}
-
 	agent_config_reload(&a->cfg);
 	return 0;
 }
@@ -677,14 +697,6 @@ int wifi_teardown_map_ifaces_by_band(struct agent *a, enum wifi_band band)
 		clean_fh(fh);
 	}
 
-	list_for_each_entry_safe(bk, bk_tmp, &a->cfg.bklist, list) {
-		if (bk->band != band)
-			continue;
-
-		wifi_teardown_iface(bk->name);
-		clean_bk(bk);
-	}
-
 	agent_config_reload(&a->cfg);
 
 	return 0;
@@ -808,6 +820,14 @@ int handle_ap_autoconfig_wsc(void *agent, struct cmdu_cstruct *cmdu)
 	dbg("|%s:%d| found radio = %s\n", __func__, __LINE__, radio->name);
 
 	wifi_teardown_map_ifaces_by_radio(a, radio->name);
+
+	if (radio->onboarded) {
+		dbg("|%s:%d| radio (%s) was onboarded, do not apply m2, apply heartbeat for this radio\n",
+				__func__, __LINE__, radio->name);
+		radio->configured = 1; /* not necessarily true */
+		radio->state = ACS_HEARTBEAT;
+		goto teardown;
+	}
 	/* iterate every TLV_TYPE_WSC, may be multiple */
 	for (i = 0; i < cmdu->num_tlvs; i++) {
 		tlv = cmdu->tlvs[i];
@@ -852,17 +872,21 @@ int handle_ap_autoconfig_wsc(void *agent, struct cmdu_cstruct *cmdu)
 						MAC2STR(bssid));
 				wifi_teardown_map_ifaces_by_radio(a,
 						radio->name);
+				uci_set_wireless_interface_option("mapagent",
+						"wifi-radio", "device",
+						radio->name, "configured", "0");
 				goto teardown;
 			}
 
-			rv = uci_apply_m2(ifname, radio->name, out.output.ssid,
-					out.output.auth_types,
+			rv = uci_apply_m2(&a->cfg, ifname, radio->name,
+					out.output.ssid, out.output.auth_types,
 					out.output.encryption_types,
 					out.output.network_key,
 					out.output.mapie, radio->band,
 					out.output.bridge, out.output.proto,
 					out.output.vid, out.output.br_ip,
-					out.output.bk_ssid, out.output.bk_key);
+					out.output.bk_ssid, out.output.bk_key,
+					radio->onboarded);
 			if (rv) {
 				err("Failure to process M2, tearing down all "\
 						" MAP interfaces"\
@@ -872,26 +896,30 @@ int handle_ap_autoconfig_wsc(void *agent, struct cmdu_cstruct *cmdu)
 						radio->name);
 				goto teardown;
 			}
+
 			break;
 		}
 		default:
 			break;
-
 		}
 	}
+
 	uci_set_wireless_interface_option("mapagent", "wifi-radio", "device",
 			radio->name, "configured", "1");
+	dbg("|%s:%d| radio (%s) was configured! Apply heartbeat for this radio\n",
+				__func__, __LINE__, radio->name);
 	radio->configured = 1;
-	//a->configured = true;
 	wifi_reorder_interfaces(&a->cfg);
 	agent_config_reload(&a->cfg);
+	radio->state = ACS_HEARTBEAT;
 	//uci_apply_wps_credentials(&a->cfg, radio->band);
 teardown:
 	// TODO: freeing from here risks freeing an updated frame
 	agent_free_wsc_data(&radio->autconfig);
 	radio->autconfig.key = NULL;
 	radio->autconfig.m1_frame = NULL;
-	uci_reload_services();
+	uci_reload_services("wireless");
+	//uci_reload_services("dhcp");
 	return 0;
 }
 
@@ -1157,7 +1185,7 @@ int handle_ap_caps_query(void *agent, struct cmdu_cstruct *rec_cmdu)
 	for (i = 0; i < a->num_radios; i++) {
 		struct tlv_ap_radio_basic_cap *p;
 
-		p = agent_gen_ap_radio_basic_cap(a, cmdu, i);
+		p = agent_gen_ap_radio_basic_cap(a, cmdu, &a->radios[i]);
 		if (!p)
 			continue;
 		//cmdu->num_tlvs++;
@@ -3207,8 +3235,6 @@ int agent_send_cmdu(struct agent *a, struct cmdu_cstruct *cmdu)
 	int ret = 0;
 	size_t i;
 	uint32_t id;
-	//uint8_t is_store_mid = 1;
-	//struct ieee1905_cmdu_msg *cmsg = NULL;
 
 	trace("|%s:%d| Entry\n", __func__, __LINE__);
 
@@ -3280,19 +3306,7 @@ int agent_send_cmdu(struct agent *a, struct cmdu_cstruct *cmdu)
 		goto out;
 	}
 
-	//TODO: improve /////////////////////////
-	//if (is_store_mid) {
-	//	cmsg = &priv->cmsg;
-	//	for (i = 0; i < MAX_CMDU_MSG; i++) {
-	//		if (cmsg->msg_id[i] == -1) {
-	//			cmsg->msg_id[i] = msgid;
-	//			cmsg->msg_ts[i] = time(NULL);
-	//			break;
-	//		}
-	//	}
-	//}
-	/////////////////////////////////////////
-
+	ret = msgid;
 out:
 	blob_buf_free(&b);
 
diff --git a/src/core/agent_tlv_generator.c b/src/core/agent_tlv_generator.c
index 7ca4c85944b130089316b813fa3dcde3471be03c..946e380020a65034de499c7654a7a15d7e314692 100644
--- a/src/core/agent_tlv_generator.c
+++ b/src/core/agent_tlv_generator.c
@@ -98,14 +98,11 @@ struct tlv_ap_cap *agent_gen_ap_caps(struct agent *a,
 }
 
 struct tlv_ap_radio_basic_cap *agent_gen_ap_radio_basic_cap(struct agent *a,
-		struct cmdu_cstruct *cmdu, uint32_t radio_index)
+		struct cmdu_cstruct *cmdu, struct wifi_radio_element *radio)
 {
 	uint32_t j;
-	struct wifi_radio_element *radio;
 	struct tlv_ap_radio_basic_cap *p;
 
-	radio = a->radios + radio_index;
-
 	p = (struct tlv_ap_radio_basic_cap *)calloc(1,
 			sizeof(struct tlv_ap_radio_basic_cap));
 
diff --git a/src/core/agent_tlv_generator.h b/src/core/agent_tlv_generator.h
index f3ff1d17b3b63bb98ee5359a94281aa80c80ca55..cd2587a25d439c894d9595c633fd47262c5edb36 100644
--- a/src/core/agent_tlv_generator.h
+++ b/src/core/agent_tlv_generator.h
@@ -20,7 +20,7 @@ struct tlv_ap_ht_cap *agent_gen_ap_ht_caps(struct agent *a,
 struct tlv_ap_cap *agent_gen_ap_caps(struct agent *a,
 		struct cmdu_cstruct *cmdu);
 struct tlv_ap_radio_basic_cap *agent_gen_ap_radio_basic_cap(struct agent *a,
-		struct cmdu_cstruct *cmdu, uint32_t radio_index);
+		struct cmdu_cstruct *cmdu, struct wifi_radio_element *radio);
 struct tlv_ap_vht_cap *agent_gen_ap_vht_caps(struct agent *a,
 		struct cmdu_cstruct *cmdu, uint32_t radio_index);
 struct tlv_profile2_ap_cap *agent_gen_profile2_ap_cap(struct agent *a);
diff --git a/src/core/config.c b/src/core/config.c
index 46e5c1921a278b313981d7cbfe924910dbdc4ea1..d2e17bde8131671baf2ca9eea39087b60fe0f1ba 100644
--- a/src/core/config.c
+++ b/src/core/config.c
@@ -90,7 +90,7 @@ int set_value_by_string(const char *package, const char *section,
 	uci_commit(ctx, &ptr.p, false);
 
 	uci_free_context(ctx);
-	return -1;
+	return rv;
 }
 
 struct uci_section *config_get_section(struct uci_context *ctx,
@@ -200,7 +200,7 @@ int wifi_set_iface_bssid(const char *ifname, uint8_t *bssid)
 
 	uci_commit(ctx, &pkg, false);
 
-	uci_reload_services();
+	uci_reload_services("wireless");
 out_pkg:
 	uci_unload(ctx, pkg);
 	uci_free_context(ctx);
@@ -585,14 +585,14 @@ static int ubus_call(const char *object, const char *method,
 	return UBUS_STATUS_OK;
 }
 
-bool uci_reload_services(void)
+bool uci_reload_services(char *services)
 {
 	struct blob_buf bb;
-	int rv;
+	int rv = 0;
 	memset(&bb, 0, sizeof(struct blob_buf));
 	blob_buf_init(&bb, 0);
 
-	blobmsg_add_string(&bb, "config", "wireless");
+	blobmsg_add_string(&bb, "config", services);
 
 	rv = ubus_call("uci", "commit", &bb, NULL, NULL);
 
@@ -600,6 +600,8 @@ bool uci_reload_services(void)
 	//if (!ubus_call("uci", "reload_config", &bb, NULL, NULL))
 	//	return true;
 
+	//ubus_call("uci", "reload_config", &bb, NULL, NULL);
+
 	blob_buf_free(&bb);
 
 	return false;
@@ -652,21 +654,24 @@ int uci_apply_wps_credentials(struct agent_config *cfg, enum wifi_band band)
 
 
 /* TODO: batch the changes arther than commit oneby one */
-int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid,
-		uint16_t auth_type, uint16_t encryption_type,
+int uci_apply_m2(struct agent_config *cfg, char *interface_name, char *device,
+		uint8_t *ssid, uint16_t auth_type, uint16_t encryption_type,
 		uint8_t *network_key, uint8_t mapie, uint8_t band,
 		uint8_t *bridge, uint8_t *proto, uint8_t vid, uint32_t br_ip,
-		uint8_t *bk_ssid, uint8_t *bk_key)
+		uint8_t *bk_ssid, uint8_t *bk_key, bool onboarded)
 {
 	bool ret;
 	char auth_type_str[20] = {0};
 	char multiap_str[2] = {0};
 	uint8_t multi_ap = 0;
-	bool bk_mode;
 	char band_str[2] = {0};
 	char agent_section[16] = {0};
 	char ipaddr_str[INET_ADDRSTRLEN] = {0};
 
+	/* step past br- prefix if present*/
+	if (!strncmp("br-", bridge, 3))
+		bridge += 3;
+
 	inet_ntop(AF_INET, &br_ip, ipaddr_str, INET_ADDRSTRLEN);
 
 	dbg("Applying WSC configuration (%s):\n", interface_name);
@@ -687,7 +692,6 @@ int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid,
 
 	multi_ap |= (BIT(5, mapie) << 1);
 	multi_ap |= BIT(6, mapie);
-	bk_mode = BIT(6, mapie);
 
 	snprintf(multiap_str, sizeof(multiap_str), "%d", multi_ap);
 
@@ -706,9 +710,7 @@ int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid,
 		return M2_PROCESS_ERROR;
 	}
 
-
-	strncpy(agent_section, (bk_mode ? UCI_BK_AGENT : UCI_FH_AGENT),
-			sizeof(agent_section));
+	strncpy(agent_section, UCI_FH_AGENT, sizeof(agent_section));
 
 	// Set uci in agent
 	ret = uci_check_wifi_iface(UCI_AGENT, interface_name,
@@ -727,8 +729,6 @@ int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid,
 	else /* TODO: 60 */
 		return M2_PROCESS_ERROR;
 
-	uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname",
-			interface_name, "band",	band_str);
 	uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname",
 			interface_name, "band",	band_str);
 	uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname",
@@ -739,13 +739,13 @@ int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid,
 			interface_name,	"key", network_key);
 	uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname",
 			interface_name,	"encryption", auth_type_str);
-	if (bk_mode) {
+	if (multi_ap & 0x01) {
 		char disallow_str[2] = {0};
 
 		snprintf(disallow_str, sizeof(disallow_str), "%d",
 				((mapie >> 2) & 0x03));
 		uci_set_wireless_interface_option(UCI_AGENT,
-				UCI_BK_AGENT, "ifname",
+				agent_section, "ifname",
 				interface_name,
 				"disallow_bsta", disallow_str);
 	}
@@ -779,7 +779,10 @@ int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid,
 	uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname",
 			interface_name, "multi_ap_backhaul_ssid", bk_ssid);
 
-	if (bk_mode) {
+	if (onboarded)
+		uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname",
+			interface_name, "disabled", "1");
+	if (multi_ap == 0x01) {
 		uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE,
 			"ifname", interface_name, "hidden", "1");
 	} else {
@@ -789,6 +792,11 @@ int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid,
 			UCI_WLAN_IFACE,	"ifname", interface_name,
 			"wps_pushbutton", "1");
 	}
+
+	/* TODO: don't support guest network for the moment */
+	//uci_add_dhcp(bridge);
+	//uci_add_fw(cfg, bridge);
+
 	return M2_PROCESS_OK;
 }
 /* end of functions taken from ieee1905d */
@@ -1233,6 +1241,7 @@ static int agent_config_get_wifi_agent(struct agent_config *a,
 		A_CNTLR_MAC,
 		A_EXCLUDE,
 		A_EXCLUDE_BTM,
+		A_AL_BRIDGE,
 		NUM_POLICIES
 	};
 	const struct uci_parse_option opts[] = {
@@ -1244,6 +1253,7 @@ static int agent_config_get_wifi_agent(struct agent_config *a,
 		{ .name = "controller_macaddr", .type = UCI_TYPE_STRING },
 		{ .name = "exclude", .type = UCI_TYPE_LIST },
 		{ .name = "exclude_btm", .type = UCI_TYPE_LIST },
+		{ .name = "al_bridge", .type = UCI_TYPE_STRING },
 	};
 	struct uci_option *tb[NUM_POLICIES];
 
@@ -1292,6 +1302,14 @@ static int agent_config_get_wifi_agent(struct agent_config *a,
 		dbg("\n");
 	}
 
+	if (tb[A_AL_BRIDGE]) {
+		const char *iface;
+
+		iface = tb[A_AL_BRIDGE]->v.string;
+		strncpy(a->al_bridge, iface, sizeof(a->al_bridge) - 1);
+	} else /* Default to br-lan if non-specfied */
+		strncpy(a->al_bridge, "br-lan", sizeof(a->al_bridge) - 1);
+
 	return 0;
 }
 
@@ -1798,7 +1816,7 @@ int config_generate_radio(struct agent_config *cfg, struct uci_context *ctx,
 }
 
 int config_generate_bsta_agent(struct agent_config *cfg, struct uci_context *ctx,
-		char *device, char *ifname,
+		const char *device, const char *ifname,
 		uint8_t band)
 {
 	struct uci_section *s;
@@ -1907,7 +1925,7 @@ bool config_find_bsta_agent(struct agent_config *cfg, struct uci_context *ctx,
 }
 
 struct uci_section *config_find_bsta_wireless(struct agent_config *cfg,
-		struct uci_context *ctx, struct uci_package *pkg, char *device)
+		struct uci_context *ctx, struct uci_package *pkg, const char *device)
 {
 	struct uci_element *e;
 	int rv;
@@ -2184,3 +2202,107 @@ int uci_set_bridge(char *config, char *bridge, char *proto, char *ipaddress)
 	uci_free_context(ctx);
 	return false;
 }
+
+int uci_add_dhcp(char *iface)
+{
+	struct uci_context *ctx = NULL;
+	struct uci_package *pkg;
+	struct uci_element *e;
+	struct uci_section *section = NULL;
+	struct uci_ptr ptr = {0};
+
+	/** if bridge starts with br prefix, step past */
+	if (!strncmp(iface, "br-", 3))
+		iface += 3;
+
+	pkg = uci_load_pkg(&ctx, "dhcp");
+	if (!pkg)
+		return -1;
+
+	uci_foreach_element(&pkg->sections, e) {
+		struct uci_section *s = uci_to_section(e);
+
+		if (strncmp(s->e.name, iface, 16))
+			continue;
+
+		trace("Existing section found for ifname %s\n", iface);
+		goto out;
+	}
+
+	trace("Adding DHCP section for ifname %s\n", iface);
+
+	ptr.p = pkg;
+	ptr.section = iface;
+	ptr.value = "dhcp";
+	ptr.option = NULL;
+	uci_set(ctx, &ptr);
+	section = ptr.s;
+
+	set_value(ctx, pkg, section, "interface", iface, UCI_TYPE_STRING);
+	set_value(ctx, pkg, section, "start", "100", UCI_TYPE_STRING);
+	set_value(ctx, pkg, section, "limit", "150", UCI_TYPE_STRING);
+	set_value(ctx, pkg, section, "leasetime", "1h", UCI_TYPE_STRING);
+	set_value(ctx, pkg, section, "dhcpv6", "server", UCI_TYPE_STRING);
+	set_value(ctx, pkg, section, "ra", "server", UCI_TYPE_STRING);
+
+	uci_commit(ctx, &pkg, false);
+out:
+	uci_unload(ctx, pkg);
+	uci_free_context(ctx);
+	return false;
+}
+
+int uci_add_fw(struct agent_config *cfg, char *iface)
+{
+	struct uci_context *ctx = NULL;
+	struct uci_package *pkg;
+	struct uci_element *e;
+	struct uci_section *section = NULL;
+	int rv;
+
+	/** if bridge starts with br prefix, step past */
+	if (!strncmp(iface, "br-", 3))
+		iface += 3;
+
+	pkg = uci_load_pkg(&ctx, "firewall");
+	if (!pkg)
+		return -1;
+
+	section = config_get_section(ctx, pkg, "zone", "name", iface);
+	if (!section) {
+		trace("No fw section found for %s\n", iface);
+		rv = uci_add_section(ctx, pkg, "zone", &section);
+		if (rv)
+			goto out_pkg;
+
+		set_value(ctx, pkg, section, "name", iface, UCI_TYPE_STRING);
+		set_value(ctx, pkg, section, "network", iface, UCI_TYPE_LIST);
+		set_value(ctx, pkg, section, "input", "ACCEPT", UCI_TYPE_STRING);
+		set_value(ctx, pkg, section, "output", "ACCEPT", UCI_TYPE_STRING);
+		set_value(ctx, pkg, section, "forward", "ACCEPT", UCI_TYPE_STRING);
+		rv = uci_save(ctx, pkg);
+		if (rv)
+			goto out_pkg;
+		uci_commit(ctx, &pkg, false);
+	}
+
+	section = config_get_section(ctx, pkg, "forwarding", "src", iface);
+	if (!section) {
+		//section = config_add_section(ctx, pkg, "firewall", "forwarding", "src", iface);
+		//if (!section)
+		//	goto out;
+		rv = uci_add_section(ctx, pkg, "forwarding", &section);
+		if (rv)
+			goto out_pkg;
+
+		set_value(ctx, pkg, section, "src", iface, UCI_TYPE_STRING);
+		set_value(ctx, pkg, section, "dest", cfg->al_bridge, UCI_TYPE_STRING);
+		uci_commit(ctx, &pkg, false);
+	}
+
+out_pkg:
+	uci_unload(ctx, pkg);
+	uci_free_context(ctx);
+	return false;
+}
+
diff --git a/src/core/config.h b/src/core/config.h
index 1c8d3d64782b236dfa9f83e6368db69451c16e06..60844c767bb82c056c97ed0346032aa65415f3eb 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -157,6 +157,7 @@ struct agent_config {
 	bool brcm_setup;
 	bool configured;
 	uint8_t cntlr_almac[6];
+	char al_bridge[16];
 
 	struct policy_cfg *pcfg;  /* policy section */
 	struct uloop_timeout metric_report_timer;
@@ -166,7 +167,6 @@ struct agent_config {
 
 	/** STAs excluded from BTM req steering; list of stax structs */
 	struct list_head steer_btm_excludelist;
-
 };
 
 #if 0
@@ -192,7 +192,7 @@ int set_value_by_string(const char *package, const char *section,
 		const char *key, const char *value, enum uci_option_type type);
 struct uci_section *config_get_iface_section(struct uci_context *ctx,
 		struct uci_package *pkg, const char *type, const char *ifname);
-bool uci_reload_services(void);
+bool uci_reload_services(char *services);
 struct uci_package *uci_load_pkg(struct uci_context **ctx, const char *config);
 int wifi_set_iface_bssid(const char *ifname, uint8_t *bssid);
 char *uci_get_bridge(char *ifname, char *bridge);
@@ -239,14 +239,16 @@ int clean_all_bk(struct agent_config *cfg);
 void clean_fh(struct netif_fhcfg *p);
 int clean_all_fh(struct agent_config *cfg);
 
-int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid,
-		uint16_t auth_type, uint16_t encryption_type,
+int uci_apply_m2(struct agent_config *cfg, char *interface_name, char *device,
+		uint8_t *ssid, uint16_t auth_type, uint16_t encryption_type,
 		uint8_t *network_key, uint8_t mapie, uint8_t band,
 		uint8_t *bridge, uint8_t *proto, uint8_t vid, uint32_t br_ip,
-		uint8_t *bk_ssid, uint8_t *bk_key);
+		uint8_t *bk_ssid, uint8_t *bk_key, bool onboaded);
 int uci_apply_wps_credentials(struct agent_config *cfg, enum wifi_band band);
 int wifi_reorder_interfaces_by_device(struct agent_config *a,
 		struct uci_context *ctx, struct uci_package *pkg, char *device);
 int wifi_reorder_interfaces(struct agent_config *a);
 int uci_set_bridge(char *config, char *bridge, char *proto, char *ipaddress);
+int uci_add_dhcp(char *interface);
+int uci_add_fw(struct agent_config *cfg, char *interface);
 #endif
diff --git a/src/utils/brcm_nl.c b/src/utils/brcm_nl.c
index 80f1aea45697057286c6d4d8ae17109793d7ad44..1fc46cb3a3afbac7bd43e4227618cde845259494 100644
--- a/src/utils/brcm_nl.c
+++ b/src/utils/brcm_nl.c
@@ -65,12 +65,6 @@ int if_updown(const char *ifname, bool up)
 	return 0;
 }
 
-static bool get_bridge(char *ifname, char *bridge)
-{
-	strncpy(bridge, "br-lan", 15);
-	return true;
-}
-
 static int func(struct nl_msg *msg, void *arg)
 {
 	struct nlmsghdr *nlh = nlmsg_hdr(msg);
@@ -81,7 +75,7 @@ static int func(struct nl_msg *msg, void *arg)
 		{
 			struct ifinfomsg *ifi;
 			char ifname[16] = {0};
-			char bridge[16] = {0};
+			char *bridge = (char *) arg;
 			int ret;
 
 			ifi = NLMSG_DATA(nlh);
@@ -99,8 +93,8 @@ static int func(struct nl_msg *msg, void *arg)
 			if (!strstr(ifname, "wds"))
 				break;
 
-			if (!get_bridge(ifname, bridge))
-				break;
+
+			printf("Adding interface %s to bridge %s!\n", ifname, bridge);
 
 			/* add wds iface to bridge */
 			ret = br_addif(bridge, ifname);
@@ -124,7 +118,7 @@ static int func(struct nl_msg *msg, void *arg)
 	return 0;
 }
 
-int brcm_nl_loop(void)
+int brcm_nl_loop(void *arg)
 {
 	struct nl_sock *sk;
 
@@ -134,7 +128,7 @@ int brcm_nl_loop(void)
 
 	nl_socket_disable_seq_check(sk);
 
-	nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, func, NULL);
+	nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, func, arg);
 
 	nl_connect(sk, NETLINK_ROUTE);
 	nl_socket_add_memberships(sk, RTNLGRP_LINK, 0);
diff --git a/src/utils/debug.c b/src/utils/debug.c
index b2a320b939d78ed358bb617df077fdf0f1dabb86..061df0a5785187ce36f6c08849b1318874349ebc 100644
--- a/src/utils/debug.c
+++ b/src/utils/debug.c
@@ -196,8 +196,6 @@ void log_test(int level, void *var, int len)
 
 	btostr(var, len, bstr);
 
-	printf("%s %d agent bstr = %s\n", __func__, __LINE__, bstr);
-
 	fprintf(testfile, "%s\n", bstr);
 	fflush(testfile);
 	free(bstr);