diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 53143f7..8b2152b 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2009,6 +2009,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
 		conf->ieee80211d = atoi(pos);
 	} else if (os_strcmp(buf, "ieee80211h") == 0) {
 		conf->ieee80211h = atoi(pos);
+	} else if (os_strcmp(buf, "dfs_test_mode") == 0) {
+		conf->dfs_test_mode = atoi(pos);
 	} else if (os_strcmp(buf, "ieee8021x") == 0) {
 		bss->ieee802_1x = atoi(pos);
 	} else if (os_strcmp(buf, "eapol_version") == 0) {
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 961d2dd..4444029 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -594,6 +594,7 @@ struct hostapd_config {
 	int ieee80211d;
 
 	int ieee80211h; /* DFS */
+	int dfs_test_mode;
 
 	/*
 	 * Local power constraint is an octet encoded as an unsigned integer in
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index d458a42..bfaaaaa 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -17,6 +17,8 @@
 #include "ap_drv_ops.h"
 #include "drivers/driver.h"
 #include "dfs.h"
+#include "beacon.h"
+#include "eloop.h"
 
 
 static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1)
@@ -832,6 +834,73 @@ static int hostapd_csa_in_progress(struct hostapd_iface *iface)
 	return 0;
 }
 
+void hostapd_dfs_test_mode_csa_timeout(void *eloop_data, void *user_data)
+{
+	struct hostapd_data *hapd = eloop_data;
+
+	wpa_printf(MSG_INFO, "Stopping CSA in dfs test mode");
+	hostapd_cleanup_cs_params(hapd);
+	ieee802_11_set_beacon(hapd);
+}
+
+static int hostapd_dfs_testmode_set_beacon_csa(struct hostapd_iface *iface)
+{
+	struct hostapd_data *hapd = iface->bss[0];
+	struct csa_settings csa_settings;
+	int secondary_channel;
+	u8 vht_oper_centr_freq_seg0_idx;
+	u8 vht_oper_centr_freq_seg1_idx;
+	int err = 0;
+
+	eloop_cancel_timeout(hostapd_dfs_test_mode_csa_timeout, hapd, NULL);
+	secondary_channel = iface->conf->secondary_channel;
+	vht_oper_centr_freq_seg0_idx =
+			iface->conf->vht_oper_centr_freq_seg0_idx;
+	vht_oper_centr_freq_seg1_idx =
+			iface->conf->vht_oper_centr_freq_seg1_idx;
+
+	/* Setup CSA request */
+	os_memset(&csa_settings, 0, sizeof(csa_settings));
+	err = hostapd_set_freq_params(&csa_settings.freq_params,
+				      iface->conf->hw_mode,
+				      iface->freq,
+				      iface->conf->channel,
+				      iface->conf->ieee80211n,
+				      iface->conf->ieee80211ac,
+				      secondary_channel,
+				      iface->conf->vht_oper_chwidth,
+				      vht_oper_centr_freq_seg0_idx,
+				      vht_oper_centr_freq_seg1_idx,
+				      iface->current_mode->vht_capab);
+
+	if (err) {
+		wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
+		goto fail;
+	}
+
+	if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)) {
+		wpa_printf(MSG_INFO, "CSA is not supported");
+		hostapd_disable_iface(iface);
+		return -1;
+	}
+
+	hapd->cs_freq_params = csa_settings.freq_params;
+	hapd->cs_count = 3;
+	hapd->cs_block_tx = 1;
+	err = ieee802_11_set_beacon(hapd);
+	if (err)
+		goto fail;
+	wpa_printf(MSG_DEBUG, "CSA beacon configured for dfs mode, count %d",
+		   hapd->cs_count);
+	hapd->csa_in_progress = 1;
+	eloop_register_timeout(HOSTAPD_DFS_TEST_MODE_CSA_DUR, 0,
+			       hostapd_dfs_test_mode_csa_timeout, hapd, NULL);
+	return 0;
+
+fail:
+	hostapd_disable_iface(iface);
+	return err;
+}
 
 static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
 {
@@ -856,6 +925,9 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
 	if (iface->cac_started)
 		return hostapd_dfs_start_channel_switch_cac(iface);
 
+	if (iface->conf->dfs_test_mode)
+		return hostapd_dfs_testmode_set_beacon_csa(iface);
+
 	/* Perform channel switch/CSA */
 	channel = dfs_get_valid_channel(iface, &secondary_channel,
 					&vht_oper_centr_freq_seg0_idx,
@@ -971,6 +1043,12 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
 	set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
 		      cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE);
 
+	if (iface->conf->dfs_test_mode) {
+		set_dfs_state(iface, freq, ht_enabled, chan_offset,
+			      chan_width, cf1, cf2,
+			      HOSTAPD_CHAN_DFS_AVAILABLE);
+	}
+
 	/* Skip if reported radar event not overlapped our channels */
 	res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2);
 	if (!res)
diff --git a/src/ap/dfs.h b/src/ap/dfs.h
index be8c0e6..8b78cfe 100644
--- a/src/ap/dfs.h
+++ b/src/ap/dfs.h
@@ -9,6 +9,11 @@
 #ifndef DFS_H
 #define DFS_H
 
+/* CSA beacon duration in seconds for dfs testing mode */
+#define HOSTAPD_DFS_TEST_MODE_CSA_DUR 1
+
+void hostapd_dfs_test_mode_csa_timeout(void *eloop_data, void *user_data);
+
 int hostapd_handle_dfs(struct hostapd_iface *iface);
 
 int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 3e4e16b..c6f9e28 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1982,6 +1982,7 @@ int hostapd_disable_iface(struct hostapd_iface *hapd_iface)
 		!!(hapd_iface->drv_flags &
 		   WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
 
+	eloop_cancel_timeout(hostapd_dfs_test_mode_csa_timeout, hapd_iface, NULL);
 	/* same as hostapd_interface_deinit without deinitializing ctrl-iface */
 	for (j = 0; j < hapd_iface->num_bss; j++) {
 		struct hostapd_data *hapd = hapd_iface->bss[j];
-- 
1.9.1

