aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h4
-rw-r--r--include/uapi/linux/nl80211.h17
-rw-r--r--net/wireless/nl80211.c46
3 files changed, 54 insertions, 13 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index e0949c8bc2d1..ed37304fa09d 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -712,7 +712,7 @@ struct cfg80211_bitrate_mask {
712 * MAC address based access control 712 * MAC address based access control
713 * @pbss: If set, start as a PCP instead of AP. Relevant for DMG 713 * @pbss: If set, start as a PCP instead of AP. Relevant for DMG
714 * networks. 714 * networks.
715 * @beacon_rate: masks for setting user configured beacon tx rate. 715 * @beacon_rate: bitrate to be used for beacons
716 */ 716 */
717struct cfg80211_ap_settings { 717struct cfg80211_ap_settings {
718 struct cfg80211_chan_def chandef; 718 struct cfg80211_chan_def chandef;
@@ -1365,6 +1365,7 @@ struct mesh_config {
1365 * @beacon_interval: beacon interval to use 1365 * @beacon_interval: beacon interval to use
1366 * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a] 1366 * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a]
1367 * @basic_rates: basic rates to use when creating the mesh 1367 * @basic_rates: basic rates to use when creating the mesh
1368 * @beacon_rate: bitrate to be used for beacons
1368 * 1369 *
1369 * These parameters are fixed when the mesh is created. 1370 * These parameters are fixed when the mesh is created.
1370 */ 1371 */
@@ -1385,6 +1386,7 @@ struct mesh_setup {
1385 u16 beacon_interval; 1386 u16 beacon_interval;
1386 int mcast_rate[NUM_NL80211_BANDS]; 1387 int mcast_rate[NUM_NL80211_BANDS];
1387 u32 basic_rates; 1388 u32 basic_rates;
1389 struct cfg80211_bitrate_mask beacon_rate;
1388}; 1390};
1389 1391
1390/** 1392/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 220694151434..ec10d1b2838f 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1343,7 +1343,13 @@ enum nl80211_commands {
1343 * enum nl80211_band value is used as the index (nla_type() of the nested 1343 * enum nl80211_band value is used as the index (nla_type() of the nested
1344 * data. If a band is not included, it will be configured to allow all 1344 * data. If a band is not included, it will be configured to allow all
1345 * rates based on negotiated supported rates information. This attribute 1345 * rates based on negotiated supported rates information. This attribute
1346 * is used with %NL80211_CMD_SET_TX_BITRATE_MASK. 1346 * is used with %NL80211_CMD_SET_TX_BITRATE_MASK and with starting AP,
1347 * and joining mesh networks (not IBSS yet). In the later case, it must
1348 * specify just a single bitrate, which is to be used for the beacon.
1349 * The driver must also specify support for this with the extended
1350 * features NL80211_EXT_FEATURE_BEACON_RATE_LEGACY,
1351 * NL80211_EXT_FEATURE_BEACON_RATE_HT and
1352 * NL80211_EXT_FEATURE_BEACON_RATE_VHT.
1347 * 1353 *
1348 * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain 1354 * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain
1349 * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. 1355 * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME.
@@ -4551,6 +4557,12 @@ enum nl80211_feature_flags {
4551 * (if available). 4557 * (if available).
4552 * @NL80211_EXT_FEATURE_SET_SCAN_DWELL: This driver supports configuration of 4558 * @NL80211_EXT_FEATURE_SET_SCAN_DWELL: This driver supports configuration of
4553 * channel dwell time. 4559 * channel dwell time.
4560 * @NL80211_EXT_FEATURE_BEACON_RATE_LEGACY: Driver supports beacon rate
4561 * configuration (AP/mesh), supporting a legacy (non HT/VHT) rate.
4562 * @NL80211_EXT_FEATURE_BEACON_RATE_HT: Driver supports beacon rate
4563 * configuration (AP/mesh) with HT rates.
4564 * @NL80211_EXT_FEATURE_BEACON_RATE_VHT: Driver supports beacon rate
4565 * configuration (AP/mesh) with VHT rates.
4554 * 4566 *
4555 * @NUM_NL80211_EXT_FEATURES: number of extended features. 4567 * @NUM_NL80211_EXT_FEATURES: number of extended features.
4556 * @MAX_NL80211_EXT_FEATURES: highest extended feature index. 4568 * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -4562,6 +4574,9 @@ enum nl80211_ext_feature_index {
4562 NL80211_EXT_FEATURE_SCAN_START_TIME, 4574 NL80211_EXT_FEATURE_SCAN_START_TIME,
4563 NL80211_EXT_FEATURE_BSS_PARENT_TSF, 4575 NL80211_EXT_FEATURE_BSS_PARENT_TSF,
4564 NL80211_EXT_FEATURE_SET_SCAN_DWELL, 4576 NL80211_EXT_FEATURE_SET_SCAN_DWELL,
4577 NL80211_EXT_FEATURE_BEACON_RATE_LEGACY,
4578 NL80211_EXT_FEATURE_BEACON_RATE_HT,
4579 NL80211_EXT_FEATURE_BEACON_RATE_VHT,
4565 4580
4566 /* add new features before the definition below */ 4581 /* add new features before the definition below */
4567 NUM_NL80211_EXT_FEATURES, 4582 NUM_NL80211_EXT_FEATURES,
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