mac80211: process and save VHT MU-MIMO group frame
The Group ID Management frame is an Action frame of category VHT. It is transmitted by the AP to assign or change the user position of a STA for one or more group IDs. Process and save the group membership data. Notify underlying driver of changes. Signed-off-by: Sara Sharon <sara.sharon@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
c799ba6eab
commit
23a1f8d44c
|
@ -843,6 +843,8 @@ enum ieee80211_vht_opmode_bits {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define WLAN_SA_QUERY_TR_ID_LEN 2
|
#define WLAN_SA_QUERY_TR_ID_LEN 2
|
||||||
|
#define WLAN_MEMBERSHIP_LEN 8
|
||||||
|
#define WLAN_USER_POSITION_LEN 16
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct ieee80211_tpc_report_ie
|
* struct ieee80211_tpc_report_ie
|
||||||
|
@ -989,6 +991,11 @@ struct ieee80211_mgmt {
|
||||||
u8 action_code;
|
u8 action_code;
|
||||||
u8 operating_mode;
|
u8 operating_mode;
|
||||||
} __packed vht_opmode_notif;
|
} __packed vht_opmode_notif;
|
||||||
|
struct {
|
||||||
|
u8 action_code;
|
||||||
|
u8 membership[WLAN_MEMBERSHIP_LEN];
|
||||||
|
u8 position[WLAN_USER_POSITION_LEN];
|
||||||
|
} __packed vht_group_notif;
|
||||||
struct {
|
struct {
|
||||||
u8 action_code;
|
u8 action_code;
|
||||||
u8 dialog_token;
|
u8 dialog_token;
|
||||||
|
|
|
@ -298,6 +298,7 @@ struct ieee80211_vif_chanctx_switch {
|
||||||
* note that this is only called when it changes after the channel
|
* note that this is only called when it changes after the channel
|
||||||
* context had been assigned.
|
* context had been assigned.
|
||||||
* @BSS_CHANGED_OCB: OCB join status changed
|
* @BSS_CHANGED_OCB: OCB join status changed
|
||||||
|
* @BSS_CHANGED_MU_GROUPS: VHT MU-MIMO group id or user position changed
|
||||||
*/
|
*/
|
||||||
enum ieee80211_bss_change {
|
enum ieee80211_bss_change {
|
||||||
BSS_CHANGED_ASSOC = 1<<0,
|
BSS_CHANGED_ASSOC = 1<<0,
|
||||||
|
@ -323,6 +324,7 @@ enum ieee80211_bss_change {
|
||||||
BSS_CHANGED_BEACON_INFO = 1<<20,
|
BSS_CHANGED_BEACON_INFO = 1<<20,
|
||||||
BSS_CHANGED_BANDWIDTH = 1<<21,
|
BSS_CHANGED_BANDWIDTH = 1<<21,
|
||||||
BSS_CHANGED_OCB = 1<<22,
|
BSS_CHANGED_OCB = 1<<22,
|
||||||
|
BSS_CHANGED_MU_GROUPS = 1<<23,
|
||||||
|
|
||||||
/* when adding here, make sure to change ieee80211_reconfig */
|
/* when adding here, make sure to change ieee80211_reconfig */
|
||||||
};
|
};
|
||||||
|
@ -435,6 +437,19 @@ struct ieee80211_event {
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ieee80211_mu_group_data - STA's VHT MU-MIMO group data
|
||||||
|
*
|
||||||
|
* This structure describes the group id data of VHT MU-MIMO
|
||||||
|
*
|
||||||
|
* @membership: 64 bits array - a bit is set if station is member of the group
|
||||||
|
* @position: 2 bits per group id indicating the position in the group
|
||||||
|
*/
|
||||||
|
struct ieee80211_mu_group_data {
|
||||||
|
u8 membership[WLAN_MEMBERSHIP_LEN];
|
||||||
|
u8 position[WLAN_USER_POSITION_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct ieee80211_bss_conf - holds the BSS's changing parameters
|
* struct ieee80211_bss_conf - holds the BSS's changing parameters
|
||||||
*
|
*
|
||||||
|
@ -477,6 +492,7 @@ struct ieee80211_event {
|
||||||
* @enable_beacon: whether beaconing should be enabled or not
|
* @enable_beacon: whether beaconing should be enabled or not
|
||||||
* @chandef: Channel definition for this BSS -- the hardware might be
|
* @chandef: Channel definition for this BSS -- the hardware might be
|
||||||
* configured a higher bandwidth than this BSS uses, for example.
|
* configured a higher bandwidth than this BSS uses, for example.
|
||||||
|
* @mu_group: VHT MU-MIMO group membership data
|
||||||
* @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation.
|
* @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation.
|
||||||
* This field is only valid when the channel is a wide HT/VHT channel.
|
* This field is only valid when the channel is a wide HT/VHT channel.
|
||||||
* Note that with TDLS this can be the case (channel is HT, protection must
|
* Note that with TDLS this can be the case (channel is HT, protection must
|
||||||
|
@ -535,6 +551,7 @@ struct ieee80211_bss_conf {
|
||||||
s32 cqm_rssi_thold;
|
s32 cqm_rssi_thold;
|
||||||
u32 cqm_rssi_hyst;
|
u32 cqm_rssi_hyst;
|
||||||
struct cfg80211_chan_def chandef;
|
struct cfg80211_chan_def chandef;
|
||||||
|
struct ieee80211_mu_group_data mu_group;
|
||||||
__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
|
__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
|
||||||
int arp_addr_cnt;
|
int arp_addr_cnt;
|
||||||
bool qos;
|
bool qos;
|
||||||
|
|
|
@ -1714,6 +1714,8 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
||||||
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta);
|
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta);
|
||||||
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta);
|
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta);
|
||||||
void ieee80211_sta_set_rx_nss(struct sta_info *sta);
|
void ieee80211_sta_set_rx_nss(struct sta_info *sta);
|
||||||
|
void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct ieee80211_mgmt *mgmt);
|
||||||
u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
||||||
struct sta_info *sta, u8 opmode,
|
struct sta_info *sta, u8 opmode,
|
||||||
enum ieee80211_band band);
|
enum ieee80211_band band);
|
||||||
|
|
|
@ -1271,6 +1271,16 @@ static void ieee80211_iface_work(struct work_struct *work)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&local->sta_mtx);
|
mutex_unlock(&local->sta_mtx);
|
||||||
|
} else if (ieee80211_is_action(mgmt->frame_control) &&
|
||||||
|
mgmt->u.action.category == WLAN_CATEGORY_VHT) {
|
||||||
|
switch (mgmt->u.action.u.vht_group_notif.action_code) {
|
||||||
|
case WLAN_VHT_ACTION_GROUPID_MGMT:
|
||||||
|
ieee80211_process_mu_groups(sdata, mgmt);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARN_ON(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else if (ieee80211_is_data_qos(mgmt->frame_control)) {
|
} else if (ieee80211_is_data_qos(mgmt->frame_control)) {
|
||||||
struct ieee80211_hdr *hdr = (void *)mgmt;
|
struct ieee80211_hdr *hdr = (void *)mgmt;
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -2079,6 +2079,13 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||||
memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
|
memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
|
||||||
memset(&ifmgd->vht_capa, 0, sizeof(ifmgd->vht_capa));
|
memset(&ifmgd->vht_capa, 0, sizeof(ifmgd->vht_capa));
|
||||||
memset(&ifmgd->vht_capa_mask, 0, sizeof(ifmgd->vht_capa_mask));
|
memset(&ifmgd->vht_capa_mask, 0, sizeof(ifmgd->vht_capa_mask));
|
||||||
|
|
||||||
|
/* reset MU-MIMO ownership and group data */
|
||||||
|
memset(sdata->vif.bss_conf.mu_group.membership, 0,
|
||||||
|
sizeof(sdata->vif.bss_conf.mu_group.membership));
|
||||||
|
memset(sdata->vif.bss_conf.mu_group.position, 0,
|
||||||
|
sizeof(sdata->vif.bss_conf.mu_group.position));
|
||||||
|
changed |= BSS_CHANGED_MU_GROUPS;
|
||||||
sdata->flags &= ~IEEE80211_SDATA_MU_MIMO_OWNER;
|
sdata->flags &= ~IEEE80211_SDATA_MU_MIMO_OWNER;
|
||||||
|
|
||||||
sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
|
sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
|
||||||
|
|
|
@ -2738,6 +2738,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
||||||
opmode, status->band);
|
opmode, status->band);
|
||||||
goto handled;
|
goto handled;
|
||||||
}
|
}
|
||||||
|
case WLAN_VHT_ACTION_GROUPID_MGMT: {
|
||||||
|
if (len < IEEE80211_MIN_ACTION_SIZE + 25)
|
||||||
|
goto invalid;
|
||||||
|
goto queue;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1928,6 +1928,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||||
BSS_CHANGED_IDLE |
|
BSS_CHANGED_IDLE |
|
||||||
BSS_CHANGED_TXPOWER;
|
BSS_CHANGED_TXPOWER;
|
||||||
|
|
||||||
|
if (sdata->flags & IEEE80211_SDATA_MU_MIMO_OWNER)
|
||||||
|
changed |= BSS_CHANGED_MU_GROUPS;
|
||||||
|
|
||||||
switch (sdata->vif.type) {
|
switch (sdata->vif.type) {
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
changed |= BSS_CHANGED_ASSOC |
|
changed |= BSS_CHANGED_ASSOC |
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* VHT handling
|
* VHT handling
|
||||||
*
|
*
|
||||||
|
* Portions of this file
|
||||||
|
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||||
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
|
@ -425,6 +428,28 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct ieee80211_mgmt *mgmt)
|
||||||
|
{
|
||||||
|
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
|
||||||
|
|
||||||
|
if (!(sdata->flags & IEEE80211_SDATA_MU_MIMO_OWNER))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!memcmp(mgmt->u.action.u.vht_group_notif.position,
|
||||||
|
bss_conf->mu_group.position, WLAN_USER_POSITION_LEN) &&
|
||||||
|
!memcmp(mgmt->u.action.u.vht_group_notif.membership,
|
||||||
|
bss_conf->mu_group.membership, WLAN_MEMBERSHIP_LEN))
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(mgmt->u.action.u.vht_group_notif.membership,
|
||||||
|
bss_conf->mu_group.membership, WLAN_MEMBERSHIP_LEN);
|
||||||
|
memcpy(mgmt->u.action.u.vht_group_notif.position,
|
||||||
|
bss_conf->mu_group.position, WLAN_USER_POSITION_LEN);
|
||||||
|
|
||||||
|
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_MU_GROUPS);
|
||||||
|
}
|
||||||
|
|
||||||
void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
||||||
struct sta_info *sta, u8 opmode,
|
struct sta_info *sta, u8 opmode,
|
||||||
enum ieee80211_band band)
|
enum ieee80211_band band)
|
||||||
|
|
Loading…
Reference in New Issue