|
@@ -22,31 +22,23 @@
|
|
|
#include "mesh.h"
|
|
#include "mesh.h"
|
|
|
#include "wme.h"
|
|
#include "wme.h"
|
|
|
|
|
|
|
|
-static int ieee80211_set_mu_mimo_follow(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
- struct vif_params *params)
|
|
|
|
|
|
|
+static void ieee80211_set_mu_mimo_follow(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
+ struct vif_params *params)
|
|
|
{
|
|
{
|
|
|
- struct ieee80211_local *local = sdata->local;
|
|
|
|
|
- struct ieee80211_sub_if_data *monitor_sdata;
|
|
|
|
|
bool mu_mimo_groups = false;
|
|
bool mu_mimo_groups = false;
|
|
|
bool mu_mimo_follow = false;
|
|
bool mu_mimo_follow = false;
|
|
|
|
|
|
|
|
- monitor_sdata = rtnl_dereference(local->monitor_sdata);
|
|
|
|
|
-
|
|
|
|
|
- if (!monitor_sdata)
|
|
|
|
|
- return -EOPNOTSUPP;
|
|
|
|
|
-
|
|
|
|
|
if (params->vht_mumimo_groups) {
|
|
if (params->vht_mumimo_groups) {
|
|
|
u64 membership;
|
|
u64 membership;
|
|
|
|
|
|
|
|
BUILD_BUG_ON(sizeof(membership) != WLAN_MEMBERSHIP_LEN);
|
|
BUILD_BUG_ON(sizeof(membership) != WLAN_MEMBERSHIP_LEN);
|
|
|
|
|
|
|
|
- memcpy(monitor_sdata->vif.bss_conf.mu_group.membership,
|
|
|
|
|
|
|
+ memcpy(sdata->vif.bss_conf.mu_group.membership,
|
|
|
params->vht_mumimo_groups, WLAN_MEMBERSHIP_LEN);
|
|
params->vht_mumimo_groups, WLAN_MEMBERSHIP_LEN);
|
|
|
- memcpy(monitor_sdata->vif.bss_conf.mu_group.position,
|
|
|
|
|
|
|
+ memcpy(sdata->vif.bss_conf.mu_group.position,
|
|
|
params->vht_mumimo_groups + WLAN_MEMBERSHIP_LEN,
|
|
params->vht_mumimo_groups + WLAN_MEMBERSHIP_LEN,
|
|
|
WLAN_USER_POSITION_LEN);
|
|
WLAN_USER_POSITION_LEN);
|
|
|
- ieee80211_bss_info_change_notify(monitor_sdata,
|
|
|
|
|
- BSS_CHANGED_MU_GROUPS);
|
|
|
|
|
|
|
+ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_MU_GROUPS);
|
|
|
/* don't care about endianness - just check for 0 */
|
|
/* don't care about endianness - just check for 0 */
|
|
|
memcpy(&membership, params->vht_mumimo_groups,
|
|
memcpy(&membership, params->vht_mumimo_groups,
|
|
|
WLAN_MEMBERSHIP_LEN);
|
|
WLAN_MEMBERSHIP_LEN);
|
|
@@ -56,11 +48,64 @@ static int ieee80211_set_mu_mimo_follow(struct ieee80211_sub_if_data *sdata,
|
|
|
if (params->vht_mumimo_follow_addr) {
|
|
if (params->vht_mumimo_follow_addr) {
|
|
|
mu_mimo_follow =
|
|
mu_mimo_follow =
|
|
|
is_valid_ether_addr(params->vht_mumimo_follow_addr);
|
|
is_valid_ether_addr(params->vht_mumimo_follow_addr);
|
|
|
- ether_addr_copy(monitor_sdata->u.mntr.mu_follow_addr,
|
|
|
|
|
|
|
+ ether_addr_copy(sdata->u.mntr.mu_follow_addr,
|
|
|
params->vht_mumimo_follow_addr);
|
|
params->vht_mumimo_follow_addr);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- monitor_sdata->vif.mu_mimo_owner = mu_mimo_groups || mu_mimo_follow;
|
|
|
|
|
|
|
+ sdata->vif.mu_mimo_owner = mu_mimo_groups || mu_mimo_follow;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
+ struct vif_params *params)
|
|
|
|
|
+{
|
|
|
|
|
+ struct ieee80211_local *local = sdata->local;
|
|
|
|
|
+ struct ieee80211_sub_if_data *monitor_sdata;
|
|
|
|
|
+
|
|
|
|
|
+ /* check flags first */
|
|
|
|
|
+ if (params->flags && ieee80211_sdata_running(sdata)) {
|
|
|
|
|
+ u32 mask = MONITOR_FLAG_COOK_FRAMES | MONITOR_FLAG_ACTIVE;
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Prohibit MONITOR_FLAG_COOK_FRAMES and
|
|
|
|
|
+ * MONITOR_FLAG_ACTIVE to be changed while the
|
|
|
|
|
+ * interface is up.
|
|
|
|
|
+ * Else we would need to add a lot of cruft
|
|
|
|
|
+ * to update everything:
|
|
|
|
|
+ * cooked_mntrs, monitor and all fif_* counters
|
|
|
|
|
+ * reconfigure hardware
|
|
|
|
|
+ */
|
|
|
|
|
+ if ((params->flags & mask) != (sdata->u.mntr.flags & mask))
|
|
|
|
|
+ return -EBUSY;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* also validate MU-MIMO change */
|
|
|
|
|
+ monitor_sdata = rtnl_dereference(local->monitor_sdata);
|
|
|
|
|
+
|
|
|
|
|
+ if (!monitor_sdata &&
|
|
|
|
|
+ (params->vht_mumimo_groups || params->vht_mumimo_follow_addr))
|
|
|
|
|
+ return -EOPNOTSUPP;
|
|
|
|
|
+
|
|
|
|
|
+ /* apply all changes now - no failures allowed */
|
|
|
|
|
+
|
|
|
|
|
+ if (monitor_sdata)
|
|
|
|
|
+ ieee80211_set_mu_mimo_follow(monitor_sdata, params);
|
|
|
|
|
+
|
|
|
|
|
+ if (params->flags) {
|
|
|
|
|
+ if (ieee80211_sdata_running(sdata)) {
|
|
|
|
|
+ ieee80211_adjust_monitor_flags(sdata, -1);
|
|
|
|
|
+ sdata->u.mntr.flags = params->flags;
|
|
|
|
|
+ ieee80211_adjust_monitor_flags(sdata, 1);
|
|
|
|
|
+
|
|
|
|
|
+ ieee80211_configure_filter(local);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Because the interface is down, ieee80211_do_stop
|
|
|
|
|
+ * and ieee80211_do_open take care of "everything"
|
|
|
|
|
+ * mentioned in the comment above.
|
|
|
|
|
+ */
|
|
|
|
|
+ sdata->u.mntr.flags = params->flags;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
@@ -83,13 +128,11 @@ static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
|
|
|
sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
|
sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
|
|
|
|
|
|
|
if (type == NL80211_IFTYPE_MONITOR) {
|
|
if (type == NL80211_IFTYPE_MONITOR) {
|
|
|
- err = ieee80211_set_mu_mimo_follow(sdata, params);
|
|
|
|
|
|
|
+ err = ieee80211_set_mon_options(sdata, params);
|
|
|
if (err) {
|
|
if (err) {
|
|
|
ieee80211_if_remove(sdata);
|
|
ieee80211_if_remove(sdata);
|
|
|
return NULL;
|
|
return NULL;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- sdata->u.mntr.flags = params->flags;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return wdev;
|
|
return wdev;
|
|
@@ -124,46 +167,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
|
|
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
|
|
|
- struct ieee80211_local *local = sdata->local;
|
|
|
|
|
- int err;
|
|
|
|
|
-
|
|
|
|
|
- err = ieee80211_set_mu_mimo_follow(sdata, params);
|
|
|
|
|
- if (err)
|
|
|
|
|
- return err;
|
|
|
|
|
-
|
|
|
|
|
- if (!params->flags)
|
|
|
|
|
- return 0;
|
|
|
|
|
-
|
|
|
|
|
- if (ieee80211_sdata_running(sdata)) {
|
|
|
|
|
- u32 mask = MONITOR_FLAG_COOK_FRAMES |
|
|
|
|
|
- MONITOR_FLAG_ACTIVE;
|
|
|
|
|
-
|
|
|
|
|
- /*
|
|
|
|
|
- * Prohibit MONITOR_FLAG_COOK_FRAMES and
|
|
|
|
|
- * MONITOR_FLAG_ACTIVE to be changed while the
|
|
|
|
|
- * interface is up.
|
|
|
|
|
- * Else we would need to add a lot of cruft
|
|
|
|
|
- * to update everything:
|
|
|
|
|
- * cooked_mntrs, monitor and all fif_* counters
|
|
|
|
|
- * reconfigure hardware
|
|
|
|
|
- */
|
|
|
|
|
- if ((params->flags & mask) !=
|
|
|
|
|
- (sdata->u.mntr.flags & mask))
|
|
|
|
|
- return -EBUSY;
|
|
|
|
|
-
|
|
|
|
|
- ieee80211_adjust_monitor_flags(sdata, -1);
|
|
|
|
|
- sdata->u.mntr.flags = params->flags;
|
|
|
|
|
- ieee80211_adjust_monitor_flags(sdata, 1);
|
|
|
|
|
-
|
|
|
|
|
- ieee80211_configure_filter(local);
|
|
|
|
|
- } else {
|
|
|
|
|
- /*
|
|
|
|
|
- * Because the interface is down, ieee80211_do_stop
|
|
|
|
|
- * and ieee80211_do_open take care of "everything"
|
|
|
|
|
- * mentioned in the comment above.
|
|
|
|
|
- */
|
|
|
|
|
- sdata->u.mntr.flags = params->flags;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ ret = ieee80211_set_mon_options(sdata, params);
|
|
|
|
|
+ if (ret)
|
|
|
|
|
+ return ret;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|