Skip to content

Commit

Permalink
mac80211: process and save VHT MU-MIMO group frame
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Sara Sharon authored and Johannes Berg committed Jan 14, 2016
1 parent c799ba6 commit 23a1f8d
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 0 deletions.
7 changes: 7 additions & 0 deletions include/linux/ieee80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,8 @@ enum ieee80211_vht_opmode_bits {
};

#define WLAN_SA_QUERY_TR_ID_LEN 2
#define WLAN_MEMBERSHIP_LEN 8
#define WLAN_USER_POSITION_LEN 16

/**
* struct ieee80211_tpc_report_ie
Expand Down Expand Up @@ -989,6 +991,11 @@ struct ieee80211_mgmt {
u8 action_code;
u8 operating_mode;
} __packed vht_opmode_notif;
struct {
u8 action_code;
u8 membership[WLAN_MEMBERSHIP_LEN];
u8 position[WLAN_USER_POSITION_LEN];
} __packed vht_group_notif;
struct {
u8 action_code;
u8 dialog_token;
Expand Down
17 changes: 17 additions & 0 deletions include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ struct ieee80211_vif_chanctx_switch {
* note that this is only called when it changes after the channel
* context had been assigned.
* @BSS_CHANGED_OCB: OCB join status changed
* @BSS_CHANGED_MU_GROUPS: VHT MU-MIMO group id or user position changed
*/
enum ieee80211_bss_change {
BSS_CHANGED_ASSOC = 1<<0,
Expand All @@ -323,6 +324,7 @@ enum ieee80211_bss_change {
BSS_CHANGED_BEACON_INFO = 1<<20,
BSS_CHANGED_BANDWIDTH = 1<<21,
BSS_CHANGED_OCB = 1<<22,
BSS_CHANGED_MU_GROUPS = 1<<23,

/* when adding here, make sure to change ieee80211_reconfig */
};
Expand Down Expand Up @@ -435,6 +437,19 @@ struct ieee80211_event {
} 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
*
Expand Down Expand Up @@ -477,6 +492,7 @@ struct ieee80211_event {
* @enable_beacon: whether beaconing should be enabled or not
* @chandef: Channel definition for this BSS -- the hardware might be
* 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.
* 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
Expand Down Expand Up @@ -535,6 +551,7 @@ struct ieee80211_bss_conf {
s32 cqm_rssi_thold;
u32 cqm_rssi_hyst;
struct cfg80211_chan_def chandef;
struct ieee80211_mu_group_data mu_group;
__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
int arp_addr_cnt;
bool qos;
Expand Down
2 changes: 2 additions & 0 deletions net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_cur_vht_bw(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,
struct sta_info *sta, u8 opmode,
enum ieee80211_band band);
Expand Down
10 changes: 10 additions & 0 deletions net/mac80211/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,16 @@ static void ieee80211_iface_work(struct work_struct *work)
}
}
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)) {
struct ieee80211_hdr *hdr = (void *)mgmt;
/*
Expand Down
7 changes: 7 additions & 0 deletions net/mac80211/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -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->vht_capa, 0, sizeof(ifmgd->vht_capa));
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->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
Expand Down
5 changes: 5 additions & 0 deletions net/mac80211/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2738,6 +2738,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
opmode, status->band);
goto handled;
}
case WLAN_VHT_ACTION_GROUPID_MGMT: {
if (len < IEEE80211_MIN_ACTION_SIZE + 25)
goto invalid;
goto queue;
}
default:
break;
}
Expand Down
3 changes: 3 additions & 0 deletions net/mac80211/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1928,6 +1928,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
BSS_CHANGED_IDLE |
BSS_CHANGED_TXPOWER;

if (sdata->flags & IEEE80211_SDATA_MU_MIMO_OWNER)
changed |= BSS_CHANGED_MU_GROUPS;

switch (sdata->vif.type) {
case NL80211_IFTYPE_STATION:
changed |= BSS_CHANGED_ASSOC |
Expand Down
25 changes: 25 additions & 0 deletions net/mac80211/vht.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/*
* VHT handling
*
* Portions of this file
* Copyright(c) 2015 Intel Deutschland GmbH
*
* 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
* published by the Free Software Foundation.
Expand Down Expand Up @@ -425,6 +428,28 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
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,
struct sta_info *sta, u8 opmode,
enum ieee80211_band band)
Expand Down

0 comments on commit 23a1f8d

Please sign in to comment.