Skip to content

Commit

Permalink
nl80211: add HT/VHT capabilities to AP parameters
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Johannes Berg committed Feb 8, 2017
1 parent a4956dc commit 66cd794
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 2 deletions.
3 changes: 2 additions & 1 deletion include/linux/ieee80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1043,8 +1043,9 @@ struct ieee80211_mgmt {
} u;
} __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_VHT_PHY 126

/* mgmt header + 1 byte category code */
#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)
Expand Down
8 changes: 8 additions & 0 deletions include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,10 @@ struct cfg80211_bitrate_mask {
* @pbss: If set, start as a PCP instead of AP. Relevant for DMG
* networks.
* @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_chan_def chandef;
Expand All @@ -768,6 +772,10 @@ struct cfg80211_ap_settings {
const struct cfg80211_acl_data *acl;
bool pbss;
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;
};

/**
Expand Down
47 changes: 46 additions & 1 deletion net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2015-2016 Intel Deutschland GmbH
* Copyright 2015-2017 Intel Deutschland GmbH
*/

#include <linux/if.h>
Expand Down Expand Up @@ -3743,6 +3743,49 @@ static int nl80211_parse_beacon(struct nlattr *attrs[],
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 = &params->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,
struct cfg80211_ap_settings *params)
{
Expand Down Expand Up @@ -3971,6 +4014,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
return PTR_ERR(params.acl);
}

nl80211_calculate_ap_params(&params);

wdev_lock(wdev);
err = rdev_start_ap(rdev, dev, &params);
if (!err) {
Expand Down

0 comments on commit 66cd794

Please sign in to comment.