Merge "cfg80211: validate beacon int as part of iface combinations"
This commit is contained in:
commit
aff86d3b4f
2 changed files with 63 additions and 46 deletions
|
@ -796,19 +796,15 @@ struct cfg80211_csa_settings {
|
||||||
* @iftype_num: array with the number of interfaces of each interface
|
* @iftype_num: array with the number of interfaces of each interface
|
||||||
* type. The index is the interface type as specified in &enum
|
* type. The index is the interface type as specified in &enum
|
||||||
* nl80211_iftype.
|
* nl80211_iftype.
|
||||||
* @beacon_int_gcd: a value specifying GCD of all beaconing interfaces,
|
* @new_beacon_int: set this to the beacon interval of a new interface
|
||||||
* the GCD of a single value is considered the value itself, so for
|
* that's not operating yet, if such is to be checked as part of
|
||||||
* a single interface this should be set to that interface's beacon
|
* the verification
|
||||||
* interval
|
|
||||||
* @beacon_int_different: a flag indicating whether or not all beacon
|
|
||||||
* intervals (of beaconing interfaces) are different or not.
|
|
||||||
*/
|
*/
|
||||||
struct iface_combination_params {
|
struct iface_combination_params {
|
||||||
int num_different_channels;
|
int num_different_channels;
|
||||||
u8 radar_detect;
|
u8 radar_detect;
|
||||||
int iftype_num[NUM_NL80211_IFTYPES];
|
int iftype_num[NUM_NL80211_IFTYPES];
|
||||||
u32 beacon_int_gcd;
|
u32 new_beacon_int;
|
||||||
bool beacon_int_different;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <net/dsfield.h>
|
#include <net/dsfield.h>
|
||||||
#include <linux/if_vlan.h>
|
#include <linux/if_vlan.h>
|
||||||
#include <linux/mpls.h>
|
#include <linux/mpls.h>
|
||||||
|
#include <linux/gcd.h>
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "rdev-ops.h"
|
#include "rdev-ops.h"
|
||||||
|
|
||||||
|
@ -1482,47 +1483,53 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
|
EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
|
||||||
|
|
||||||
|
static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
|
||||||
|
u32 *beacon_int_gcd,
|
||||||
|
bool *beacon_int_different)
|
||||||
|
{
|
||||||
|
struct wireless_dev *wdev;
|
||||||
|
|
||||||
|
*beacon_int_gcd = 0;
|
||||||
|
*beacon_int_different = false;
|
||||||
|
|
||||||
|
list_for_each_entry(wdev, &wiphy->wdev_list, list) {
|
||||||
|
if (!wdev->beacon_interval)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!*beacon_int_gcd) {
|
||||||
|
*beacon_int_gcd = wdev->beacon_interval;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wdev->beacon_interval == *beacon_int_gcd)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*beacon_int_different = true;
|
||||||
|
*beacon_int_gcd = gcd(*beacon_int_gcd, wdev->beacon_interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_beacon_int && *beacon_int_gcd != new_beacon_int) {
|
||||||
|
if (*beacon_int_gcd)
|
||||||
|
*beacon_int_different = true;
|
||||||
|
*beacon_int_gcd = gcd(*beacon_int_gcd, new_beacon_int);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
|
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
|
||||||
enum nl80211_iftype iftype, u32 beacon_int)
|
enum nl80211_iftype iftype, u32 beacon_int)
|
||||||
{
|
{
|
||||||
struct wireless_dev *wdev;
|
/*
|
||||||
struct iface_combination_params params = {
|
* This is just a basic pre-condition check; if interface combinations
|
||||||
.beacon_int_gcd = beacon_int, /* GCD(n) = n */
|
* are possible the driver must already be checking those with a call
|
||||||
};
|
* to cfg80211_check_combinations(), in which case we'll validate more
|
||||||
|
* through the cfg80211_calculate_bi_data() call and code in
|
||||||
|
* cfg80211_iter_combinations().
|
||||||
|
*/
|
||||||
|
|
||||||
if (beacon_int < 10 || beacon_int > 10000)
|
if (beacon_int < 10 || beacon_int > 10000)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
params.iftype_num[iftype] = 1;
|
return 0;
|
||||||
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
|
|
||||||
if (!wdev->beacon_interval)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
params.iftype_num[wdev->iftype]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
|
|
||||||
u32 bi_prev = wdev->beacon_interval;
|
|
||||||
|
|
||||||
if (!wdev->beacon_interval)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* slight optimisation - skip identical BIs */
|
|
||||||
if (wdev->beacon_interval == beacon_int)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
params.beacon_int_different = true;
|
|
||||||
|
|
||||||
/* Get the GCD */
|
|
||||||
while (bi_prev != 0) {
|
|
||||||
u32 tmp_bi = bi_prev;
|
|
||||||
|
|
||||||
bi_prev = params.beacon_int_gcd % bi_prev;
|
|
||||||
params.beacon_int_gcd = tmp_bi;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cfg80211_check_combinations(&rdev->wiphy, ¶ms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cfg80211_iter_combinations(struct wiphy *wiphy,
|
int cfg80211_iter_combinations(struct wiphy *wiphy,
|
||||||
|
@ -1536,6 +1543,21 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
|
||||||
int i, j, iftype;
|
int i, j, iftype;
|
||||||
int num_interfaces = 0;
|
int num_interfaces = 0;
|
||||||
u32 used_iftypes = 0;
|
u32 used_iftypes = 0;
|
||||||
|
u32 beacon_int_gcd;
|
||||||
|
bool beacon_int_different;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a bit strange, since the iteration used to rely only on
|
||||||
|
* the data given by the driver, but here it now relies on context,
|
||||||
|
* in form of the currently operating interfaces.
|
||||||
|
* This is OK for all current users, and saves us from having to
|
||||||
|
* push the GCD calculations into all the drivers.
|
||||||
|
* In the future, this should probably rely more on data that's in
|
||||||
|
* cfg80211 already - the only thing not would appear to be any new
|
||||||
|
* interfaces (while being brought up) and channel/radar data.
|
||||||
|
*/
|
||||||
|
cfg80211_calculate_bi_data(wiphy, params->new_beacon_int,
|
||||||
|
&beacon_int_gcd, &beacon_int_different);
|
||||||
|
|
||||||
if (params->radar_detect) {
|
if (params->radar_detect) {
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
@ -1598,12 +1620,11 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
|
||||||
if ((all_iftypes & used_iftypes) != used_iftypes)
|
if ((all_iftypes & used_iftypes) != used_iftypes)
|
||||||
goto cont;
|
goto cont;
|
||||||
|
|
||||||
if (params->beacon_int_gcd) {
|
if (beacon_int_gcd) {
|
||||||
if (c->beacon_int_min_gcd &&
|
if (c->beacon_int_min_gcd &&
|
||||||
params->beacon_int_gcd < c->beacon_int_min_gcd)
|
beacon_int_gcd < c->beacon_int_min_gcd)
|
||||||
goto cont;
|
goto cont;
|
||||||
if (!c->beacon_int_min_gcd &&
|
if (!c->beacon_int_min_gcd && beacon_int_different)
|
||||||
params->beacon_int_different)
|
|
||||||
goto cont;
|
goto cont;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue