[PATCH 05/14] wpa_supplicant/hostapd: Add support for eCSA

Ilan Peer ilan.peer at intel.com
Mon May 19 03:07:07 EDT 2014


From: Andrei Otcheretianski <andrei.otcheretianski at intel.com>

Extended channel switch provides an ability to switch between
operating classes and is required for P2P devices by the spec
when switching in 5GHZ.
When operating class is provided for channel swich the AP/GO
will use eCSA IE in addition to the regular CSA IE both on
2.4GHZ and 5GHZ bands.
Transitions between differnet hw_modes are not supported.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
 src/ap/beacon.c              |   62 ++++++++++++++++++++++++++++++++----------
 src/ap/hostapd.c             |    4 +++
 src/ap/hostapd.h             |    4 +++
 src/common/ieee802_11_defs.h |    1 +
 4 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index f9ec5c8..7178862 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -275,8 +275,25 @@ static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid)
 	return eid;
 }
 
+static u8 *hostapd_eid_ecsa(struct hostapd_data *hapd, u8 *eid)
+{
+	if (!hapd->iface->cs_freq_params.channel)
+		return eid;
+
+	if (!hapd->iface->cs_oper_class)
+		return eid;
+
+	*eid++ = WLAN_EID_EXT_CHANSWITCH_ANN;
+	*eid++ = 4;
+	*eid++ = hapd->iface->cs_block_tx;
+	*eid++ = hapd->iface->cs_oper_class;
+	*eid++ = hapd->iface->cs_freq_params.channel;
+	*eid++ = hapd->iface->cs_count;
 
-static u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid)
+	return eid;
+}
+
+static u8 *hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid)
 {
 	u8 sec_ch;
 
@@ -351,25 +368,38 @@ static u8 *hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid)
 	return eid;
 }
 
-static u8 * hostapd_add_csa_elems(struct hostapd_data *hapd, u8 *pos,
-				  u8 *start, unsigned int *csa_counter_off)
+static u8 *hostapd_add_csa_elems(struct hostapd_data *hapd, u8 *pos,
+				 u8 *start, unsigned int *csa_counter_off,
+				 unsigned int *ecsa_counter_off)
 {
-	u8 *old_pos = pos;
+	u8 *curr_pos = pos;
+	u8 *csa_pos = pos;
 
-	if (!csa_counter_off)
+	if (!csa_counter_off || !ecsa_counter_off)
 		return pos;
 
 	*csa_counter_off = 0;
-	pos = hostapd_eid_csa(hapd, pos);
+	*ecsa_counter_off = 0;
 
-	if (pos != old_pos) {
-		/* save an offset to the counter - should be last byte */
-		*csa_counter_off = pos - start - 1;
-		pos = hostapd_eid_secondary_channel(hapd, pos);
-		pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
-	}
+	curr_pos = hostapd_eid_csa(hapd, curr_pos);
 
-	return pos;
+	/* save an offset to the csa counter - should be last byte */
+	if (curr_pos != pos)
+		*csa_counter_off = curr_pos - start - 1;
+
+	csa_pos = curr_pos;
+	curr_pos = hostapd_eid_ecsa(hapd, curr_pos);
+
+	/* save an offset to the eCSA counter - should be last byte */
+	if (curr_pos != csa_pos)
+		*ecsa_counter_off = curr_pos - start - 1;
+
+	/* at least one of ies is added */
+	if (pos != curr_pos) {
+		curr_pos = hostapd_eid_secondary_channel(hapd, curr_pos);
+		curr_pos = hostapd_eid_wb_chsw_wrapper(hapd, curr_pos);
+	}
+	return curr_pos;
 }
 
 
@@ -457,7 +487,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 	pos = hostapd_eid_roaming_consortium(hapd, pos);
 
 	pos = hostapd_add_csa_elems(hapd, pos, (u8 *)resp,
-				    &hapd->iface->cs_c_off_proberesp);
+				    &hapd->iface->cs_c_off_proberesp,
+				    &hapd->iface->cs_c_off_ecsa_proberesp);
 #ifdef CONFIG_IEEE80211AC
 	pos = hostapd_eid_vht_capabilities(hapd, pos);
 	pos = hostapd_eid_vht_operation(hapd, pos);
@@ -872,7 +903,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 	tailpos = hostapd_eid_adv_proto(hapd, tailpos);
 	tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
 	tailpos = hostapd_add_csa_elems(hapd, tailpos, tail,
-					&hapd->iface->cs_c_off_beacon);
+					&hapd->iface->cs_c_off_beacon,
+					&hapd->iface->cs_c_off_ecsa_beacon);
 #ifdef CONFIG_IEEE80211AC
 	tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
 	tailpos = hostapd_eid_vht_operation(hapd, tailpos);
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 72f2b24..31aaca7 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -2357,6 +2357,8 @@ static int hostapd_fill_csa_settings(struct hostapd_iface *iface,
 
 	settings->counter_offset_beacon[0] = iface->cs_c_off_beacon;
 	settings->counter_offset_presp[0] = iface->cs_c_off_proberesp;
+	settings->counter_offset_beacon[1] = iface->cs_c_off_ecsa_beacon;
+	settings->counter_offset_presp[1] = iface->cs_c_off_ecsa_proberesp;
 
 	return 0;
 }
@@ -2371,6 +2373,8 @@ void hostapd_cleanup_cs_params(struct hostapd_data *hapd)
 	hapd->iface->cs_c_off_beacon = 0;
 	hapd->iface->cs_c_off_proberesp = 0;
 	hapd->iface->csa_in_progress = 0;
+	hapd->iface->cs_c_off_ecsa_beacon = 0;
+	hapd->iface->cs_c_off_ecsa_proberesp = 0;
 }
 
 
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 687dbaa..600e2ad 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -348,8 +348,12 @@ struct hostapd_iface {
 	struct hostapd_freq_params cs_freq_params;
 	u8 cs_count;
 	int cs_block_tx;
+	/* eCSA IE will be added only if operating class is specified */
+	u8 cs_oper_class;
 	unsigned int cs_c_off_beacon;
 	unsigned int cs_c_off_proberesp;
+	unsigned int cs_c_off_ecsa_beacon;
+	unsigned int cs_c_off_ecsa_proberesp;
 	int csa_in_progress;
 	unsigned int csa_supported:1;
 
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 8fe2e4a..4693cef 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -230,6 +230,7 @@
 #define WLAN_EID_TIMEOUT_INTERVAL 56
 #define WLAN_EID_RIC_DATA 57
 #define WLAN_EID_SUPPORTED_OPERATING_CLASSES 59
+#define WLAN_EID_EXT_CHANSWITCH_ANN 60
 #define WLAN_EID_HT_OPERATION 61
 #define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
 #define WLAN_EID_WAPI 68
-- 
1.7.10.4



More information about the HostAP mailing list