@@ -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);
@@ -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;
}
@@ -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;
@@ -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