Skip to content

Commit 0c317a0

Browse files
Purushottam Kushwahajmberg-intel
authored andcommitted
cfg80211: support virtual interfaces with different beacon intervals
This commit provides a mechanism for the host drivers to advertise the support for different beacon intervals among the respective interface combinations in a group, through NL80211_IFACE_COMB_BI_MIN_GCD (u32). This value will be compared against GCD of all beaconing interfaces of matching combinations. If the driver doesn't advertise this value, the old behaviour where all beacon intervals must be identical is retained. If it is specified, then any beacon interval for an interface in the interface combination as well as the GCD of all active beacon intervals in the combination must be greater or equal to this value. Signed-off-by: Purushottam Kushwaha <pkushwah@qti.qualcomm.com> [change commit message, some variable names, small other things] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
1 parent e227300 commit 0c317a0

File tree

5 files changed

+70
-12
lines changed

5 files changed

+70
-12
lines changed

include/net/cfg80211.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,11 +784,19 @@ struct cfg80211_csa_settings {
784784
* @iftype_num: array with the number of interfaces of each interface
785785
* type. The index is the interface type as specified in &enum
786786
* nl80211_iftype.
787+
* @beacon_int_gcd: a value specifying GCD of all beaconing interfaces,
788+
* the GCD of a single value is considered the value itself, so for
789+
* a single interface this should be set to that interface's beacon
790+
* interval
791+
* @beacon_int_different: a flag indicating whether or not all beacon
792+
* intervals (of beaconing interfaces) are different or not.
787793
*/
788794
struct iface_combination_params {
789795
int num_different_channels;
790796
u8 radar_detect;
791797
int iftype_num[NUM_NL80211_IFTYPES];
798+
u32 beacon_int_gcd;
799+
bool beacon_int_different;
792800
};
793801

794802
/**
@@ -3100,6 +3108,12 @@ struct ieee80211_iface_limit {
31003108
* only in special cases.
31013109
* @radar_detect_widths: bitmap of channel widths supported for radar detection
31023110
* @radar_detect_regions: bitmap of regions supported for radar detection
3111+
* @beacon_int_min_gcd: This interface combination supports different
3112+
* beacon intervals.
3113+
* = 0 - all beacon intervals for different interface must be same.
3114+
* > 0 - any beacon interval for the interface part of this combination AND
3115+
* *GCD* of all beacon intervals from beaconing interfaces of this
3116+
* combination must be greater or equal to this value.
31033117
*
31043118
* With this structure the driver can describe which interface
31053119
* combinations it supports concurrently.
@@ -3158,6 +3172,7 @@ struct ieee80211_iface_combination {
31583172
bool beacon_int_infra_match;
31593173
u8 radar_detect_widths;
31603174
u8 radar_detect_regions;
3175+
u32 beacon_int_min_gcd;
31613176
};
31623177

31633178
struct ieee80211_txrx_stypes {

include/uapi/linux/nl80211.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4280,15 +4280,18 @@ enum nl80211_iface_limit_attrs {
42804280
* of supported channel widths for radar detection.
42814281
* @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap
42824282
* of supported regulatory regions for radar detection.
4283+
* @NL80211_IFACE_COMB_BI_MIN_GCD: u32 attribute specifying the minimum GCD of
4284+
* different beacon intervals supported by all the interface combinations
4285+
* in this group (if not present, all beacon intervals be identical).
42834286
* @NUM_NL80211_IFACE_COMB: number of attributes
42844287
* @MAX_NL80211_IFACE_COMB: highest attribute number
42854288
*
42864289
* Examples:
42874290
* limits = [ #{STA} <= 1, #{AP} <= 1 ], matching BI, channels = 1, max = 2
42884291
* => allows an AP and a STA that must match BIs
42894292
*
4290-
* numbers = [ #{AP, P2P-GO} <= 8 ], channels = 1, max = 8
4291-
* => allows 8 of AP/GO
4293+
* numbers = [ #{AP, P2P-GO} <= 8 ], BI min gcd, channels = 1, max = 8,
4294+
* => allows 8 of AP/GO that can have BI gcd >= min gcd
42924295
*
42934296
* numbers = [ #{STA} <= 2 ], channels = 2, max = 2
42944297
* => allows two STAs on different channels
@@ -4314,6 +4317,7 @@ enum nl80211_if_combination_attrs {
43144317
NL80211_IFACE_COMB_NUM_CHANNELS,
43154318
NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
43164319
NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
4320+
NL80211_IFACE_COMB_BI_MIN_GCD,
43174321

43184322
/* keep last */
43194323
NUM_NL80211_IFACE_COMB,

net/wireless/core.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
475475
u32 *mask);
476476

477477
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
478-
u32 beacon_int);
478+
enum nl80211_iftype iftype, u32 beacon_int);
479479

480480
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
481481
enum nl80211_iftype iftype, int num);

net/wireless/nl80211.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,10 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy,
10751075
nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
10761076
c->radar_detect_regions)))
10771077
goto nla_put_failure;
1078+
if (c->beacon_int_min_gcd &&
1079+
nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
1080+
c->beacon_int_min_gcd))
1081+
goto nla_put_failure;
10781082

10791083
nla_nest_end(msg, nl_combi);
10801084
}
@@ -3803,7 +3807,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
38033807
params.dtim_period =
38043808
nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
38053809

3806-
err = cfg80211_validate_beacon_int(rdev, params.beacon_interval);
3810+
err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
3811+
params.beacon_interval);
38073812
if (err)
38083813
return err;
38093814

@@ -8152,7 +8157,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
81528157
ibss.beacon_interval =
81538158
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
81548159

8155-
err = cfg80211_validate_beacon_int(rdev, ibss.beacon_interval);
8160+
err = cfg80211_validate_beacon_int(rdev, NL80211_IFTYPE_ADHOC,
8161+
ibss.beacon_interval);
81568162
if (err)
81578163
return err;
81588164

@@ -9417,7 +9423,9 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
94179423
setup.beacon_interval =
94189424
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
94199425

9420-
err = cfg80211_validate_beacon_int(rdev, setup.beacon_interval);
9426+
err = cfg80211_validate_beacon_int(rdev,
9427+
NL80211_IFTYPE_MESH_POINT,
9428+
setup.beacon_interval);
94219429
if (err)
94229430
return err;
94239431
}

net/wireless/util.c

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,24 +1559,46 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
15591559
EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
15601560

15611561
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
1562-
u32 beacon_int)
1562+
enum nl80211_iftype iftype, u32 beacon_int)
15631563
{
15641564
struct wireless_dev *wdev;
1565-
int res = 0;
1565+
struct iface_combination_params params = {
1566+
.beacon_int_gcd = beacon_int, /* GCD(n) = n */
1567+
};
15661568

15671569
if (beacon_int < 10 || beacon_int > 10000)
15681570
return -EINVAL;
15691571

1572+
params.iftype_num[iftype] = 1;
15701573
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
15711574
if (!wdev->beacon_interval)
15721575
continue;
1573-
if (wdev->beacon_interval != beacon_int) {
1574-
res = -EINVAL;
1575-
break;
1576+
1577+
params.iftype_num[wdev->iftype]++;
1578+
}
1579+
1580+
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
1581+
u32 bi_prev = wdev->beacon_interval;
1582+
1583+
if (!wdev->beacon_interval)
1584+
continue;
1585+
1586+
/* slight optimisation - skip identical BIs */
1587+
if (wdev->beacon_interval == beacon_int)
1588+
continue;
1589+
1590+
params.beacon_int_different = true;
1591+
1592+
/* Get the GCD */
1593+
while (bi_prev != 0) {
1594+
u32 tmp_bi = bi_prev;
1595+
1596+
bi_prev = params.beacon_int_gcd % bi_prev;
1597+
params.beacon_int_gcd = tmp_bi;
15761598
}
15771599
}
15781600

1579-
return res;
1601+
return cfg80211_check_combinations(&rdev->wiphy, &params);
15801602
}
15811603

15821604
int cfg80211_iter_combinations(struct wiphy *wiphy,
@@ -1652,6 +1674,15 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
16521674
if ((all_iftypes & used_iftypes) != used_iftypes)
16531675
goto cont;
16541676

1677+
if (params->beacon_int_gcd) {
1678+
if (c->beacon_int_min_gcd &&
1679+
params->beacon_int_gcd < c->beacon_int_min_gcd)
1680+
return -EINVAL;
1681+
if (!c->beacon_int_min_gcd &&
1682+
params->beacon_int_different)
1683+
goto cont;
1684+
}
1685+
16551686
/* This combination covered all interface types and
16561687
* supported the requested numbers, so we're good.
16571688
*/

0 commit comments

Comments
 (0)