Add support for eCSA

Extended channel switch provides an ability to switch between operating
classes and is required for P2P Devices by the P2P specification when
switching in 5 GHz.

When the operating class is provided for channel switch, the AP/P2P GO
will use eCSA IE in addition to the regular CSA IE both on 2.4 GHz and 5
GHz bands.

Transitions between different hw_modes are not supported.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
This commit is contained in:
Andrei Otcheretianski 2015-09-08 12:46:15 +03:00 committed by Jouni Malinen
parent 366179d218
commit 6315bfdba2
5 changed files with 56 additions and 13 deletions

View file

@ -310,6 +310,22 @@ static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid)
} }
static u8 * hostapd_eid_ecsa(struct hostapd_data *hapd, u8 *eid)
{
if (!hapd->cs_freq_params.channel || !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;
return eid;
}
static u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid) static u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid)
{ {
u8 sec_ch; u8 sec_ch;
@ -333,26 +349,39 @@ static u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid)
static u8 * hostapd_add_csa_elems(struct hostapd_data *hapd, u8 *pos, static u8 * hostapd_add_csa_elems(struct hostapd_data *hapd, u8 *pos,
u8 *start, unsigned int *csa_counter_off) 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; return pos;
*csa_counter_off = 0; *csa_counter_off = 0;
pos = hostapd_eid_csa(hapd, pos); *ecsa_counter_off = 0;
if (pos != old_pos) { curr_pos = hostapd_eid_csa(hapd, curr_pos);
/* save an offset to the counter - should be last byte */
*csa_counter_off = pos - start - 1; /* save an offset to the csa counter - should be last byte */
pos = hostapd_eid_secondary_channel(hapd, pos); 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);
#ifdef CONFIG_IEEE80211AC #ifdef CONFIG_IEEE80211AC
pos = hostapd_eid_wb_chsw_wrapper(hapd, pos); curr_pos = hostapd_eid_wb_chsw_wrapper(hapd, curr_pos);
#endif /* CONFIG_IEEE80211AC */ #endif /* CONFIG_IEEE80211AC */
} }
return curr_pos;
return pos;
} }
@ -449,7 +478,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
pos = hostapd_eid_roaming_consortium(hapd, pos); pos = hostapd_eid_roaming_consortium(hapd, pos);
pos = hostapd_add_csa_elems(hapd, pos, (u8 *)resp, 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 #ifdef CONFIG_FST
if (hapd->iface->fst_ies) { if (hapd->iface->fst_ies) {
@ -1018,7 +1048,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
tailpos = hostapd_eid_adv_proto(hapd, tailpos); tailpos = hostapd_eid_adv_proto(hapd, tailpos);
tailpos = hostapd_eid_roaming_consortium(hapd, tailpos); tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
tailpos = hostapd_add_csa_elems(hapd, tailpos, tail, 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 #ifdef CONFIG_FST
if (hapd->iface->fst_ies) { if (hapd->iface->fst_ies) {

View file

@ -2850,6 +2850,8 @@ static int hostapd_fill_csa_settings(struct hostapd_data *hapd,
settings->counter_offset_beacon[0] = hapd->cs_c_off_beacon; settings->counter_offset_beacon[0] = hapd->cs_c_off_beacon;
settings->counter_offset_presp[0] = hapd->cs_c_off_proberesp; 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; return 0;
} }
@ -2863,6 +2865,8 @@ void hostapd_cleanup_cs_params(struct hostapd_data *hapd)
hapd->cs_c_off_beacon = 0; hapd->cs_c_off_beacon = 0;
hapd->cs_c_off_proberesp = 0; hapd->cs_c_off_proberesp = 0;
hapd->csa_in_progress = 0; hapd->csa_in_progress = 0;
hapd->cs_c_off_ecsa_beacon = 0;
hapd->cs_c_off_ecsa_proberesp = 0;
} }

View file

@ -228,6 +228,8 @@ struct hostapd_data {
unsigned int cs_c_off_beacon; unsigned int cs_c_off_beacon;
unsigned int cs_c_off_proberesp; unsigned int cs_c_off_proberesp;
int csa_in_progress; int csa_in_progress;
unsigned int cs_c_off_ecsa_beacon;
unsigned int cs_c_off_ecsa_proberesp;
/* BSS Load */ /* BSS Load */
unsigned int bss_load_update_timeout; unsigned int bss_load_update_timeout;
@ -402,6 +404,9 @@ struct hostapd_iface {
u64 last_channel_time_busy; u64 last_channel_time_busy;
u8 channel_utilization; u8 channel_utilization;
/* eCSA IE will be added only if operating class is specified */
u8 cs_oper_class;
unsigned int dfs_cac_ms; unsigned int dfs_cac_ms;
struct os_reltime dfs_cac_start; struct os_reltime dfs_cac_start;

View file

@ -172,6 +172,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
case 0: /* Bits 0-7 */ case 0: /* Bits 0-7 */
if (hapd->iconf->obss_interval) if (hapd->iconf->obss_interval)
*pos |= 0x01; /* Bit 0 - Coexistence management */ *pos |= 0x01; /* Bit 0 - Coexistence management */
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)
*pos |= 0x04; /* Bit 2 - Extended Channel Switching */
break; break;
case 1: /* Bits 8-15 */ case 1: /* Bits 8-15 */
if (hapd->conf->proxy_arp) if (hapd->conf->proxy_arp)

View file

@ -247,6 +247,7 @@
#define WLAN_EID_TIMEOUT_INTERVAL 56 #define WLAN_EID_TIMEOUT_INTERVAL 56
#define WLAN_EID_RIC_DATA 57 #define WLAN_EID_RIC_DATA 57
#define WLAN_EID_SUPPORTED_OPERATING_CLASSES 59 #define WLAN_EID_SUPPORTED_OPERATING_CLASSES 59
#define WLAN_EID_EXT_CHANSWITCH_ANN 60
#define WLAN_EID_HT_OPERATION 61 #define WLAN_EID_HT_OPERATION 61
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62 #define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
#define WLAN_EID_WAPI 68 #define WLAN_EID_WAPI 68