forked from Minki/linux
nl80211: add HT/VHT capabilities to AP parameters
For the benefit of drivers that rebuild IEs in firmware, parse the IEs for HT/VHT capabilities and the respective membership selector in the (extended) supported rates. This avoids duplicating the same code into all drivers that need this information. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
a4956dca07
commit
66cd794e3c
@ -1043,8 +1043,9 @@ struct ieee80211_mgmt {
|
|||||||
} u;
|
} u;
|
||||||
} __packed __aligned(2);
|
} __packed __aligned(2);
|
||||||
|
|
||||||
/* Supported Rates value encodings in 802.11n-2009 7.3.2.2 */
|
/* Supported rates membership selectors */
|
||||||
#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
|
#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
|
||||||
|
#define BSS_MEMBERSHIP_SELECTOR_VHT_PHY 126
|
||||||
|
|
||||||
/* mgmt header + 1 byte category code */
|
/* mgmt header + 1 byte category code */
|
||||||
#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)
|
#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)
|
||||||
|
@ -748,6 +748,10 @@ struct cfg80211_bitrate_mask {
|
|||||||
* @pbss: If set, start as a PCP instead of AP. Relevant for DMG
|
* @pbss: If set, start as a PCP instead of AP. Relevant for DMG
|
||||||
* networks.
|
* networks.
|
||||||
* @beacon_rate: bitrate to be used for beacons
|
* @beacon_rate: bitrate to be used for beacons
|
||||||
|
* @ht_cap: HT capabilities (or %NULL if HT isn't enabled)
|
||||||
|
* @vht_cap: VHT capabilities (or %NULL if VHT isn't enabled)
|
||||||
|
* @ht_required: stations must support HT
|
||||||
|
* @vht_required: stations must support VHT
|
||||||
*/
|
*/
|
||||||
struct cfg80211_ap_settings {
|
struct cfg80211_ap_settings {
|
||||||
struct cfg80211_chan_def chandef;
|
struct cfg80211_chan_def chandef;
|
||||||
@ -768,6 +772,10 @@ struct cfg80211_ap_settings {
|
|||||||
const struct cfg80211_acl_data *acl;
|
const struct cfg80211_acl_data *acl;
|
||||||
bool pbss;
|
bool pbss;
|
||||||
struct cfg80211_bitrate_mask beacon_rate;
|
struct cfg80211_bitrate_mask beacon_rate;
|
||||||
|
|
||||||
|
const struct ieee80211_ht_cap *ht_cap;
|
||||||
|
const struct ieee80211_vht_cap *vht_cap;
|
||||||
|
bool ht_required, vht_required;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||||
* Copyright 2015-2016 Intel Deutschland GmbH
|
* Copyright 2015-2017 Intel Deutschland GmbH
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
@ -3743,6 +3743,49 @@ static int nl80211_parse_beacon(struct nlattr *attrs[],
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
|
||||||
|
const u8 *rates)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!rates)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < rates[1]; i++) {
|
||||||
|
if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
|
||||||
|
params->ht_required = true;
|
||||||
|
if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)
|
||||||
|
params->vht_required = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since the nl80211 API didn't include, from the beginning, attributes about
|
||||||
|
* HT/VHT requirements/capabilities, we parse them out of the IEs for the
|
||||||
|
* benefit of drivers that rebuild IEs in the firmware.
|
||||||
|
*/
|
||||||
|
static void nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
|
||||||
|
{
|
||||||
|
const struct cfg80211_beacon_data *bcn = ¶ms->beacon;
|
||||||
|
size_t ies_len = bcn->beacon_ies_len;
|
||||||
|
const u8 *ies = bcn->beacon_ies;
|
||||||
|
const u8 *rates;
|
||||||
|
const u8 *cap;
|
||||||
|
|
||||||
|
rates = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies, ies_len);
|
||||||
|
nl80211_check_ap_rate_selectors(params, rates);
|
||||||
|
|
||||||
|
rates = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, ies, ies_len);
|
||||||
|
nl80211_check_ap_rate_selectors(params, rates);
|
||||||
|
|
||||||
|
cap = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len);
|
||||||
|
if (cap && cap[1] >= sizeof(*params->ht_cap))
|
||||||
|
params->ht_cap = (void *)(cap + 2);
|
||||||
|
cap = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, ies, ies_len);
|
||||||
|
if (cap && cap[1] >= sizeof(*params->vht_cap))
|
||||||
|
params->vht_cap = (void *)(cap + 2);
|
||||||
|
}
|
||||||
|
|
||||||
static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
|
static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
|
||||||
struct cfg80211_ap_settings *params)
|
struct cfg80211_ap_settings *params)
|
||||||
{
|
{
|
||||||
@ -3971,6 +4014,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|||||||
return PTR_ERR(params.acl);
|
return PTR_ERR(params.acl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nl80211_calculate_ap_params(¶ms);
|
||||||
|
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
err = rdev_start_ap(rdev, dev, ¶ms);
|
err = rdev_start_ap(rdev, dev, ¶ms);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
|
Loading…
Reference in New Issue
Block a user