Commit 9041c1fa authored by Arik Nemtsov's avatar Arik Nemtsov Committed by Johannes Berg

mac80211: track AP and peer STA TDLS chan-switch support

The AP or peer can prohibit TDLS channel switch via a bit in the
extended capabilities IE. Parse the IE and track this bit. Set an
appropriate STA flag if both the AP and peer STA support TDLS
channel-switching.

Add the new STA flag and the missing TDLS_INITIATOR to debugfs.
Signed-off-by: default avatarArik Nemtsov <arikx.nemtsov@intel.com>
Signed-off-by: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 78632a17
...@@ -1042,6 +1042,13 @@ static int sta_apply_parameters(struct ieee80211_local *local, ...@@ -1042,6 +1042,13 @@ static int sta_apply_parameters(struct ieee80211_local *local,
clear_sta_flag(sta, WLAN_STA_TDLS_PEER); clear_sta_flag(sta, WLAN_STA_TDLS_PEER);
} }
/* mark TDLS channel switch support, if the AP allows it */
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
!sdata->u.mgd.tdls_chan_switch_prohibited &&
params->ext_capab_len >= 4 &&
params->ext_capab[3] & WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)
set_sta_flag(sta, WLAN_STA_TDLS_CHAN_SWITCH);
if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) { if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) {
sta->sta.uapsd_queues = params->uapsd_queues; sta->sta.uapsd_queues = params->uapsd_queues;
sta->sta.max_sp = params->max_sp; sta->sta.max_sp = params->max_sp;
......
...@@ -74,7 +74,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, ...@@ -74,7 +74,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : ""
int res = scnprintf(buf, sizeof(buf), int res = scnprintf(buf, sizeof(buf),
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
TEST(AUTH), TEST(ASSOC), TEST(PS_STA), TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
TEST(PS_DRIVER), TEST(AUTHORIZED), TEST(PS_DRIVER), TEST(AUTHORIZED),
TEST(SHORT_PREAMBLE), TEST(SHORT_PREAMBLE),
...@@ -82,7 +82,8 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, ...@@ -82,7 +82,8 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
TEST(WDS), TEST(CLEAR_PS_FILT), TEST(WDS), TEST(CLEAR_PS_FILT),
TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), TEST(UAPSD), TEST(SP), TEST(TDLS_PEER),
TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT), TEST(TDLS_PEER_AUTH), TEST(TDLS_INITIATOR),
TEST(TDLS_CHAN_SWITCH), TEST(4ADDR_EVENT),
TEST(INSERTED), TEST(RATE_CONTROL), TEST(INSERTED), TEST(RATE_CONTROL),
TEST(TOFFSET_KNOWN), TEST(MPSP_OWNER), TEST(TOFFSET_KNOWN), TEST(MPSP_OWNER),
TEST(MPSP_RECIPIENT)); TEST(MPSP_RECIPIENT));
......
...@@ -531,6 +531,7 @@ struct ieee80211_if_managed { ...@@ -531,6 +531,7 @@ struct ieee80211_if_managed {
struct sk_buff *orig_teardown_skb; /* The original teardown skb */ struct sk_buff *orig_teardown_skb; /* The original teardown skb */
struct sk_buff *teardown_skb; /* A copy to send through the AP */ struct sk_buff *teardown_skb; /* A copy to send through the AP */
spinlock_t teardown_lock; /* To lock changing teardown_skb */ spinlock_t teardown_lock; /* To lock changing teardown_skb */
bool tdls_chan_switch_prohibited;
/* WMM-AC TSPEC support */ /* WMM-AC TSPEC support */
struct ieee80211_sta_tx_tspec tx_tspec[IEEE80211_NUM_ACS]; struct ieee80211_sta_tx_tspec tx_tspec[IEEE80211_NUM_ACS];
...@@ -1399,6 +1400,7 @@ struct ieee802_11_elems { ...@@ -1399,6 +1400,7 @@ struct ieee802_11_elems {
size_t total_len; size_t total_len;
/* pointers to IEs */ /* pointers to IEs */
const u8 *ext_capab;
const u8 *ssid; const u8 *ssid;
const u8 *supp_rates; const u8 *supp_rates;
const u8 *ds_params; const u8 *ds_params;
...@@ -1433,6 +1435,7 @@ struct ieee802_11_elems { ...@@ -1433,6 +1435,7 @@ struct ieee802_11_elems {
const struct ieee80211_mesh_chansw_params_ie *mesh_chansw_params_ie; const struct ieee80211_mesh_chansw_params_ie *mesh_chansw_params_ie;
/* length of them, respectively */ /* length of them, respectively */
u8 ext_capab_len;
u8 ssid_len; u8 ssid_len;
u8 supp_rates_len; u8 supp_rates_len;
u8 tim_len; u8 tim_len;
......
...@@ -2802,6 +2802,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, ...@@ -2802,6 +2802,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
} }
ifmgd->aid = aid; ifmgd->aid = aid;
ifmgd->tdls_chan_switch_prohibited =
elems.ext_capab && elems.ext_capab_len >= 5 &&
(elems.ext_capab[4] & WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED);
/* /*
* Some APs are erroneously not including some information in their * Some APs are erroneously not including some information in their
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
* packets. This means the link is enabled. * packets. This means the link is enabled.
* @WLAN_STA_TDLS_INITIATOR: We are the initiator of the TDLS link with this * @WLAN_STA_TDLS_INITIATOR: We are the initiator of the TDLS link with this
* station. * station.
* @WLAN_STA_TDLS_CHAN_SWITCH: This TDLS peer supports TDLS channel-switching
* @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was * @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was
* keeping station in power-save mode, reply when the driver * keeping station in power-save mode, reply when the driver
* unblocks the station. * unblocks the station.
...@@ -78,6 +79,7 @@ enum ieee80211_sta_info_flags { ...@@ -78,6 +79,7 @@ enum ieee80211_sta_info_flags {
WLAN_STA_TDLS_PEER, WLAN_STA_TDLS_PEER,
WLAN_STA_TDLS_PEER_AUTH, WLAN_STA_TDLS_PEER_AUTH,
WLAN_STA_TDLS_INITIATOR, WLAN_STA_TDLS_INITIATOR,
WLAN_STA_TDLS_CHAN_SWITCH,
WLAN_STA_UAPSD, WLAN_STA_UAPSD,
WLAN_STA_SP, WLAN_STA_SP,
WLAN_STA_4ADDR_EVENT, WLAN_STA_4ADDR_EVENT,
......
...@@ -831,6 +831,7 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, ...@@ -831,6 +831,7 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
case WLAN_EID_SECONDARY_CHANNEL_OFFSET: case WLAN_EID_SECONDARY_CHANNEL_OFFSET:
case WLAN_EID_WIDE_BW_CHANNEL_SWITCH: case WLAN_EID_WIDE_BW_CHANNEL_SWITCH:
case WLAN_EID_CHAN_SWITCH_PARAM: case WLAN_EID_CHAN_SWITCH_PARAM:
case WLAN_EID_EXT_CAPABILITY:
/* /*
* not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible * not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible
* that if the content gets bigger it might be needed more than once * that if the content gets bigger it might be needed more than once
...@@ -850,6 +851,10 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, ...@@ -850,6 +851,10 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
elem_parse_failed = false; elem_parse_failed = false;
switch (id) { switch (id) {
case WLAN_EID_EXT_CAPABILITY:
elems->ext_capab = pos;
elems->ext_capab_len = elen;
break;
case WLAN_EID_SSID: case WLAN_EID_SSID:
elems->ssid = pos; elems->ssid = pos;
elems->ssid_len = elen; elems->ssid_len = elen;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment