wifi: mac80211: handle TDLS negotiation with MLO
Userspace can now select the link to use for TDLS management frames (indicating e.g. which BSSID should be used), use the link_id received from cfg80211 to build the frames. Signed-off-by: Mukesh Sisodiya <mukesh.sisodiya@intel.com> Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Link: https://lore.kernel.org/r/20230616094948.ce1fc230b505.Ie773c5679805001f5a52680d68d9ce0232c57648@changeid [Benjamin fixed some locking] Co-developed-by: Benjamin Berg <benjamin.berg@intel.com> Signed-off-by: Benjamin Berg <benjamin.berg@intel.com> [fix sta mutex locking too] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
c6112046b1
commit
78a7ea370d
@ -39,9 +39,10 @@ void ieee80211_tdls_peer_del_work(struct work_struct *wk)
|
||||
mutex_unlock(&local->mtx);
|
||||
}
|
||||
|
||||
static void ieee80211_tdls_add_ext_capab(struct ieee80211_sub_if_data *sdata,
|
||||
static void ieee80211_tdls_add_ext_capab(struct ieee80211_link_data *link,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = link->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
bool chan_switch = local->hw.wiphy->features &
|
||||
@ -50,7 +51,7 @@ static void ieee80211_tdls_add_ext_capab(struct ieee80211_sub_if_data *sdata,
|
||||
!ifmgd->tdls_wider_bw_prohibited;
|
||||
bool buffer_sta = ieee80211_hw_check(&local->hw,
|
||||
SUPPORTS_TDLS_BUFFER_STA);
|
||||
struct ieee80211_supported_band *sband = ieee80211_get_sband(sdata);
|
||||
struct ieee80211_supported_band *sband = ieee80211_get_link_sband(link);
|
||||
bool vht = sband && sband->vht_cap.vht_supported;
|
||||
u8 *pos = skb_put(skb, 10);
|
||||
|
||||
@ -152,13 +153,13 @@ ieee80211_tdls_add_supp_channels(struct ieee80211_sub_if_data *sdata,
|
||||
*pos = 2 * subband_cnt;
|
||||
}
|
||||
|
||||
static void ieee80211_tdls_add_oper_classes(struct ieee80211_sub_if_data *sdata,
|
||||
static void ieee80211_tdls_add_oper_classes(struct ieee80211_link_data *link,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
u8 *pos;
|
||||
u8 op_class;
|
||||
|
||||
if (!ieee80211_chandef_to_operating_class(&sdata->vif.bss_conf.chandef,
|
||||
if (!ieee80211_chandef_to_operating_class(&link->conf->chandef,
|
||||
&op_class))
|
||||
return;
|
||||
|
||||
@ -180,7 +181,7 @@ static void ieee80211_tdls_add_bss_coex_ie(struct sk_buff *skb)
|
||||
*pos++ = WLAN_BSS_COEX_INFORMATION_REQUEST;
|
||||
}
|
||||
|
||||
static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata,
|
||||
static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_link_data *link,
|
||||
u16 status_code)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
@ -189,7 +190,8 @@ static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata,
|
||||
if (status_code != 0)
|
||||
return 0;
|
||||
|
||||
sband = ieee80211_get_sband(sdata);
|
||||
sband = ieee80211_get_link_sband(link);
|
||||
|
||||
if (sband && sband->band == NL80211_BAND_2GHZ) {
|
||||
return WLAN_CAPABILITY_SHORT_SLOT_TIME |
|
||||
WLAN_CAPABILITY_SHORT_PREAMBLE;
|
||||
@ -198,10 +200,11 @@ static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ieee80211_tdls_add_link_ie(struct ieee80211_sub_if_data *sdata,
|
||||
static void ieee80211_tdls_add_link_ie(struct ieee80211_link_data *link,
|
||||
struct sk_buff *skb, const u8 *peer,
|
||||
bool initiator)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = link->sdata;
|
||||
struct ieee80211_tdls_lnkie *lnkid;
|
||||
const u8 *init_addr, *rsp_addr;
|
||||
|
||||
@ -218,7 +221,7 @@ static void ieee80211_tdls_add_link_ie(struct ieee80211_sub_if_data *sdata,
|
||||
lnkid->ie_type = WLAN_EID_LINK_ID;
|
||||
lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
|
||||
|
||||
memcpy(lnkid->bssid, sdata->deflink.u.mgd.bssid, ETH_ALEN);
|
||||
memcpy(lnkid->bssid, link->u.mgd.bssid, ETH_ALEN);
|
||||
memcpy(lnkid->init_sta, init_addr, ETH_ALEN);
|
||||
memcpy(lnkid->resp_sta, rsp_addr, ETH_ALEN);
|
||||
}
|
||||
@ -359,11 +362,12 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_tdls_add_setup_start_ies(struct ieee80211_link_data *link,
|
||||
struct sk_buff *skb, const u8 *peer,
|
||||
u8 action_code, bool initiator,
|
||||
const u8 *extra_ies, size_t extra_ies_len)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = link->sdata;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_sta_ht_cap ht_cap;
|
||||
@ -372,8 +376,8 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
|
||||
size_t offset = 0, noffset;
|
||||
u8 *pos;
|
||||
|
||||
sband = ieee80211_get_sband(sdata);
|
||||
if (!sband)
|
||||
sband = ieee80211_get_link_sband(link);
|
||||
if (WARN_ON_ONCE(!sband))
|
||||
return;
|
||||
|
||||
ieee80211_add_srates_ie(sdata, skb, false, sband->band);
|
||||
@ -397,7 +401,7 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
|
||||
offset = noffset;
|
||||
}
|
||||
|
||||
ieee80211_tdls_add_ext_capab(sdata, skb);
|
||||
ieee80211_tdls_add_ext_capab(link, skb);
|
||||
|
||||
/* add the QoS element if we support it */
|
||||
if (local->hw.queues >= IEEE80211_NUM_ACS &&
|
||||
@ -426,20 +430,16 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
|
||||
offset = noffset;
|
||||
}
|
||||
|
||||
mutex_lock(&local->sta_mtx);
|
||||
|
||||
/* we should have the peer STA if we're already responding */
|
||||
if (action_code == WLAN_TDLS_SETUP_RESPONSE) {
|
||||
sta = sta_info_get(sdata, peer);
|
||||
if (WARN_ON_ONCE(!sta)) {
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
if (WARN_ON_ONCE(!sta))
|
||||
return;
|
||||
}
|
||||
|
||||
sta->tdls_chandef = sdata->vif.bss_conf.chandef;
|
||||
sta->tdls_chandef = link->conf->chandef;
|
||||
}
|
||||
|
||||
ieee80211_tdls_add_oper_classes(sdata, skb);
|
||||
ieee80211_tdls_add_oper_classes(link, skb);
|
||||
|
||||
/*
|
||||
* with TDLS we can switch channels, and HT-caps are not necessarily
|
||||
@ -472,7 +472,7 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
|
||||
(ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
|
||||
ieee80211_tdls_add_bss_coex_ie(skb);
|
||||
|
||||
ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
|
||||
ieee80211_tdls_add_link_ie(link, skb, peer, initiator);
|
||||
|
||||
/* add any custom IEs that go before VHT capabilities */
|
||||
if (extra_ies_len) {
|
||||
@ -529,8 +529,6 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_tdls_chandef_vht_upgrade(sdata, sta);
|
||||
}
|
||||
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
|
||||
/* add any remaining IEs */
|
||||
if (extra_ies_len) {
|
||||
noffset = extra_ies_len;
|
||||
@ -540,31 +538,29 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_link_data *link,
|
||||
struct sk_buff *skb, const u8 *peer,
|
||||
bool initiator, const u8 *extra_ies,
|
||||
size_t extra_ies_len)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = link->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
size_t offset = 0, noffset;
|
||||
struct sta_info *sta, *ap_sta;
|
||||
struct ieee80211_supported_band *sband;
|
||||
u8 *pos;
|
||||
|
||||
sband = ieee80211_get_sband(sdata);
|
||||
if (!sband)
|
||||
sband = ieee80211_get_link_sband(link);
|
||||
if (WARN_ON_ONCE(!sband))
|
||||
return;
|
||||
|
||||
mutex_lock(&local->sta_mtx);
|
||||
|
||||
sta = sta_info_get(sdata, peer);
|
||||
ap_sta = sta_info_get(sdata, sdata->deflink.u.mgd.bssid);
|
||||
if (WARN_ON_ONCE(!sta || !ap_sta)) {
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
return;
|
||||
}
|
||||
ap_sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
|
||||
|
||||
sta->tdls_chandef = sdata->vif.bss_conf.chandef;
|
||||
if (WARN_ON_ONCE(!sta || !ap_sta))
|
||||
return;
|
||||
|
||||
sta->tdls_chandef = link->conf->chandef;
|
||||
|
||||
/* add any custom IEs that go before the QoS IE */
|
||||
if (extra_ies_len) {
|
||||
@ -610,11 +606,11 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
|
||||
ieee80211_ie_build_ht_oper(pos, &sta->sta.deflink.ht_cap,
|
||||
&sdata->vif.bss_conf.chandef, prot,
|
||||
&link->conf->chandef, prot,
|
||||
true);
|
||||
}
|
||||
|
||||
ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
|
||||
ieee80211_tdls_add_link_ie(link, skb, peer, initiator);
|
||||
|
||||
/* only include VHT-operation if not on the 2.4GHz band */
|
||||
if (sband->band != NL80211_BAND_2GHZ &&
|
||||
@ -631,8 +627,6 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
|
||||
&sta->tdls_chandef);
|
||||
}
|
||||
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
|
||||
/* add any remaining IEs */
|
||||
if (extra_ies_len) {
|
||||
noffset = extra_ies_len;
|
||||
@ -641,7 +635,7 @@ ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211_tdls_add_chan_switch_req_ies(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_tdls_add_chan_switch_req_ies(struct ieee80211_link_data *link,
|
||||
struct sk_buff *skb, const u8 *peer,
|
||||
bool initiator, const u8 *extra_ies,
|
||||
size_t extra_ies_len, u8 oper_class,
|
||||
@ -670,7 +664,7 @@ ieee80211_tdls_add_chan_switch_req_ies(struct ieee80211_sub_if_data *sdata,
|
||||
offset = noffset;
|
||||
}
|
||||
|
||||
ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
|
||||
ieee80211_tdls_add_link_ie(link, skb, peer, initiator);
|
||||
|
||||
/* add any remaining IEs */
|
||||
if (extra_ies_len) {
|
||||
@ -680,20 +674,20 @@ ieee80211_tdls_add_chan_switch_req_ies(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211_tdls_add_chan_switch_resp_ies(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_tdls_add_chan_switch_resp_ies(struct ieee80211_link_data *link,
|
||||
struct sk_buff *skb, const u8 *peer,
|
||||
u16 status_code, bool initiator,
|
||||
const u8 *extra_ies,
|
||||
size_t extra_ies_len)
|
||||
{
|
||||
if (status_code == 0)
|
||||
ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
|
||||
ieee80211_tdls_add_link_ie(link, skb, peer, initiator);
|
||||
|
||||
if (extra_ies_len)
|
||||
skb_put_data(skb, extra_ies, extra_ies_len);
|
||||
}
|
||||
|
||||
static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata,
|
||||
static void ieee80211_tdls_add_ies(struct ieee80211_link_data *link,
|
||||
struct sk_buff *skb, const u8 *peer,
|
||||
u8 action_code, u16 status_code,
|
||||
bool initiator, const u8 *extra_ies,
|
||||
@ -705,7 +699,8 @@ static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata,
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
|
||||
if (status_code == 0)
|
||||
ieee80211_tdls_add_setup_start_ies(sdata, skb, peer,
|
||||
ieee80211_tdls_add_setup_start_ies(link,
|
||||
skb, peer,
|
||||
action_code,
|
||||
initiator,
|
||||
extra_ies,
|
||||
@ -713,7 +708,7 @@ static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata,
|
||||
break;
|
||||
case WLAN_TDLS_SETUP_CONFIRM:
|
||||
if (status_code == 0)
|
||||
ieee80211_tdls_add_setup_cfm_ies(sdata, skb, peer,
|
||||
ieee80211_tdls_add_setup_cfm_ies(link, skb, peer,
|
||||
initiator, extra_ies,
|
||||
extra_ies_len);
|
||||
break;
|
||||
@ -722,16 +717,17 @@ static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata,
|
||||
if (extra_ies_len)
|
||||
skb_put_data(skb, extra_ies, extra_ies_len);
|
||||
if (status_code == 0 || action_code == WLAN_TDLS_TEARDOWN)
|
||||
ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
|
||||
ieee80211_tdls_add_link_ie(link, skb,
|
||||
peer, initiator);
|
||||
break;
|
||||
case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
|
||||
ieee80211_tdls_add_chan_switch_req_ies(sdata, skb, peer,
|
||||
ieee80211_tdls_add_chan_switch_req_ies(link, skb, peer,
|
||||
initiator, extra_ies,
|
||||
extra_ies_len,
|
||||
oper_class, chandef);
|
||||
break;
|
||||
case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
|
||||
ieee80211_tdls_add_chan_switch_resp_ies(sdata, skb, peer,
|
||||
ieee80211_tdls_add_chan_switch_resp_ies(link, skb, peer,
|
||||
status_code,
|
||||
initiator, extra_ies,
|
||||
extra_ies_len);
|
||||
@ -742,6 +738,7 @@ static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
static int
|
||||
ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct ieee80211_link_data *link,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, struct sk_buff *skb)
|
||||
{
|
||||
@ -766,7 +763,7 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
|
||||
skb_put(skb, sizeof(tf->u.setup_req));
|
||||
tf->u.setup_req.dialog_token = dialog_token;
|
||||
tf->u.setup_req.capability =
|
||||
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata,
|
||||
cpu_to_le16(ieee80211_get_tdls_sta_capab(link,
|
||||
status_code));
|
||||
break;
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
@ -777,7 +774,7 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
|
||||
tf->u.setup_resp.status_code = cpu_to_le16(status_code);
|
||||
tf->u.setup_resp.dialog_token = dialog_token;
|
||||
tf->u.setup_resp.capability =
|
||||
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata,
|
||||
cpu_to_le16(ieee80211_get_tdls_sta_capab(link,
|
||||
status_code));
|
||||
break;
|
||||
case WLAN_TDLS_SETUP_CONFIRM:
|
||||
@ -824,7 +821,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
|
||||
|
||||
static int
|
||||
ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
const u8 *peer, struct ieee80211_link_data *link,
|
||||
u8 action_code, u8 dialog_token,
|
||||
u16 status_code, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
@ -833,8 +831,7 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
|
||||
mgmt = skb_put_zero(skb, 24);
|
||||
memcpy(mgmt->da, peer, ETH_ALEN);
|
||||
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
|
||||
memcpy(mgmt->bssid, sdata->deflink.u.mgd.bssid, ETH_ALEN);
|
||||
|
||||
memcpy(mgmt->bssid, link->u.mgd.bssid, ETH_ALEN);
|
||||
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
||||
IEEE80211_STYPE_ACTION);
|
||||
|
||||
@ -847,7 +844,7 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
|
||||
mgmt->u.action.u.tdls_discover_resp.dialog_token =
|
||||
dialog_token;
|
||||
mgmt->u.action.u.tdls_discover_resp.capability =
|
||||
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata,
|
||||
cpu_to_le16(ieee80211_get_tdls_sta_capab(link,
|
||||
status_code));
|
||||
break;
|
||||
default:
|
||||
@ -859,15 +856,23 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
|
||||
|
||||
static struct sk_buff *
|
||||
ieee80211_tdls_build_mgmt_packet_data(struct ieee80211_sub_if_data *sdata,
|
||||
const u8 *peer, u8 action_code,
|
||||
u8 dialog_token, u16 status_code,
|
||||
bool initiator, const u8 *extra_ies,
|
||||
size_t extra_ies_len, u8 oper_class,
|
||||
const u8 *peer, int link_id,
|
||||
u8 action_code, u8 dialog_token,
|
||||
u16 status_code, bool initiator,
|
||||
const u8 *extra_ies, size_t extra_ies_len,
|
||||
u8 oper_class,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
struct ieee80211_link_data *link;
|
||||
|
||||
link_id = link_id >= 0 ? link_id : 0;
|
||||
rcu_read_lock();
|
||||
link = rcu_dereference(sdata->link[link_id]);
|
||||
if (WARN_ON(!link))
|
||||
goto unlock;
|
||||
|
||||
skb = netdev_alloc_skb(sdata->dev,
|
||||
local->hw.extra_tx_headroom +
|
||||
@ -887,7 +892,7 @@ ieee80211_tdls_build_mgmt_packet_data(struct ieee80211_sub_if_data *sdata,
|
||||
extra_ies_len +
|
||||
sizeof(struct ieee80211_tdls_lnkie));
|
||||
if (!skb)
|
||||
return NULL;
|
||||
goto unlock;
|
||||
|
||||
skb_reserve(skb, local->hw.extra_tx_headroom);
|
||||
|
||||
@ -900,13 +905,13 @@ ieee80211_tdls_build_mgmt_packet_data(struct ieee80211_sub_if_data *sdata,
|
||||
case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
|
||||
case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
|
||||
ret = ieee80211_prep_tdls_encap_data(local->hw.wiphy,
|
||||
sdata->dev, peer,
|
||||
sdata->dev, link, peer,
|
||||
action_code, dialog_token,
|
||||
status_code, skb);
|
||||
break;
|
||||
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
|
||||
ret = ieee80211_prep_tdls_direct(local->hw.wiphy, sdata->dev,
|
||||
peer, action_code,
|
||||
peer, link, action_code,
|
||||
dialog_token, status_code,
|
||||
skb);
|
||||
break;
|
||||
@ -918,19 +923,23 @@ ieee80211_tdls_build_mgmt_packet_data(struct ieee80211_sub_if_data *sdata,
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
ieee80211_tdls_add_ies(sdata, skb, peer, action_code, status_code,
|
||||
ieee80211_tdls_add_ies(link, skb, peer, action_code, status_code,
|
||||
initiator, extra_ies, extra_ies_len, oper_class,
|
||||
chandef);
|
||||
rcu_read_unlock();
|
||||
return skb;
|
||||
|
||||
fail:
|
||||
dev_kfree_skb(skb);
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
const u8 *peer, int link_id,
|
||||
u8 action_code, u8 dialog_token,
|
||||
u16 status_code, u32 peer_capability,
|
||||
bool initiator, const u8 *extra_ies,
|
||||
size_t extra_ies_len, u8 oper_class,
|
||||
@ -988,7 +997,8 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
skb = ieee80211_tdls_build_mgmt_packet_data(sdata, peer, action_code,
|
||||
skb = ieee80211_tdls_build_mgmt_packet_data(sdata, peer,
|
||||
link_id, action_code,
|
||||
dialog_token, status_code,
|
||||
initiator, extra_ies,
|
||||
extra_ies_len, oper_class,
|
||||
@ -999,7 +1009,7 @@ ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
|
||||
}
|
||||
|
||||
if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
|
||||
ieee80211_tx_skb(sdata, skb);
|
||||
ieee80211_tx_skb_tid(sdata, skb, 7, link_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1066,7 +1076,8 @@ fail:
|
||||
|
||||
static int
|
||||
ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
const u8 *peer, int link_id,
|
||||
u8 action_code, u8 dialog_token,
|
||||
u16 status_code, u32 peer_capability, bool initiator,
|
||||
const u8 *extra_ies, size_t extra_ies_len)
|
||||
{
|
||||
@ -1115,7 +1126,8 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
/* we cannot take the mutex while preparing the setup packet */
|
||||
ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
|
||||
ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer,
|
||||
link_id, action_code,
|
||||
dialog_token, status_code,
|
||||
peer_capability, initiator,
|
||||
extra_ies, extra_ies_len, 0,
|
||||
@ -1139,7 +1151,8 @@ out_unlock:
|
||||
|
||||
static int
|
||||
ieee80211_tdls_mgmt_teardown(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
const u8 *peer, int link_id,
|
||||
u8 action_code, u8 dialog_token,
|
||||
u16 status_code, u32 peer_capability,
|
||||
bool initiator, const u8 *extra_ies,
|
||||
size_t extra_ies_len)
|
||||
@ -1159,7 +1172,8 @@ ieee80211_tdls_mgmt_teardown(struct wiphy *wiphy, struct net_device *dev,
|
||||
IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN);
|
||||
ieee80211_flush_queues(local, sdata, false);
|
||||
|
||||
ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
|
||||
ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer,
|
||||
link_id, action_code,
|
||||
dialog_token, status_code,
|
||||
peer_capability, initiator,
|
||||
extra_ies, extra_ies_len, 0,
|
||||
@ -1204,13 +1218,14 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
|
||||
switch (action_code) {
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
ret = ieee80211_tdls_mgmt_setup(wiphy, dev, peer, action_code,
|
||||
ret = ieee80211_tdls_mgmt_setup(wiphy, dev, peer,
|
||||
link_id, action_code,
|
||||
dialog_token, status_code,
|
||||
peer_capability, initiator,
|
||||
extra_ies, extra_ies_len);
|
||||
break;
|
||||
case WLAN_TDLS_TEARDOWN:
|
||||
ret = ieee80211_tdls_mgmt_teardown(wiphy, dev, peer,
|
||||
ret = ieee80211_tdls_mgmt_teardown(wiphy, dev, peer, link_id,
|
||||
action_code, dialog_token,
|
||||
status_code,
|
||||
peer_capability, initiator,
|
||||
@ -1228,7 +1243,7 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
|
||||
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
|
||||
/* no special handling */
|
||||
ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer,
|
||||
action_code,
|
||||
link_id, action_code,
|
||||
dialog_token,
|
||||
status_code,
|
||||
peer_capability,
|
||||
@ -1240,8 +1255,8 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
|
||||
break;
|
||||
}
|
||||
|
||||
tdls_dbg(sdata, "TDLS mgmt action %d peer %pM status %d\n",
|
||||
action_code, peer, ret);
|
||||
tdls_dbg(sdata, "TDLS mgmt action %d peer %pM link_id %d status %d\n",
|
||||
action_code, peer, link_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1497,6 +1512,7 @@ ieee80211_tdls_ch_sw_tmpl_get(struct sta_info *sta, u8 oper_class,
|
||||
int extra_ies_len = 2 + sizeof(struct ieee80211_ch_switch_timing);
|
||||
u8 *pos = extra_ies;
|
||||
struct sk_buff *skb;
|
||||
int link_id = sta->sta.valid_links ? ffs(sta->sta.valid_links) - 1 : 0;
|
||||
|
||||
/*
|
||||
* if chandef points to a wide channel add a Secondary-Channel
|
||||
@ -1524,6 +1540,7 @@ ieee80211_tdls_ch_sw_tmpl_get(struct sta_info *sta, u8 oper_class,
|
||||
iee80211_tdls_add_ch_switch_timing(pos, 0, 0);
|
||||
|
||||
skb = ieee80211_tdls_build_mgmt_packet_data(sdata, sta->sta.addr,
|
||||
link_id,
|
||||
WLAN_TDLS_CHANNEL_SWITCH_REQUEST,
|
||||
0, 0, !sta->sta.tdls_initiator,
|
||||
extra_ies, extra_ies_len,
|
||||
@ -1644,11 +1661,13 @@ ieee80211_tdls_ch_sw_resp_tmpl_get(struct sta_info *sta,
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct sk_buff *skb;
|
||||
u8 extra_ies[2 + sizeof(struct ieee80211_ch_switch_timing)];
|
||||
int link_id = sta->sta.valid_links ? ffs(sta->sta.valid_links) - 1 : 0;
|
||||
|
||||
/* initial timing are always zero in the template */
|
||||
iee80211_tdls_add_ch_switch_timing(extra_ies, 0, 0);
|
||||
|
||||
skb = ieee80211_tdls_build_mgmt_packet_data(sdata, sta->sta.addr,
|
||||
link_id,
|
||||
WLAN_TDLS_CHANNEL_SWITCH_RESPONSE,
|
||||
0, 0, !sta->sta.tdls_initiator,
|
||||
extra_ies, sizeof(extra_ies), 0, NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user