Loading include/net/cfg80211.h +4 −8 Original line number Diff line number Diff line Loading @@ -784,19 +784,15 @@ struct cfg80211_csa_settings { * @iftype_num: array with the number of interfaces of each interface * type. The index is the interface type as specified in &enum * nl80211_iftype. * @beacon_int_gcd: a value specifying GCD of all beaconing interfaces, * the GCD of a single value is considered the value itself, so for * a single interface this should be set to that interface's beacon * interval * @beacon_int_different: a flag indicating whether or not all beacon * intervals (of beaconing interfaces) are different or not. * @new_beacon_int: set this to the beacon interval of a new interface * that's not operating yet, if such is to be checked as part of * the verification */ struct iface_combination_params { int num_different_channels; u8 radar_detect; int iftype_num[NUM_NL80211_IFTYPES]; u32 beacon_int_gcd; bool beacon_int_different; u32 new_beacon_int; }; /** Loading net/wireless/util.c +53 −34 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/mpls.h> #include <net/ndisc.h> #include <linux/if_arp.h> #include <linux/gcd.h> #include "core.h" #include "rdev-ops.h" Loading Loading @@ -1559,47 +1560,53 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, } EXPORT_SYMBOL(ieee80211_chandef_to_operating_class); int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, enum nl80211_iftype iftype, u32 beacon_int) 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; struct iface_combination_params params = { .beacon_int_gcd = beacon_int, /* GCD(n) = n */ }; if (beacon_int < 10 || beacon_int > 10000) return -EINVAL; *beacon_int_gcd = 0; *beacon_int_different = false; params.iftype_num[iftype] = 1; list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { list_for_each_entry(wdev, &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) if (!*beacon_int_gcd) { *beacon_int_gcd = wdev->beacon_interval; continue; } /* slight optimisation - skip identical BIs */ if (wdev->beacon_interval == beacon_int) if (wdev->beacon_interval == *beacon_int_gcd) continue; params.beacon_int_different = true; /* Get the GCD */ while (bi_prev != 0) { u32 tmp_bi = bi_prev; *beacon_int_different = true; *beacon_int_gcd = gcd(*beacon_int_gcd, wdev->beacon_interval); } bi_prev = params.beacon_int_gcd % bi_prev; params.beacon_int_gcd = tmp_bi; 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); } } return cfg80211_check_combinations(&rdev->wiphy, ¶ms); int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, enum nl80211_iftype iftype, u32 beacon_int) { /* * This is just a basic pre-condition check; if interface combinations * 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) return -EINVAL; return 0; } int cfg80211_iter_combinations(struct wiphy *wiphy, Loading @@ -1613,6 +1620,21 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, int i, j, iftype; int num_interfaces = 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) { rcu_read_lock(); Loading Loading @@ -1675,14 +1697,11 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, if ((all_iftypes & used_iftypes) != used_iftypes) goto cont; if (params->beacon_int_gcd) { if (beacon_int_gcd) { if (c->beacon_int_min_gcd && params->beacon_int_gcd < c->beacon_int_min_gcd) { kfree(limits); return -EINVAL; } if (!c->beacon_int_min_gcd && params->beacon_int_different) beacon_int_gcd < c->beacon_int_min_gcd) goto cont; if (!c->beacon_int_min_gcd && beacon_int_different) goto cont; } Loading Loading
include/net/cfg80211.h +4 −8 Original line number Diff line number Diff line Loading @@ -784,19 +784,15 @@ struct cfg80211_csa_settings { * @iftype_num: array with the number of interfaces of each interface * type. The index is the interface type as specified in &enum * nl80211_iftype. * @beacon_int_gcd: a value specifying GCD of all beaconing interfaces, * the GCD of a single value is considered the value itself, so for * a single interface this should be set to that interface's beacon * interval * @beacon_int_different: a flag indicating whether or not all beacon * intervals (of beaconing interfaces) are different or not. * @new_beacon_int: set this to the beacon interval of a new interface * that's not operating yet, if such is to be checked as part of * the verification */ struct iface_combination_params { int num_different_channels; u8 radar_detect; int iftype_num[NUM_NL80211_IFTYPES]; u32 beacon_int_gcd; bool beacon_int_different; u32 new_beacon_int; }; /** Loading
net/wireless/util.c +53 −34 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/mpls.h> #include <net/ndisc.h> #include <linux/if_arp.h> #include <linux/gcd.h> #include "core.h" #include "rdev-ops.h" Loading Loading @@ -1559,47 +1560,53 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, } EXPORT_SYMBOL(ieee80211_chandef_to_operating_class); int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, enum nl80211_iftype iftype, u32 beacon_int) 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; struct iface_combination_params params = { .beacon_int_gcd = beacon_int, /* GCD(n) = n */ }; if (beacon_int < 10 || beacon_int > 10000) return -EINVAL; *beacon_int_gcd = 0; *beacon_int_different = false; params.iftype_num[iftype] = 1; list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { list_for_each_entry(wdev, &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) if (!*beacon_int_gcd) { *beacon_int_gcd = wdev->beacon_interval; continue; } /* slight optimisation - skip identical BIs */ if (wdev->beacon_interval == beacon_int) if (wdev->beacon_interval == *beacon_int_gcd) continue; params.beacon_int_different = true; /* Get the GCD */ while (bi_prev != 0) { u32 tmp_bi = bi_prev; *beacon_int_different = true; *beacon_int_gcd = gcd(*beacon_int_gcd, wdev->beacon_interval); } bi_prev = params.beacon_int_gcd % bi_prev; params.beacon_int_gcd = tmp_bi; 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); } } return cfg80211_check_combinations(&rdev->wiphy, ¶ms); int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, enum nl80211_iftype iftype, u32 beacon_int) { /* * This is just a basic pre-condition check; if interface combinations * 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) return -EINVAL; return 0; } int cfg80211_iter_combinations(struct wiphy *wiphy, Loading @@ -1613,6 +1620,21 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, int i, j, iftype; int num_interfaces = 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) { rcu_read_lock(); Loading Loading @@ -1675,14 +1697,11 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, if ((all_iftypes & used_iftypes) != used_iftypes) goto cont; if (params->beacon_int_gcd) { if (beacon_int_gcd) { if (c->beacon_int_min_gcd && params->beacon_int_gcd < c->beacon_int_min_gcd) { kfree(limits); return -EINVAL; } if (!c->beacon_int_min_gcd && params->beacon_int_different) beacon_int_gcd < c->beacon_int_min_gcd) goto cont; if (!c->beacon_int_min_gcd && beacon_int_different) goto cont; } Loading