diff --git a/src/core/cntlr.c b/src/core/cntlr.c
index 5ecdc0e8725dea09f7b0239d9f90bf86653366f7..728f94a81c7dfaf3f58187430ec66f1026578788 100644
--- a/src/core/cntlr.c
+++ b/src/core/cntlr.c
@@ -2017,8 +2017,8 @@ static void cntlr_signal_periodic_run(struct uloop_timeout *t)
 				if ((diff & CONFIG_DIFF_AGENT_POLICY) && !p->is_policy_diff)
 					continue;
 
-				cmdu = cntlr_gen_policy_config_req(c, NULL, p,
-						num_radio, radio_id, num_bk, bk_id);
+				cmdu = cntlr_gen_policy_config_req(c, p, num_radio,
+						radio_id, num_bk, bk_id);
 				if (cmdu) {
 					send_cmdu(c, cmdu);
 					cmdu_free(cmdu);
diff --git a/src/core/cntlr_cmdu_generator.c b/src/core/cntlr_cmdu_generator.c
index 9254e6792be70f7e613d5940ef29b4911e5e3f15..5ab943eb065972794162f25544da6dd2a6dd37a9 100644
--- a/src/core/cntlr_cmdu_generator.c
+++ b/src/core/cntlr_cmdu_generator.c
@@ -261,105 +261,75 @@ out:
 }
 
 struct cmdu_buff *cntlr_gen_policy_config_req(struct controller *c,
-		char *intf_name, struct agent_policy *found,
+		struct agent_policy *found,
 		int num_radio, uint8_t *radiolist,
 		int num_bss, uint8_t *bsslist)
 {
+	int i, ret;
+	uint16_t mid = 0;
+	struct cmdu_buff *frm;
+
+	frm = cmdu_alloc_simple(CMDU_POLICY_CONFIG_REQ, &mid);
+	if (!frm) {
+		dbg("%s: -ENOMEM\n", __func__);
+		return NULL;
+	}
+
+	memcpy(frm->origin, found->agent_id, 6);
+
+	/* Steering Policy TLV */
+	ret = cntlr_gen_steering_policy(c, found, frm,
+			num_radio, radiolist);
+	if (ret)
+		goto out;
+
+	/* Metric Reporting Policy TLV */
+	ret = cntlr_gen_metric_report_policy(c, found, frm,
+			num_radio, radiolist);
+	if (ret)
+		goto out;
+
+// #ifdef PROFILE2
+	/* Default 802.1Q setting TLV */
+	ret = cntlr_gen_8021q_settings(c, frm, found);
+	if (ret)
+		goto out;
+
+	/* Traffic Seperation Policy TLV */
+#if 0
+	ret = cntlr_gen_traffic_sep_policy(c, frm);
+	if (ret)
+		goto out;
+#endif
+
+	/* Channel Scan Reporting Policy TLV */
+	ret = cntlr_gen_ch_scan_rep_policy(c, found, frm);
+	if (ret)
+		goto out;
+
+	/* Unsuccessful Association Policy TLV */
+	ret = cntlr_gen_unsuccess_assoc_policy(c, found, frm);
+	if (ret)
+		goto out;
+
+	/* Backhaul BSS Configuration TLV */
+	for (i = 0; i < num_bss; i++) {
+		uint8_t bssid[6] = {0};
+
+		memcpy(bssid, &bsslist[i*6], 6);
+		ret = cntlr_gen_backhaul_bss_config(c, found, frm, bssid);
+		if (ret)
+			goto out;
+	}
+// #endif
+
+	cmdu_put_eom(frm);
+
+	return frm;
+out:
+	cmdu_free(frm);
+
 	return NULL;
-//	struct cmdu_cstruct *cmdu;
-//	int tlv_index = 0;
-//	int i;
-//	/* TLVs */
-//	struct tlv_steering_policy *p1;
-//	struct tlv_metric_report_policy *p2;
-//	/* Map-2 tlvs */
-//// #ifdef PROFILE2
-//	struct tlv_default_8021q_settings *p3;
-//	struct tlv_traffic_sep_policy *p4;
-//	struct tlv_ch_scan_rep_policy *p5;
-//	struct tlv_unsuccess_assoc_policy *p6;
-//	struct tlv_backhaul_bss_config *p7;
-//// #endif
-//
-//	cmdu = (struct cmdu_cstruct *)calloc(1, sizeof(struct cmdu_cstruct));
-//	if (!cmdu) {
-//		trace("failed to malloc cmdu\n");
-//		return NULL;
-//	}
-//
-//	cmdu_defaults(c, cmdu, found->agent_id, intf_name, CMDU_POLICY_CONFIG_REQ);
-//
-//	cmdu->num_tlvs = 2;
-//// #ifdef PROFILE2
-//	cmdu->num_tlvs += 4 + num_bss;
-//// #endif
-//
-//	cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs, sizeof(uint8_t *));
-//	if (!cmdu->tlvs) {
-//		cmdu->num_tlvs = 0;
-//		goto fail_cmdu;
-//	}
-//
-//	/* Steering Policy TLV */
-//	p1 = cntlr_gen_steering_policy(c, found, cmdu, num_radio, radiolist);
-//	if (!p1)
-//		goto fail_cmdu;
-//
-//	cmdu->tlvs[tlv_index++] = (uint8_t *)p1;
-//
-//	/* Metric Reporting Policy TLV */
-//	p2 = cntlr_gen_metric_report_policy(c, found, cmdu, num_radio, radiolist);
-//	if (!p2)
-//		goto fail_cmdu;
-//
-//	cmdu->tlvs[tlv_index++] = (uint8_t *)p2;
-//
-//// #ifdef PROFILE2
-//	/* Default 802.1Q setting TLV */
-//	p3 = cntlr_gen_8021q_settings(c, found);
-//	if (!p3)
-//		goto fail_cmdu;
-//
-//	cmdu->tlvs[tlv_index++] = (uint8_t *)p3;
-//
-//	/* Traffic Seperation Policy TLV */
-//	p4 = cntlr_gen_traffic_sep_policy(c, cmdu);
-//	if (!p4)
-//		goto fail_cmdu;
-//
-//	cmdu->tlvs[tlv_index++] = (uint8_t *)p4;
-//
-//	/* Channel Scan Reporting Policy TLV */
-//	p5 = cntlr_gen_ch_scan_rep_policy(c, found, cmdu);
-//	if (!p5)
-//		goto fail_cmdu;
-//
-//	cmdu->tlvs[tlv_index++] = (uint8_t *)p5;
-//
-//	/* Unsuccessful Association Policy TLV */
-//	p6 = cntlr_gen_unsuccess_assoc_policy(c, found, cmdu);
-//	if (!p6)
-//		goto fail_cmdu;
-//
-//	cmdu->tlvs[tlv_index++] = (uint8_t *)p6;
-//
-//	/* Backhaul BSS Configuration TLV */
-//	for (i = 0; i < num_bss; i++) {
-//		uint8_t bssid[6] = {0};
-//
-//		memcpy(bssid, &bsslist[i*6], 6);
-//		p7 = cntlr_gen_backhaul_bss_config(c, found, cmdu, bssid);
-//		if (!p7)
-//			goto fail_cmdu;
-//
-//		cmdu->tlvs[tlv_index++] = (uint8_t *)p7;
-//	}
-//// #endif
-//
-//	return cmdu;
-//fail_cmdu:
-//	map_free_cmdu(cmdu);
-//	return NULL;
 }
 
 struct cmdu_buff *cntlr_gen_sta_metric_query(struct controller *c,
diff --git a/src/core/cntlr_cmdu_generator.h b/src/core/cntlr_cmdu_generator.h
index 0013b7a9cd09ceaf26013ec3f44d585bda3b217c..0cb9f4e76eee5ec71f3bf821ad7e38931093b7e4 100644
--- a/src/core/cntlr_cmdu_generator.h
+++ b/src/core/cntlr_cmdu_generator.h
@@ -29,7 +29,7 @@ struct cmdu_buff *cntlr_gen_ap_metrics_query(struct controller *c,
 		uint8_t *origin, int num_bss, uint8_t *bsslist,
 		int num_radio, uint8_t *radiolist);
 struct cmdu_buff *cntlr_gen_policy_config_req(struct controller *c,
-		char *intf_name, struct agent_policy *found,
+		struct agent_policy *found,
 		int num_radio, uint8_t *radiolist,
 		int num_bss, uint8_t *bsslist);
 struct cmdu_buff *cntlr_gen_sta_metric_query(struct controller *c,
diff --git a/src/core/cntlr_map_debug.c b/src/core/cntlr_map_debug.c
index 6019ed52c835effda9b084a6db0a98865d89bb36..7a743187b6ad659564ffed7f3076254b517b31a4 100644
--- a/src/core/cntlr_map_debug.c
+++ b/src/core/cntlr_map_debug.c
@@ -1202,64 +1202,55 @@ int debug_assoc_status_notification(void *cntlr, struct cmdu_buff *cmdu)
 
 int debug_tunneled_message(void *cntlr, struct cmdu_buff *cmdu)
 {
+	struct tlv *tv[3][16] = { 0 };
+	struct tlv_policy tunnel_policy[] = {
+		[0] = { .type = MAP_TLV_SOURCE_INFO, .present = TLV_PRESENT_ONE },
+		[1] = { .type = MAP_TLV_TUNNELED_MSG_TYPE, .present = TLV_PRESENT_ONE },
+		[2] = { .type = MAP_TLV_TUNNELED, .present = TLV_PRESENT_ONE }
+	};
+
+	trace("%s: --->\n", __func__);
+	trace("parsing tunnel message |" MACFMT "\n",
+			MAC2STR(cmdu->origin));
+
+	cmdu_parse_tlvs(cmdu, tv, tunnel_policy, 3);
+
+	if (tv[0][0]) {
+		struct tlv_source_info *p =
+			(struct tlv_source_info *) tv[0][0]->data;
+
+		trace("\tmac: " MACFMT "\n", MAC2STR(p->macaddr));
+	}
+
+	if (tv[1][0]) {
+		struct tlv_tunnel_msg_type *p =
+			(struct tlv_tunnel_msg_type *) tv[1][0]->data;
+
+		trace("\ttunnel_protocol_type: %d\n", p->type);
+	}
+
+	if (tv[2][0]) {
+		struct tlv *t = (struct tlv *)tv[2][0];
+		char *framestr = NULL;
+		uint16_t frame_len;
+		struct tlv_tunneled *p =
+			(struct tlv_tunneled *) tv[2][0]->data;
+
+		frame_len = BUF_GET_BE16(t->len);
+		trace("\tlen: %d\n", frame_len);
+		if (frame_len > 0) {
+			framestr = calloc((2 * frame_len) + 1,
+					sizeof(char));
+		}
+
+		if (framestr) {
+			btostr(p->frame, frame_len, framestr);
+			trace("\tframe_body: %s\n", framestr);
+			free(framestr);
+		}
+	}
+
 	return 0;
-//	int i;
-//	uint8_t *tlv;
-//
-//	trace("%s: --->\n", __func__);
-//	trace("parsing tunnel message |" MACFMT "|CMDU: %s\n",
-//			MAC2STR(cmdu->origin),
-//			map_stringify_cmdu_type(cmdu->message_type));
-//
-//	for (i = 0; i < cmdu->num_tlvs; i++) {
-//		tlv = (uint8_t *)cmdu->tlvs[i];
-//		trace("TLV: %s\n", map_stringify_tlv_type(*tlv));
-//		switch (*tlv) {
-//		case MAP_TLV_SOURCE_INFO:
-//			{
-//				struct tlv_source_info *p =
-//					(struct tlv_source_info *)tlv;
-//
-//				trace("\tmac: " MACFMT "\n", MAC2STR(p->mac));
-//				break;
-//			}
-//		case MAP_TLV_TUNNELED_MSG_TYPE:
-//			{
-//				struct tlv_tunnel_msg_type *p =
-//					(struct tlv_tunnel_msg_type *)tlv;
-//
-//				trace("\ttunnel_protocol_type: %d\n",
-//						p->tunnel_protocol_type);
-//				break;
-//			}
-//		case MAP_TLV_TUNNELED:
-//			{
-//				char *framestr = NULL;
-//				int frame_len;
-//				struct tlv_tunneled *p = (struct tlv_tunneled *)tlv;
-//
-//				trace("\ttlv_len: %d\n", p->tlv_len);
-//				if (p->tlv_len > 0) {
-//					frame_len = (2 * p->tlv_len) + 1;
-//					framestr = calloc(frame_len, sizeof(char));
-//				}
-//
-//				if (framestr) {
-//					btostr(p->frame_body, p->tlv_len, framestr);
-//					trace("\tframe_body: %s\n", framestr);
-//					free(framestr);
-//				}
-//				break;
-//			}
-//		default:
-//			{
-//				trace("unknown TLV\n");
-//				break;
-//			}
-//		}
-//	}
-//
-//	return 0;
 }
 
 int debug_backhaul_sta_caps_report(void *cntlr, struct cmdu_buff *cmdu)
diff --git a/src/core/cntlr_tlv_generator.c b/src/core/cntlr_tlv_generator.c
index 24c1d5df81f9eaf08a4cf8d164926685ef41bb91..7807561b4cbe44e3fb78821f8f56b208375428ed 100644
--- a/src/core/cntlr_tlv_generator.c
+++ b/src/core/cntlr_tlv_generator.c
@@ -106,16 +106,16 @@ int cntlr_gen_8021q_settings(struct controller *c, struct cmdu_buff *frm,
 	struct tlv_default_8021q_settings *data;
 	int ret;
 
-	t = cmdu_reserve_tlv(frm, 256);
+	t = cmdu_reserve_tlv(frm, 20);
 	if (!t)
 		return -1;
 
 	t->type = MAP_TLV_DEFAULT_8021Q_SETTINGS;
-	t->len = 3;
+	t->len = sizeof(*data);
 
 	data = (struct tlv_default_8021q_settings *) t->data;
-	data->pvid = a->pvid;
-	data->pcp = a->pcp_default;
+	BUF_PUT_BE16(data->pvid, a->pvid);
+	data->pcp = (a->pcp_default << 5) & PCP_MASK;
 
 	ret = cmdu_put_tlv(frm, t);
 	if (ret) {
@@ -124,17 +124,6 @@ int cntlr_gen_8021q_settings(struct controller *c, struct cmdu_buff *frm,
 	}
 
 	return 0;
-//	struct tlv_default_8021q_settings *p;
-//
-//	p = (struct tlv_default_8021q_settings *) calloc(1, sizeof(*p));
-//	if (!p)
-//		return NULL;
-//
-//	p->tlv_type = MAP_TLV_DEFAULT_8021Q_SETTINGS;
-//	p->primary_vid = a->pvid;
-//	p->pcp = a->pcp_default;
-//
-//	return p;
 }
 
 int cntlr_gen_traffic_sep_policy(struct controller *c, struct cmdu_buff *frm,
@@ -378,21 +367,31 @@ int cntlr_gen_map_profile(struct controller *c, struct cmdu_buff *frm,
 	return 0;
 }
 
-struct tlv_ch_scan_rep_policy *cntlr_gen_ch_scan_rep_policy(
-		struct controller *c, struct agent_policy *a,
-		struct cmdu_buff *cmdu)
+int cntlr_gen_ch_scan_rep_policy( struct controller *c,
+		struct agent_policy *a, struct cmdu_buff *frm)
 {
-	return NULL;
-//	struct tlv_ch_scan_rep_policy *p;
-//
-//	p = calloc(1, sizeof(struct tlv_ch_scan_rep_policy));
-//	if (!p)
-//		return NULL;
-//
-//	p->tlv_type = MAP_TLV_CHANNEL_SCAN_REPORTING_POLICY;
-//	p->ch_scans = a->report_scan;
-//
-//	return p;
+	int ret;
+	struct tlv *t;
+	struct tlv_channel_scan_report_policy *data;
+
+	t = cmdu_reserve_tlv(frm, 20);
+	if (!t)
+		return -1;
+
+	t->type = MAP_TLV_CHANNEL_SCAN_REPORTING_POLICY;
+	t->len = sizeof(*data);
+	data = (struct tlv_channel_scan_report_policy *) t->data;
+
+	if (a->report_scan)
+		data->report = REPORT_CHANNEL_SCANS;
+
+	ret = cmdu_put_tlv(frm, t);
+	if (ret) {
+		dbg("%s: error: cmdu_put_tlv()\n", __func__);
+		return -1;
+	}
+
+	return 0;
 }
 
 int cntlr_gen_al_mac(struct controller *c, struct cmdu_buff *frm,
@@ -421,22 +420,33 @@ int cntlr_gen_al_mac(struct controller *c, struct cmdu_buff *frm,
 	return 0;
 }
 
-struct tlv_unsuccess_assoc_policy *cntlr_gen_unsuccess_assoc_policy(
-		struct controller *c, struct agent_policy *a,
-		struct cmdu_buff *cmdu)
+int cntlr_gen_unsuccess_assoc_policy(struct controller *c,
+		struct agent_policy *a, struct cmdu_buff *frm)
 {
-	return NULL;
-//	struct tlv_unsuccess_assoc_policy *p;
-//
-//	p = calloc(1, sizeof(struct tlv_unsuccess_assoc_policy));
-//	if (!p)
-//		return NULL;
-//
-//	p->tlv_type = MAP_TLV_UNSUCCESS_ASSOCIATION_POLICY;
-//	p->report = a->report_sta_assocfails;
-//	p->max_reporting_rate = a->report_sta_assocfails_rate;
-//
-//	return p;
+	int ret;
+	struct tlv *t;
+	struct tlv_unsuccess_assoc_policy *data;
+
+	t = cmdu_reserve_tlv(frm, 20);
+	if (!t)
+		return -1;
+
+	t->type = MAP_TLV_UNSUCCESS_ASSOCIATION_POLICY;
+	t->len = sizeof(*data);
+	data = (struct tlv_unsuccess_assoc_policy *) t->data;
+
+	if (a->report_sta_assocfails)
+		data->report = UNSUCCESSFUL_ASSOC_REPORT;
+
+	BUF_PUT_BE32(data->max_report_rate, a->report_sta_assocfails_rate);
+
+	ret = cmdu_put_tlv(frm, t);
+	if (ret) {
+		dbg("%s: error: cmdu_put_tlv()\n", __func__);
+		return -1;
+	}
+
+	return 0;
 }
 
 int cntlr_gen_supported_freq_band(struct controller *c, struct cmdu_buff *frm,
@@ -464,133 +474,139 @@ int cntlr_gen_supported_freq_band(struct controller *c, struct cmdu_buff *frm,
 	return 0;
 }
 
-struct tlv_backhaul_bss_config *cntlr_gen_backhaul_bss_config(
-		struct controller *c, struct agent_policy *a,
-		struct cmdu_buff *cmdu, const uint8_t *bssid)
+int cntlr_gen_backhaul_bss_config(struct controller *c,
+		struct agent_policy *a, struct cmdu_buff *frm,
+		const uint8_t *bssid)
 {
-	return NULL;
-//	struct tlv_backhaul_bss_config *p;
-//
-//	p = calloc(1, sizeof(struct tlv_backhaul_bss_config));
-//	if (!p)
-//		return NULL;
-//
-//	p->tlv_type = MAP_TLV_BACKHAUL_BSS_CONFIG;
-//	memcpy(p->bssid, bssid, 6);
-//	p->p1 = a->disallow_bsta_p1;
-//	p->p2 = a->disallow_bsta_p2;
-//
-//	return p;
+	int ret;
+	struct tlv *t;
+	struct tlv_bbss_config *data;
+
+	t = cmdu_reserve_tlv(frm, 20);
+	if (!t)
+		return -1;
+
+	t->type = MAP_TLV_BACKHAUL_BSS_CONFIG;
+	t->len = sizeof(*data);
+	data = (struct tlv_bbss_config *) t->data;
+
+	memcpy(data->bssid, bssid, 6);
+	if (a->disallow_bsta_p1)
+		data->config |= BBSS_CONFIG_P1_BSTA_DISALLOWED;
+
+	if (a->disallow_bsta_p2)
+		data->config |= BBSS_CONFIG_P2_BSTA_DISALLOWED;
+
+	ret = cmdu_put_tlv(frm, t);
+	if (ret) {
+		dbg("%s: error: cmdu_put_tlv()\n", __func__);
+		return -1;
+	}
+
+	return 0;
 }
 
-struct tlv_steering_policy *cntlr_gen_steering_policy(
-		struct controller *c, struct agent_policy *a,
-		struct cmdu_buff *cmdu, int num_radio, uint8_t *radiolist)
+int cntlr_gen_steering_policy(struct controller *c, struct agent_policy *a,
+		struct cmdu_buff *frm, int num_radio, uint8_t *radiolist)
 {
-	return NULL;
-//	int i = 0, index;
-//	struct tlv_steering_policy *p;
-//	struct stax *x;
-//	uint8_t sta_mac[6] = {0};
-//
-//	p = calloc(1, sizeof(struct tlv_steering_policy));
-//	if (!p)
-//		return NULL;
-//
-//	p->tlv_type = MAP_TLV_STEERING_POLICY;
-//
-//	p->local_disallowed_sta_nr = 0;
-//	list_for_each_entry(x, &a->steer_exlist, list) {
-//		p->local_disallowed_sta_nr++;
-//		index = p->local_disallowed_sta_nr - 1;
-//		p->local_disallowed_sta_macs = realloc(p->local_disallowed_sta_macs,
-//				p->local_disallowed_sta_nr * sizeof(*p->local_disallowed_sta_macs));
-//		if (!p->local_disallowed_sta_macs)
-//			goto fail_alloc;
-//
-//		hwaddr_aton(x->macstring, sta_mac);
-//		memcpy(p->local_disallowed_sta_macs[index].addr, sta_mac, 6);
-//	}
-//
-//	p->btm_disallowed_sta_nr = 0;
-//	list_for_each_entry(x, &a->btmsteer_exlist, list) {
-//		p->btm_disallowed_sta_nr++;
-//		index = p->btm_disallowed_sta_nr - 1;
-//		p->btm_disallowed_sta_macs = realloc(p->btm_disallowed_sta_macs,
-//				p->btm_disallowed_sta_nr * sizeof(*p->btm_disallowed_sta_macs));
-//		if (!p->btm_disallowed_sta_macs)
-//			goto fail_alloc;
-//
-//		hwaddr_aton(x->macstring, sta_mac);
-//		memcpy(p->btm_disallowed_sta_macs[index].addr, sta_mac, 6);
-//	}
-//
-//	p->control_policy_radio_nr = num_radio;
-//	p->control_policy = calloc(p->control_policy_radio_nr,
-//			sizeof(*p->control_policy));
-//	if (!p->control_policy)
-//		goto fail_alloc;
-//
-//	for (i = 0; i < p->control_policy_radio_nr; i++) {
-//		memcpy(p->control_policy[i].radio_id, &radiolist[i*6], 6);
-//		p->control_policy[i].steering_policy = a->policy;
-//		p->control_policy[i].channel_utilization_thres =
-//							a->util_threshold;
-//		p->control_policy[i].rcpi_steering_thres =
-//							a->rcpi_threshold;
-//	}
-//
-//	return p;
-//
-//fail_alloc:
-//	if (p->local_disallowed_sta_macs)
-//		free(p->local_disallowed_sta_macs);
-//	if (p->btm_disallowed_sta_macs)
-//		free(p->btm_disallowed_sta_macs);
-//
-//	free(p);
-//
-//	return NULL;
+	int ret, i;
+	int offset = 0;
+	struct tlv *t;
+	struct stax *x;
+	uint8_t sta_mac[6] = {0};
+	uint8_t num_nosteer_index = 0;
+	uint8_t num_nobtmsteer_index = 0;
+	uint8_t num_nosteer = 0;
+	uint8_t num_nobtmsteer = 0;
+
+	t = cmdu_reserve_tlv(frm, 256);
+	if (!t)
+		return -1;
+
+	t->type = MAP_TLV_STEERING_POLICY;
+
+	num_nosteer_index = offset++;
+	list_for_each_entry(x, &a->steer_exlist, list) {
+		num_nosteer++;
+		hwaddr_aton(x->macstring, sta_mac);
+		memcpy(t->data + offset, sta_mac, 6);
+		offset += 6;
+	}
+	t->data[num_nosteer_index] = num_nosteer;
+
+	num_nobtmsteer_index = offset++;
+	list_for_each_entry(x, &a->btmsteer_exlist, list) {
+		num_nobtmsteer++;
+		hwaddr_aton(x->macstring, sta_mac);
+		memcpy(t->data + offset, sta_mac, 6);
+		offset += 6;
+	}
+	t->data[num_nobtmsteer_index] = num_nobtmsteer;
+
+	t->data[offset++] = num_radio;
+	for (i = 0; i < num_radio; i++) {
+		memcpy(t->data + offset, &radiolist[i*6], 6);
+		offset += 6;
+		t->data[offset++] = a->policy;
+		t->data[offset++] = a->util_threshold;
+		t->data[offset++] = a->rcpi_threshold;
+	}
+
+	/* update the tlv len */
+	t->len = offset;
+
+	ret = cmdu_put_tlv(frm, t);
+	if (ret) {
+		dbg("%s: error: cmdu_put_tlv()\n", __func__);
+		return -1;
+	}
+
+	return 0;
 }
 
-struct tlv_metric_report_policy *cntlr_gen_metric_report_policy(
-		struct controller *c, struct agent_policy *a,
-		struct cmdu_buff *cmdu, int num_radio, uint8_t *radiolist)
+int cntlr_gen_metric_report_policy(struct controller *c, struct agent_policy *a,
+		struct cmdu_buff *frm, int num_radio, uint8_t *radiolist)
 {
-	return NULL;
-//	int i = 0;
-//	struct tlv_metric_report_policy *p;
-//
-//	p = calloc(1, sizeof(struct tlv_metric_report_policy));
-//	if (!p)
-//		return NULL;
-//
-//	p->tlv_type = MAP_TLV_METRIC_REPORTING_POLICY;
-//	p->interval = a->report_metric_periodic;
-//	p->metric_reporting_policy_radio_nr = num_radio;
-//	p->metric_reporting_policy = calloc(p->metric_reporting_policy_radio_nr,
-//					sizeof(*p->metric_reporting_policy));
-//
-//	if (!p->metric_reporting_policy) {
-//		free(p);
-//		return NULL;
-//	}
-//
-//	for (i = 0; i < p->metric_reporting_policy_radio_nr; i++) {
-//		memcpy(p->metric_reporting_policy[i].radio_id, &radiolist[i*6], 6);
-//		p->metric_reporting_policy[i].rcpi_thres =
-//						a->report_rcpi_threshold;
-//		p->metric_reporting_policy[i].rcpi_hysteresis_margin =
-//						a->rcpi_hysteresis_margin;
-//		p->metric_reporting_policy[i].channel_utilization_thres =
-//						a->report_util_threshold;
-//		p->metric_reporting_policy[i].is_assoc_sta_traffic_stats =
-//						a->include_sta_stats;
-//		p->metric_reporting_policy[i].is_assoc_sta_link_metrics =
-//						a->include_sta_metric;
-//	}
-//
-//	return p;
+	int ret, i;
+	struct tlv *t;
+	int offset = 0;
+	uint8_t include_flag = 0x00;
+
+	t = cmdu_reserve_tlv(frm, 256);
+	if (!t)
+		return -1;
+
+	t->type = MAP_TLV_METRIC_REPORTING_POLICY;
+
+	t->data[offset++] = a->report_metric_periodic;
+	t->data[offset++] = num_radio;
+
+	for (i = 0; i < num_radio; i++) {
+		memcpy(t->data + offset, &radiolist[i*6], 6);
+		offset += 6;
+		t->data[offset++] = a->report_rcpi_threshold;
+		t->data[offset++] = a->rcpi_hysteresis_margin;
+		t->data[offset++] = a->report_util_threshold;
+
+		if (a->include_sta_stats)
+			include_flag |= INCLUDE_STA_STATS;
+
+		if (a->include_sta_metric)
+			include_flag |= INCLUDE_STA_LINK_METRICS;
+
+		t->data[offset++] = include_flag;
+	}
+
+	/* update the tlv length */
+	t->len = offset;
+
+	ret = cmdu_put_tlv(frm, t);
+	if (ret) {
+		dbg("%s: error: cmdu_put_tlv()\n", __func__);
+		return -1;
+	}
+
+	return 0;
 }
 
 struct tlv_supported_role *cntlr_gen_supported_role(struct controller *c,
diff --git a/src/core/cntlr_tlv_generator.h b/src/core/cntlr_tlv_generator.h
index a8b44b451b6ade984ca9f8f6f8455667b63001e5..4bf519bb7c9cf2b7e762cc289f2d8cf3a644f2da 100644
--- a/src/core/cntlr_tlv_generator.h
+++ b/src/core/cntlr_tlv_generator.h
@@ -26,20 +26,18 @@ int cntlr_gen_supp_service(struct controller *c, struct cmdu_buff *cmdu,
 		uint8_t service);
 int cntlr_gen_map_profile(struct controller *c, struct cmdu_buff *frm,
 		uint8_t profile);
-struct tlv_steering_policy *cntlr_gen_steering_policy(struct controller *c,
-		struct agent_policy *a, struct cmdu_buff *cmdu,
+int cntlr_gen_steering_policy(struct controller *c,
+		struct agent_policy *a, struct cmdu_buff *frm,
 		int num_radio, uint8_t *radiolist);
-struct tlv_metric_report_policy *cntlr_gen_metric_report_policy(struct controller *c,
-		struct agent_policy *a, struct cmdu_buff *cmdu,
+int cntlr_gen_metric_report_policy(struct controller *c,
+		struct agent_policy *a, struct cmdu_buff *frm,
 		int num_radio, uint8_t *radiolist);
-struct tlv_ch_scan_rep_policy *cntlr_gen_ch_scan_rep_policy(struct controller *c,
-		struct agent_policy *a, struct cmdu_buff *cmdu);
-struct tlv_unsuccess_assoc_policy *cntlr_gen_unsuccess_assoc_policy(
-		struct controller *c, struct agent_policy *a,
-		struct cmdu_buff *cmdu);
-struct tlv_backhaul_bss_config *cntlr_gen_backhaul_bss_config(
-		struct controller *c, struct agent_policy *a,
-		struct cmdu_buff *cmdu, const uint8_t *bssid);
+int cntlr_gen_ch_scan_rep_policy(struct controller *c,
+		struct agent_policy *a, struct cmdu_buff *frm);
+int cntlr_gen_unsuccess_assoc_policy(struct controller *c,
+		struct agent_policy *a, struct cmdu_buff *frm);
+int cntlr_gen_backhaul_bss_config(struct controller *c, struct agent_policy *a,
+		struct cmdu_buff *frm, const uint8_t *bssid);
 int cntlr_gen_al_mac(struct controller *c, struct cmdu_buff *frm,
 		uint8_t *hwaddr);
 int cntlr_gen_supported_freq_band(struct controller *c, struct cmdu_buff *frm,
diff --git a/src/core/cntlr_ubus.c b/src/core/cntlr_ubus.c
index 931dc37b64be85101740ad181d5dc4a6759c293d..6061f358d93f531ac8f1c1f181501071a98e5be5 100644
--- a/src/core/cntlr_ubus.c
+++ b/src/core/cntlr_ubus.c
@@ -1287,119 +1287,116 @@ static int cntlr_ap_policy_config(struct ubus_context *ctx, struct ubus_object *
 				struct ubus_request_data *req, const char *method,
 				struct blob_attr *msg)
 {
-	return 0;
-//	char agent[18] = {0};
-//	char radio[18] = {0};
-//	char bss[18] = {0};
-//	uint8_t hwaddr[6] = {0};
-//	struct cmdu_cstruct *cmdu_data;
-//	struct agent_policy *a, *found = NULL;
-//	struct blob_attr *attr = NULL;
-//	uint8_t *radiolist = NULL;
-//	uint8_t *bsslist = NULL;
-//	int rem, num_radio = 0, num_bss = 0;
-//	struct blob_attr *tb[__AP_POLICY_CONFIG_MAX];
-//	struct controller *c = container_of(obj, struct controller, obj);
-//
-//	blobmsg_parse(ap_policy_config_params, __AP_POLICY_CONFIG_MAX, tb,
-//			blob_data(msg), blob_len(msg));
-//
-//	if (!tb[AP_POLICY_CONFIG_AGENT] || !tb[AP_POLICY_CONFIG_RADIOS]) {
-//		fprintf(stderr, "Agent policy config: provide Agent or Radio " \
-//				"address in format 11:22:33...\n");
-//		return UBUS_STATUS_INVALID_ARGUMENT;
-//	}
-//
-//	strncpy(agent, blobmsg_data(tb[AP_POLICY_CONFIG_AGENT]), sizeof(agent) - 1);
-//	if (!hwaddr_aton(agent, hwaddr))
-//		return UBUS_STATUS_UNKNOWN_ERROR;
-//
-//	list_for_each_entry(a, &c->cfg.policylist, list) {
-//		if (!memcmp(hwaddr, a->agent_id, sizeof(hwaddr))) {
-//			found = a;
-//			break;
-//		}
-//	}
-//
-//	if (!found)
-//		return UBUS_STATUS_UNKNOWN_ERROR;
-//
-//	/* fetch radio id's */
-//	blobmsg_for_each_attr(attr, tb[AP_POLICY_CONFIG_RADIOS], rem) {
-//		uint8_t bssid[6] = {0};
-//
-//		if (blobmsg_type(attr) != BLOBMSG_TYPE_STRING)
-//			continue;
-//
-//		memset(radio, 0, sizeof(radio));
-//		strncpy(radio, blobmsg_data(attr), sizeof(radio)-1);
-//		if (!hwaddr_aton(radio, bssid)) {
-//			fprintf(stderr, "Agent policy config: provide radio " \
-//					"address in format 11:22:33...\n");
-//			if (radiolist)
-//				free(radiolist);
-//
-//			return UBUS_STATUS_UNKNOWN_ERROR;
-//		}
-//
-//		num_radio++;
-//		radiolist = (uint8_t *)realloc(radiolist, 6 * num_radio * sizeof(uint8_t));
-//		if (!radiolist)
-//			return UBUS_STATUS_UNKNOWN_ERROR;
-//
-//		memcpy(&radiolist[(num_radio-1)*6], bssid, 6);
-//	}
-//
-//	if (num_radio == 0)
-//		return UBUS_STATUS_UNKNOWN_ERROR;
-//
-//	/* fetch BSS list */
-//	blobmsg_for_each_attr(attr, tb[AP_POLICY_CONFIG_BSS], rem) {
-//		uint8_t bssid[6] = {0};
-//
-//		if (blobmsg_type(attr) != BLOBMSG_TYPE_STRING)
-//			continue;
-//
-//		memset(bss, 0, sizeof(bss));
-//		strncpy(bss, blobmsg_data(attr), sizeof(bss)-1);
-//		if (!hwaddr_aton(bss, bssid)) {
-//			fprintf(stderr, "Agent policy config: provide bssid " \
-//					"address in format 11:22:33...\n");
-//			goto fail_parsing;
-//		}
-//
-//		num_bss++;
-//		bsslist = (uint8_t *)realloc(bsslist, 6 * num_bss * sizeof(uint8_t));
-//		if (!bsslist)
-//			goto fail_parsing;
-//
-//		memcpy(&bsslist[(num_bss-1)*6], bssid, 6);
-//	}
-//
-//	cmdu_data = cntlr_gen_policy_config_req(c, NULL, found, num_radio,
-//			radiolist, num_bss, bsslist);
-//	if (!cmdu_data)
-//		goto fail_parsing;
-//
-//	// TODO: ff:ff:ff:ff:ff:ff = send to all agents
-//
-//	send_cmdu(c, cmdu_data);
-//	map_free_cmdu(cmdu_data);
-//
-//	if (bsslist)
-//		free(bsslist);
-//
-//	free(radiolist);
-//
-//	return UBUS_STATUS_OK;
-//
-//fail_parsing:
-//	if (bsslist)
-//		free(bsslist);
-//
-//	free(radiolist);
-//
-//	return UBUS_STATUS_UNKNOWN_ERROR;
+	char agent[18] = {0};
+	char radio[18] = {0};
+	char bss[18] = {0};
+	uint8_t hwaddr[6] = {0};
+	struct cmdu_buff *cmdu;
+	struct agent_policy *a, *found = NULL;
+	struct blob_attr *attr = NULL;
+	uint8_t *radiolist = NULL;
+	uint8_t *bsslist = NULL;
+	int rem, num_radio = 0, num_bss = 0;
+	struct blob_attr *tb[__AP_POLICY_CONFIG_MAX];
+	struct controller *c = container_of(obj, struct controller, obj);
+
+	blobmsg_parse(ap_policy_config_params, __AP_POLICY_CONFIG_MAX, tb,
+			blob_data(msg), blob_len(msg));
+
+	if (!tb[AP_POLICY_CONFIG_AGENT] || !tb[AP_POLICY_CONFIG_RADIOS]) {
+		fprintf(stderr, "Agent policy config: provide Agent or Radio " \
+				"address in format 11:22:33...\n");
+		return UBUS_STATUS_INVALID_ARGUMENT;
+	}
+
+	strncpy(agent, blobmsg_data(tb[AP_POLICY_CONFIG_AGENT]), sizeof(agent) - 1);
+	if (!hwaddr_aton(agent, hwaddr))
+		return UBUS_STATUS_UNKNOWN_ERROR;
+
+	list_for_each_entry(a, &c->cfg.policylist, list) {
+		if (!memcmp(hwaddr, a->agent_id, sizeof(hwaddr))) {
+			found = a;
+			break;
+		}
+	}
+
+	if (!found)
+		return UBUS_STATUS_UNKNOWN_ERROR;
+
+	/* fetch radio id's */
+	blobmsg_for_each_attr(attr, tb[AP_POLICY_CONFIG_RADIOS], rem) {
+		uint8_t bssid[6] = {0};
+
+		if (blobmsg_type(attr) != BLOBMSG_TYPE_STRING)
+			continue;
+
+		memset(radio, 0, sizeof(radio));
+		strncpy(radio, blobmsg_data(attr), sizeof(radio)-1);
+		if (!hwaddr_aton(radio, bssid)) {
+			fprintf(stderr, "Agent policy config: provide radio " \
+					"address in format 11:22:33...\n");
+			if (radiolist)
+				free(radiolist);
+
+			return UBUS_STATUS_UNKNOWN_ERROR;
+		}
+
+		num_radio++;
+		radiolist = (uint8_t *)realloc(radiolist, 6 * num_radio * sizeof(uint8_t));
+		if (!radiolist)
+			return UBUS_STATUS_UNKNOWN_ERROR;
+
+		memcpy(&radiolist[(num_radio-1)*6], bssid, 6);
+	}
+
+	if (num_radio == 0)
+		return UBUS_STATUS_UNKNOWN_ERROR;
+
+	/* fetch BSS list */
+	blobmsg_for_each_attr(attr, tb[AP_POLICY_CONFIG_BSS], rem) {
+		uint8_t bssid[6] = {0};
+
+		if (blobmsg_type(attr) != BLOBMSG_TYPE_STRING)
+			continue;
+
+		memset(bss, 0, sizeof(bss));
+		strncpy(bss, blobmsg_data(attr), sizeof(bss)-1);
+		if (!hwaddr_aton(bss, bssid)) {
+			fprintf(stderr, "Agent policy config: provide bssid " \
+					"address in format 11:22:33...\n");
+			goto fail_parsing;
+		}
+
+		num_bss++;
+		bsslist = (uint8_t *)realloc(bsslist, 6 * num_bss * sizeof(uint8_t));
+		if (!bsslist)
+			goto fail_parsing;
+
+		memcpy(&bsslist[(num_bss-1)*6], bssid, 6);
+	}
+
+	cmdu = cntlr_gen_policy_config_req(c, found, num_radio,
+			radiolist, num_bss, bsslist);
+	if (!cmdu)
+		goto fail_parsing;
+
+	send_cmdu(c, cmdu);
+	cmdu_free(cmdu);
+
+	if (bsslist)
+		free(bsslist);
+
+	free(radiolist);
+
+	return UBUS_STATUS_OK;
+
+fail_parsing:
+	if (bsslist)
+		free(bsslist);
+
+	free(radiolist);
+
+	return UBUS_STATUS_UNKNOWN_ERROR;
 }
 
 static int cntlr_scan(struct ubus_context *ctx, struct ubus_object *obj,