aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2016-09-19 03:44:44 -0400
committerJohannes Berg <johannes.berg@intel.com>2016-09-26 04:23:48 -0400
commit8564e38206de2ff005a27c8d7c2ce3869a44f0dd (patch)
tree2c6a9ae667d5bf80a6789d1201dfb9a492ea99d1 /net/wireless
parenta7c7fbff6a408d00431c705bbe3dfc5f51e3f1c4 (diff)
cfg80211: add checks for beacon rate, extend to mesh
The previous commit added support for specifying the beacon rate for AP mode. Add features checks to this, and extend it to also support the rate configuration for mesh networks. For IBSS it's not as simple due to joining etc., so that's not yet supported. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c46
1 files changed, 35 insertions, 11 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a10484da60c0..b8441e60b0f6 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3569,13 +3569,12 @@ out:
3569 return 0; 3569 return 0;
3570} 3570}
3571 3571
3572static int validate_beacon_tx_rate(struct cfg80211_ap_settings *params) 3572static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev,
3573 enum nl80211_band band,
3574 struct cfg80211_bitrate_mask *beacon_rate)
3573{ 3575{
3574 u32 rate, count_ht, count_vht, i; 3576 u32 count_ht, count_vht, i;
3575 enum nl80211_band band; 3577 u32 rate = beacon_rate->control[band].legacy;
3576
3577 band = params->chandef.chan->band;
3578 rate = params->beacon_rate.control[band].legacy;
3579 3578
3580 /* Allow only one rate */ 3579 /* Allow only one rate */
3581 if (hweight32(rate) > 1) 3580 if (hweight32(rate) > 1)
@@ -3583,9 +3582,9 @@ static int validate_beacon_tx_rate(struct cfg80211_ap_settings *params)
3583 3582
3584 count_ht = 0; 3583 count_ht = 0;
3585 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { 3584 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
3586 if (hweight8(params->beacon_rate.control[band].ht_mcs[i]) > 1) { 3585 if (hweight8(beacon_rate->control[band].ht_mcs[i]) > 1) {
3587 return -EINVAL; 3586 return -EINVAL;
3588 } else if (params->beacon_rate.control[band].ht_mcs[i]) { 3587 } else if (beacon_rate->control[band].ht_mcs[i]) {
3589 count_ht++; 3588 count_ht++;
3590 if (count_ht > 1) 3589 if (count_ht > 1)
3591 return -EINVAL; 3590 return -EINVAL;
@@ -3596,9 +3595,9 @@ static int validate_beacon_tx_rate(struct cfg80211_ap_settings *params)
3596 3595
3597 count_vht = 0; 3596 count_vht = 0;
3598 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) { 3597 for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
3599 if (hweight16(params->beacon_rate.control[band].vht_mcs[i]) > 1) { 3598 if (hweight16(beacon_rate->control[band].vht_mcs[i]) > 1) {
3600 return -EINVAL; 3599 return -EINVAL;
3601 } else if (params->beacon_rate.control[band].vht_mcs[i]) { 3600 } else if (beacon_rate->control[band].vht_mcs[i]) {
3602 count_vht++; 3601 count_vht++;
3603 if (count_vht > 1) 3602 if (count_vht > 1)
3604 return -EINVAL; 3603 return -EINVAL;
@@ -3610,6 +3609,19 @@ static int validate_beacon_tx_rate(struct cfg80211_ap_settings *params)
3610 if ((count_ht && count_vht) || (!rate && !count_ht && !count_vht)) 3609 if ((count_ht && count_vht) || (!rate && !count_ht && !count_vht))
3611 return -EINVAL; 3610 return -EINVAL;
3612 3611
3612 if (rate &&
3613 !wiphy_ext_feature_isset(&rdev->wiphy,
3614 NL80211_EXT_FEATURE_BEACON_RATE_LEGACY))
3615 return -EINVAL;
3616 if (count_ht &&
3617 !wiphy_ext_feature_isset(&rdev->wiphy,
3618 NL80211_EXT_FEATURE_BEACON_RATE_HT))
3619 return -EINVAL;
3620 if (count_vht &&
3621 !wiphy_ext_feature_isset(&rdev->wiphy,
3622 NL80211_EXT_FEATURE_BEACON_RATE_VHT))
3623 return -EINVAL;
3624
3613 return 0; 3625 return 0;
3614} 3626}
3615 3627
@@ -3847,7 +3859,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
3847 if (err) 3859 if (err)
3848 return err; 3860 return err;
3849 3861
3850 err = validate_beacon_tx_rate(&params); 3862 err = validate_beacon_tx_rate(rdev, params.chandef.chan->band,
3863 &params.beacon_rate);
3851 if (err) 3864 if (err)
3852 return err; 3865 return err;
3853 } 3866 }
@@ -9406,6 +9419,17 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
9406 return err; 9419 return err;
9407 } 9420 }
9408 9421
9422 if (info->attrs[NL80211_ATTR_TX_RATES]) {
9423 err = nl80211_parse_tx_bitrate_mask(info, &setup.beacon_rate);
9424 if (err)
9425 return err;
9426
9427 err = validate_beacon_tx_rate(rdev, setup.chandef.chan->band,
9428 &setup.beacon_rate);
9429 if (err)
9430 return err;
9431 }
9432
9409 return cfg80211_join_mesh(rdev, dev, &setup, &cfg); 9433 return cfg80211_join_mesh(rdev, dev, &setup, &cfg);
9410} 9434}
9411 9435