[PATCH 08/26] wpa_supplicant/hostapd: Add support for eCSA
Ilan Peer
ilan.peer
Tue Sep 8 02:46:15 PDT 2015
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 swtich the AP/P2P GO
will use eCSA IE in addition to the regular CSA IE both on
2.4GHz and 5GHz bands.
Transitions between different 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 | 5 ++++
src/ap/ieee802_11_shared.c | 2 ++
src/common/ieee802_11_defs.h | 1 +
5 files changed, 59 insertions(+), 15 deletions(-)
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index e98c189..2122e9a 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -309,8 +309,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->cs_freq_params.channel)
+ return eid;
+
+ if (!hapd->iface->cs_oper_class)
+ return eid;
+
+ *eid++ = WLAN_EID_EXT_CHANSWITCH_ANN;
+ *eid++ = 4;
+ *eid++ = hapd->cs_block_tx;
+ *eid++ = hapd->iface->cs_oper_class;
+ *eid++ = hapd->cs_freq_params.channel;
+ *eid++ = hapd->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;
@@ -385,25 +402,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;
}
@@ -500,7 +530,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->cs_c_off_proberesp);
+ &hapd->cs_c_off_proberesp,
+ &hapd->cs_c_off_ecsa_proberesp);
#ifdef CONFIG_FST
if (hapd->iface->fst_ies) {
@@ -1069,7 +1100,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->cs_c_off_beacon);
+ &hapd->cs_c_off_beacon,
+ &hapd->cs_c_off_ecsa_beacon);
#ifdef CONFIG_FST
if (hapd->iface->fst_ies) {
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 787b8db..d366673 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -2851,6 +2851,8 @@ static int hostapd_fill_csa_settings(struct hostapd_data *hapd,
settings->counter_offset_beacon[0] = hapd->cs_c_off_beacon;
settings->counter_offset_presp[0] = hapd->cs_c_off_proberesp;
+ settings->counter_offset_beacon[1] = hapd->cs_c_off_ecsa_beacon;
+ settings->counter_offset_presp[1] = hapd->cs_c_off_ecsa_proberesp;
return 0;
}
@@ -2864,6 +2866,8 @@ void hostapd_cleanup_cs_params(struct hostapd_data *hapd)
hapd->cs_c_off_beacon = 0;
hapd->cs_c_off_proberesp = 0;
hapd->csa_in_progress = 0;
+ hapd->cs_c_off_ecsa_beacon = 0;
+ hapd->cs_c_off_ecsa_proberesp = 0;
}
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index dcf51f0..ffc4533 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -228,6 +228,8 @@ struct hostapd_data {
unsigned int cs_c_off_beacon;
unsigned int cs_c_off_proberesp;
int csa_in_progress;
+ unsigned int cs_c_off_ecsa_beacon;
+ unsigned int cs_c_off_ecsa_proberesp;
/* BSS Load */
unsigned int bss_load_update_timeout;
@@ -402,6 +404,9 @@ struct hostapd_iface {
u64 last_channel_time_busy;
u8 channel_utilization;
+ /* eCSA IE will be added only if operating class is specified */
+ u8 cs_oper_class;
+
unsigned int dfs_cac_ms;
struct os_reltime dfs_cac_start;
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index d462ac8..9e3363e 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -172,6 +172,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
case 0: /* Bits 0-7 */
if (hapd->iconf->obss_interval)
*pos |= 0x01; /* Bit 0 - Coexistence management */
+ if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)
+ *pos |= 0x04; /* Bit 2 - Extended Channel Switching */
break;
case 1: /* Bits 8-15 */
if (hapd->conf->proxy_arp)
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 44530ce..cc67658 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -247,6 +247,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.9.1
More information about the Hostap
mailing list