Add support for eCSA
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>
Tue, 8 Sep 2015 09:46:15 +0000 (12:46 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 3 Oct 2015 17:00:50 +0000 (20:00 +0300)
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>
src/ap/beacon.c
src/ap/hostapd.c
src/ap/hostapd.h
src/ap/ieee802_11_shared.c
src/common/ieee802_11_defs.h

index ea6b009..f9bbf1a 100644 (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)
 {
        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,
-                                 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;
 
        *csa_counter_off = 0;
-       pos = hostapd_eid_csa(hapd, pos);
+       *ecsa_counter_off = 0;
+
+       curr_pos = hostapd_eid_csa(hapd, curr_pos);
+
+       /* save an offset to the csa counter - should be last byte */
+       if (curr_pos != pos)
+               *csa_counter_off = curr_pos - start - 1;
 
-       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);
+       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
-               pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
+               curr_pos = hostapd_eid_wb_chsw_wrapper(hapd, curr_pos);
 #endif /* CONFIG_IEEE80211AC */
        }
-
-       return pos;
+       return curr_pos;
 }
 
 
@@ -449,7 +478,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) {
@@ -1018,7 +1048,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) {
index 89bfe5b..bf16e74 100644 (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_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;
 }
@@ -2863,6 +2865,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;
 }
 
 
index dcf51f0..ffc4533 100644 (file)
@@ -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;
 
index d462ac8..9e3363e 100644 (file)
@@ -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)
index 44530ce..cc67658 100644 (file)
 #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