2011-10-20 18:34:54

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH v2 0/6] HT support for mesh

This patchset adds basic HT support for mesh nodes. We avoid the question of
how to negotiate channel types, by simply disallowing peering with mismatched
HT modes. Needs the mesh fixes posted earlier today for patch context.

Many thanks to Luis Rodriguez for his assistance, and Ashok Nagarajan for
co-authoring this patchset.

v2:
Remove outdated BA comments (Christian)

Alexander Simon (1):
mac80211: Add HT helper functions

Thomas Pedersen (5):
mac80211: add HT IEs to mesh frames
mac80211: set HT capabilities for mesh peer
mac80211: allow frame aggregation for mesh
mac80211: add WMM IE to mesh frames
mac80211: check mesh peer's WMM parameters

include/linux/ieee80211.h | 26 ++++++
include/net/mac80211.h | 4 +
net/mac80211/agg-rx.c | 3 +-
net/mac80211/agg-tx.c | 10 +--
net/mac80211/ht.c | 3 +-
net/mac80211/ieee80211_i.h | 8 ++
net/mac80211/mesh.c | 75 ++++++++++++++--
net/mac80211/mesh.h | 4 +
net/mac80211/mesh_plink.c | 24 +++++-
net/mac80211/rx.c | 7 +--
net/mac80211/tx.c | 6 ++
net/mac80211/util.c | 208 ++++++++++++++++++++++++++++++++++++++++----
net/mac80211/work.c | 29 +------
13 files changed, 336 insertions(+), 71 deletions(-)

--
1.7.5.4



2011-10-20 18:35:07

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH v2 6/6] mac80211: check mesh peer's WMM parameters

For now, disallow peering if our WMM parameters don't match our peer's.

Signed-off-by: Thomas Pedersen <[email protected]>
---
net/mac80211/mesh.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index b3a125f..dd83c8f7 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -103,6 +103,13 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat
ieee80211_ht_info_to_channel_type(ie->ht_info_elem)))
goto mismatch;

+ if (ie->wmm_param) {
+ u8 wmm_local[sizeof(struct ieee80211_wmm_param_ie)];
+ ieee80211_build_wmm_ie(&sdata->vif, wmm_local);
+ if (memcmp(ie->wmm_param, wmm_local, sizeof(wmm_local)))
+ goto mismatch;
+ }
+
return true;
mismatch:
return false;
--
1.7.5.4


2011-10-20 18:35:00

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH v2 3/6] mac80211: set HT capabilities for mesh peer

Set peer's HT capabilities, and disallow peering if we're on a different
channel type.

Signed-off-by: Thomas Pedersen <[email protected]>
Signed-off-by: Ashok Nagarajan <[email protected]>
---
net/mac80211/mesh.c | 25 +++++++++++++++++--------
net/mac80211/mesh_plink.c | 13 ++++++++++---
2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 2dc76a9..b3a125f 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -76,6 +76,7 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct ieee80211_local *local = sdata->local;

/*
* As support for each feature is added, check for matching
@@ -87,15 +88,23 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat
* - MDA enabled
* - Power management control on fc
*/
- if (ifmsh->mesh_id_len == ie->mesh_id_len &&
- memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
- (ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) &&
- (ifmsh->mesh_pm_id == ie->mesh_config->meshconf_pmetric) &&
- (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) &&
- (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) &&
- (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))
- return true;
-
+ if (!(ifmsh->mesh_id_len == ie->mesh_id_len &&
+ memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
+ (ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) &&
+ (ifmsh->mesh_pm_id == ie->mesh_config->meshconf_pmetric) &&
+ (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) &&
+ (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) &&
+ (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)))
+ goto mismatch;
+
+ /* disallow peering with mismatched channel types for now */
+ if (ie->ht_info_elem &&
+ (local->_oper_channel_type !=
+ ieee80211_ht_info_to_channel_type(ie->ht_info_elem)))
+ goto mismatch;
+
+ return true;
+mismatch:
return false;
}

diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index bbfbd45..f0705e6 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -80,11 +80,15 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta)
* on it in the lifecycle management section!
*/
static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
- u8 *hw_addr, u32 rates)
+ u8 *hw_addr, u32 rates,
+ struct ieee802_11_elems *elems)
{
struct ieee80211_local *local = sdata->local;
+ struct ieee80211_supported_band *sband;
struct sta_info *sta;

+ sband = local->hw.wiphy->bands[local->oper_channel->band];
+
if (local->num_sta >= MESH_MAX_PLINKS)
return NULL;

@@ -96,6 +100,9 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
set_sta_flag(sta, WLAN_STA_AUTHORIZED);
set_sta_flag(sta, WLAN_STA_WME);
sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
+ if (elems->ht_cap_elem)
+ ieee80211_ht_cap_ie_to_sta_ht_cap(sband, elems->ht_cap_elem,
+ &sta->sta.ht_cap);
rate_control_rate_init(sta);

return sta;
@@ -279,7 +286,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates,
elems->ie_start, elems->total_len,
GFP_KERNEL);
else
- sta = mesh_plink_alloc(sdata, hw_addr, rates);
+ sta = mesh_plink_alloc(sdata, hw_addr, rates, elems);
if (!sta)
return;
if (sta_info_insert_rcu(sta)) {
@@ -570,7 +577,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
}

rates = ieee80211_sta_get_rates(local, &elems, rx_status->band);
- sta = mesh_plink_alloc(sdata, mgmt->sa, rates);
+ sta = mesh_plink_alloc(sdata, mgmt->sa, rates, &elems);
if (!sta) {
mpl_dbg("Mesh plink error: plink table full\n");
return;
--
1.7.5.4


2011-10-20 18:34:59

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH v2 2/6] mac80211: add HT IEs to mesh frames

Signed-off-by: Thomas Pedersen <[email protected]>
Signed-off-by: Ashok Nagarajan <[email protected]>
---
net/mac80211/mesh.c | 43 +++++++++++++++++++++++++++++++++++++++++++
net/mac80211/mesh.h | 4 ++++
net/mac80211/mesh_plink.c | 9 +++++++++
net/mac80211/tx.c | 4 ++++
4 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index a7078fd..2dc76a9 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -341,6 +341,49 @@ int mesh_add_ds_params_ie(struct sk_buff *skb,
return 0;
}

+int mesh_add_ht_cap_ie(struct sk_buff *skb,
+ struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_supported_band *sband;
+ u8 *pos;
+
+ sband = local->hw.wiphy->bands[local->oper_channel->band];
+ if (!sband->ht_cap.ht_supported ||
+ local->_oper_channel_type == NL80211_CHAN_NO_HT)
+ return 0;
+
+ if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap))
+ return -ENOMEM;
+
+ pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_cap));
+ ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
+
+ return 0;
+}
+
+int mesh_add_ht_info_ie(struct sk_buff *skb,
+ struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_channel *channel = local->oper_channel;
+ enum nl80211_channel_type channel_type = local->_oper_channel_type;
+ struct ieee80211_supported_band *sband =
+ local->hw.wiphy->bands[channel->band];
+ struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap;
+ u8 *pos;
+
+ if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT)
+ return 0;
+
+ if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_info))
+ return -ENOMEM;
+
+ pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_info));
+ ieee80211_ie_build_ht_info(pos, ht_cap, channel, channel_type);
+
+ return 0;
+}
static void ieee80211_mesh_path_timer(unsigned long data)
{
struct ieee80211_sub_if_data *sdata =
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 8c00e2d..0f2c4e6 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -212,6 +212,10 @@ int mesh_add_vendor_ies(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
int mesh_add_ds_params_ie(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
+int mesh_add_ht_cap_ie(struct sk_buff *skb,
+ struct ieee80211_sub_if_data *sdata);
+int mesh_add_ht_info_ie(struct sk_buff *skb,
+ struct ieee80211_sub_if_data *sdata);
void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
void ieee80211s_init(void);
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 42a0544..bbfbd45 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -168,6 +168,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
2 + (IEEE80211_MAX_SUPP_RATES - 8) +
2 + sdata->u.mesh.mesh_id_len +
2 + sizeof(struct ieee80211_meshconf_ie) +
+ 2 + sizeof(struct ieee80211_ht_cap) +
+ 2 + sizeof(struct ieee80211_ht_info) +
2 + 8 + /* peering IE */
sdata->u.mesh.ie_len);
if (!skb)
@@ -244,6 +246,13 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
memcpy(pos, &reason, 2);
pos += 2;
}
+
+ if (action != WLAN_SP_MESH_PEERING_CLOSE) {
+ if (mesh_add_ht_cap_ie(skb, sdata) ||
+ mesh_add_ht_info_ie(skb, sdata))
+ return -1;
+ }
+
if (mesh_add_vendor_ies(skb, sdata))
return -1;

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index f28a920..faca189 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2290,6 +2290,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2 + 8 + /* supported rates */
2 + 3 + /* DS params */
2 + (IEEE80211_MAX_SUPP_RATES - 8) +
+ 2 + sizeof(struct ieee80211_ht_cap) +
+ 2 + sizeof(struct ieee80211_ht_info) +
2 + sdata->u.mesh.mesh_id_len +
2 + sizeof(struct ieee80211_meshconf_ie) +
sdata->u.mesh.ie_len);
@@ -2318,6 +2320,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
mesh_add_ds_params_ie(skb, sdata) ||
ieee80211_add_ext_srates_ie(&sdata->vif, skb) ||
mesh_add_rsn_ie(skb, sdata) ||
+ mesh_add_ht_cap_ie(skb, sdata) ||
+ mesh_add_ht_info_ie(skb, sdata) ||
mesh_add_meshid_ie(skb, sdata) ||
mesh_add_meshconf_ie(skb, sdata) ||
mesh_add_vendor_ies(skb, sdata)) {
--
1.7.5.4


2011-10-20 18:35:04

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH v2 4/6] mac80211: allow frame aggregation for mesh

Signed-off-by: Thomas Pedersen <[email protected]>
Signed-off-by: Ashok Nagarajan <[email protected]>

---
v2:
Remove outdated comments (Christian)

net/mac80211/agg-rx.c | 3 ++-
net/mac80211/agg-tx.c | 10 +++-------
net/mac80211/ht.c | 3 ++-
net/mac80211/rx.c | 7 +------
4 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 0cde8df..e8af4b0 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -176,7 +176,8 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
memcpy(mgmt->da, da, ETH_ALEN);
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
if (sdata->vif.type == NL80211_IFTYPE_AP ||
- sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+ sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 2ac0339..fefc7e5 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -77,7 +77,8 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
memcpy(mgmt->da, da, ETH_ALEN);
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
if (sdata->vif.type == NL80211_IFTYPE_AP ||
- sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+ sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
@@ -371,13 +372,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
pubsta->addr, tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */

- /*
- * The aggregation code is not prepared to handle
- * anything but STA/AP due to the BSSID handling.
- * IBSS could work in the code but isn't supported
- * by drivers or the standard.
- */
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
sdata->vif.type != NL80211_IFTYPE_AP)
return -EINVAL;
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index f80a35c..988c7ec 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -195,7 +195,8 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
memcpy(mgmt->da, da, ETH_ALEN);
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
if (sdata->vif.type == NL80211_IFTYPE_AP ||
- sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+ sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 8c03d6e..39b69e2 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2208,13 +2208,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)

switch (mgmt->u.action.category) {
case WLAN_CATEGORY_BACK:
- /*
- * The aggregation code is not prepared to handle
- * anything but STA/AP due to the BSSID handling;
- * IBSS could work in the code but isn't supported
- * by drivers or the standard.
- */
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
sdata->vif.type != NL80211_IFTYPE_AP)
break;
--
1.7.5.4


2011-10-20 19:17:29

by Xianghua Xiao

[permalink] [raw]
Subject: Re: [PATCH v2 0/6] HT support for mesh

how does this relate to Alex HT patches? Alex's patch addresses IBSS
but there seems to be some overlaps between Mesh/IBSS HT patches.
thanks,

On Thu, Oct 20, 2011 at 1:34 PM, Thomas Pedersen <[email protected]> wrote:
> This patchset adds basic HT support for mesh nodes. We avoid the question of
> how to negotiate channel types, by simply disallowing peering with mismatched
> HT modes. Needs the mesh fixes posted earlier today for patch context.
>
> Many thanks to Luis Rodriguez for his assistance, and Ashok Nagarajan for
> co-authoring this patchset.
>
> v2:
>        Remove outdated BA comments (Christian)
>
> Alexander Simon (1):
>  mac80211: Add HT helper functions
>
> Thomas Pedersen (5):
>  mac80211: add HT IEs to mesh frames
>  mac80211: set HT capabilities for mesh peer
>  mac80211: allow frame aggregation for mesh
>  mac80211: add WMM IE to mesh frames
>  mac80211: check mesh peer's WMM parameters
>
>  include/linux/ieee80211.h  |   26 ++++++
>  include/net/mac80211.h     |    4 +
>  net/mac80211/agg-rx.c      |    3 +-
>  net/mac80211/agg-tx.c      |   10 +--
>  net/mac80211/ht.c          |    3 +-
>  net/mac80211/ieee80211_i.h |    8 ++
>  net/mac80211/mesh.c        |   75 ++++++++++++++--
>  net/mac80211/mesh.h        |    4 +
>  net/mac80211/mesh_plink.c  |   24 +++++-
>  net/mac80211/rx.c          |    7 +--
>  net/mac80211/tx.c          |    6 ++
>  net/mac80211/util.c        |  208 ++++++++++++++++++++++++++++++++++++++++----
>  net/mac80211/work.c        |   29 +------
>  13 files changed, 336 insertions(+), 71 deletions(-)
>
> --
> 1.7.5.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

2011-10-20 18:34:56

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH v2 1/6] mac80211: Add HT helper functions

From: Alexander Simon <[email protected]>

Some refactoring for IBSS HT.

Move HT info and capability IEs building code into separate functions.

Add function to get the channel type from an HT info IE.

Signed-off-by: Alexander Simon <[email protected]>
---
net/mac80211/ieee80211_i.h | 8 +++
net/mac80211/util.c | 116 +++++++++++++++++++++++++++++++++++++------
net/mac80211/work.c | 29 +-----------
3 files changed, 108 insertions(+), 45 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4c3d1f5..30fc9e7 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1333,6 +1333,12 @@ void ieee80211_recalc_smps(struct ieee80211_local *local);
size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
const u8 *ids, int n_ids, size_t offset);
size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
+u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
+ u16 cap);
+u8 *ieee80211_ie_build_ht_info(u8 *pos,
+ struct ieee80211_sta_ht_cap *ht_cap,
+ struct ieee80211_channel *channel,
+ enum nl80211_channel_type channel_type);

/* internal work items */
void ieee80211_work_init(struct ieee80211_local *local);
@@ -1361,6 +1367,8 @@ ieee80211_get_channel_mode(struct ieee80211_local *local,
bool ieee80211_set_channel_type(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
enum nl80211_channel_type chantype);
+enum nl80211_channel_type
+ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info);

#ifdef CONFIG_MAC80211_NOINLINE
#define debug_noinline noinline
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7439d26..72b3a2e 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -811,23 +811,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
offset = noffset;
}

- if (sband->ht_cap.ht_supported) {
- u16 cap = sband->ht_cap.cap;
- __le16 tmp;
-
- *pos++ = WLAN_EID_HT_CAPABILITY;
- *pos++ = sizeof(struct ieee80211_ht_cap);
- memset(pos, 0, sizeof(struct ieee80211_ht_cap));
- tmp = cpu_to_le16(cap);
- memcpy(pos, &tmp, sizeof(u16));
- pos += sizeof(u16);
- *pos++ = sband->ht_cap.ampdu_factor |
- (sband->ht_cap.ampdu_density <<
- IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
- memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
- pos += sizeof(sband->ht_cap.mcs);
- pos += 2 + 4 + 1; /* ext info, BF cap, antsel */
- }
+ if (sband->ht_cap.ht_supported)
+ pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);

/*
* If adding more here, adjust code in main.c
@@ -1362,6 +1347,103 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
}
EXPORT_SYMBOL(ieee80211_disable_rssi_reports);

+u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
+ u16 cap)
+{
+ __le16 tmp;
+
+ *pos++ = WLAN_EID_HT_CAPABILITY;
+ *pos++ = sizeof(struct ieee80211_ht_cap);
+ memset(pos, 0, sizeof(struct ieee80211_ht_cap));
+
+ /* capability flags */
+ tmp = cpu_to_le16(cap);
+ memcpy(pos, &tmp, sizeof(u16));
+ pos += sizeof(u16);
+
+ /* AMPDU parameters */
+ *pos++ = sband->ht_cap.ampdu_factor |
+ (sband->ht_cap.ampdu_density <<
+ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
+
+ /* MCS set */
+ memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
+ pos += sizeof(sband->ht_cap.mcs);
+
+ /* extended capabilities */
+ pos += sizeof(__le16);
+
+ /* BF capabilities */
+ pos += sizeof(__le32);
+
+ /* antenna selection */
+ pos += sizeof(u8);
+
+ return pos;
+}
+
+u8 *ieee80211_ie_build_ht_info(u8 *pos,
+ struct ieee80211_sta_ht_cap *ht_cap,
+ struct ieee80211_channel *channel,
+ enum nl80211_channel_type channel_type)
+{
+ struct ieee80211_ht_info *ht_info;
+ /* Build HT Information */
+ *pos++ = WLAN_EID_HT_INFORMATION;
+ *pos++ = sizeof(struct ieee80211_ht_info);
+ ht_info = (struct ieee80211_ht_info *)pos;
+ ht_info->control_chan =
+ ieee80211_frequency_to_channel(channel->center_freq);
+ switch (channel_type) {
+ case NL80211_CHAN_HT40MINUS:
+ ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ break;
+ case NL80211_CHAN_HT40PLUS:
+ ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ break;
+ case NL80211_CHAN_HT20:
+ default:
+ ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ break;
+ }
+ if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
+ ht_info->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
+ ht_info->operation_mode = 0x0000;
+ ht_info->stbc_param = 0x0000;
+
+ /* It seems that Basic MCS set and Supported MCS set
+ are identical for the first 10 bytes */
+ memset(&ht_info->basic_set, 0, 16);
+ memcpy(&ht_info->basic_set, &ht_cap->mcs, 10);
+
+ return pos + sizeof(struct ieee80211_ht_info);
+}
+
+enum nl80211_channel_type
+ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info)
+{
+ enum nl80211_channel_type channel_type;
+
+ if (!ht_info)
+ return NL80211_CHAN_NO_HT;
+
+ switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+ case IEEE80211_HT_PARAM_CHA_SEC_NONE:
+ channel_type = NL80211_CHAN_HT20;
+ break;
+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+ channel_type = NL80211_CHAN_HT40PLUS;
+ break;
+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+ channel_type = NL80211_CHAN_HT40MINUS;
+ break;
+ default:
+ channel_type = NL80211_CHAN_NO_HT;
+ }
+
+ return channel_type;
+}
+
int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index 94472eb..fab5092 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -103,7 +103,6 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
u8 *pos;
u32 flags = channel->flags;
u16 cap = sband->ht_cap.cap;
- __le16 tmp;

if (!sband->ht_cap.ht_supported)
return;
@@ -154,34 +153,8 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
}

/* reserve and fill IE */
-
pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
- *pos++ = WLAN_EID_HT_CAPABILITY;
- *pos++ = sizeof(struct ieee80211_ht_cap);
- memset(pos, 0, sizeof(struct ieee80211_ht_cap));
-
- /* capability flags */
- tmp = cpu_to_le16(cap);
- memcpy(pos, &tmp, sizeof(u16));
- pos += sizeof(u16);
-
- /* AMPDU parameters */
- *pos++ = sband->ht_cap.ampdu_factor |
- (sband->ht_cap.ampdu_density <<
- IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
-
- /* MCS set */
- memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
- pos += sizeof(sband->ht_cap.mcs);
-
- /* extended capabilities */
- pos += sizeof(__le16);
-
- /* BF capabilities */
- pos += sizeof(__le32);
-
- /* antenna selection */
- pos += sizeof(u8);
+ ieee80211_ie_build_ht_cap(pos, sband, cap);
}

static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
--
1.7.5.4


2011-10-20 19:18:59

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 0/6] HT support for mesh

On Thu, 2011-10-20 at 14:17 -0500, Xianghua Xiao wrote:
> how does this relate to Alex HT patches? Alex's patch addresses IBSS
> but there seems to be some overlaps between Mesh/IBSS HT patches.

He just uses one of Alex's refactoring patches here :)

johannes


2011-10-20 18:35:05

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH v2 5/6] mac80211: add WMM IE to mesh frames

Include the WMM IE in mesh peering and beacon frames. This is needed
tell any potential peers what our WMM / EDCA parameters are.

Signed-off-by: Thomas Pedersen <[email protected]>
---
include/linux/ieee80211.h | 26 +++++++++++++
include/net/mac80211.h | 4 ++
net/mac80211/mesh_plink.c | 4 +-
net/mac80211/tx.c | 2 +
net/mac80211/util.c | 92 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 127 insertions(+), 1 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 48363c3..ec6f396 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -152,6 +152,11 @@
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x03
#define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT 5

+#define IEEE80211_WMM_IE_ECWMIN_MASK 0x0f
+#define IEEE80211_WMM_IE_ECWMIN_SHIFT 0
+#define IEEE80211_WMM_IE_ECWMAX_MASK 0xf0
+#define IEEE80211_WMM_IE_ECWMAX_SHIFT 4
+
#define IEEE80211_HT_CTL_LEN 4

struct ieee80211_hdr {
@@ -605,6 +610,27 @@ struct ieee80211_tim_ie {
u8 virtual_map[1];
} __attribute__ ((packed));

+struct ieee80211_wmm_ac_param {
+ u8 ac_aci_acm_aifsn;
+ u8 ac_ecwmin_ecwmax;
+ __le16 ac_txop_limit;
+} __attribute__ ((packed));
+
+/**
+ * struct ieee80211_wmm_param
+ *
+ * This structure refers to "WMM parameter information element"
+ */
+struct ieee80211_wmm_param_ie {
+ u8 oui[3];
+ u8 oui_type;
+ u8 oui_subtype;
+ u8 version;
+ u8 qos_info;
+ u8 reserved;
+ struct ieee80211_wmm_ac_param ac[4];
+} __attribute__ ((packed));
+
/**
* struct ieee80211_meshconf_ie
*
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index dc1123a..fd28b2b 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3649,4 +3649,8 @@ int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb);

int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif,
struct sk_buff *skb);
+int ieee80211_build_wmm_ie(struct ieee80211_vif *vif,
+ u8 *ie_data);
+int ieee80211_add_wmm_ie(struct ieee80211_vif *vif,
+ struct sk_buff *skb);
#endif /* MAC80211_H */
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index f0705e6..069e5dc 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -177,6 +177,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
2 + sizeof(struct ieee80211_meshconf_ie) +
2 + sizeof(struct ieee80211_ht_cap) +
2 + sizeof(struct ieee80211_ht_info) +
+ 2 + sizeof(struct ieee80211_wmm_param_ie) +
2 + 8 + /* peering IE */
sdata->u.mesh.ie_len);
if (!skb)
@@ -256,7 +257,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,

if (action != WLAN_SP_MESH_PEERING_CLOSE) {
if (mesh_add_ht_cap_ie(skb, sdata) ||
- mesh_add_ht_info_ie(skb, sdata))
+ mesh_add_ht_info_ie(skb, sdata) ||
+ ieee80211_add_wmm_ie(&sdata->vif, skb))
return -1;
}

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index faca189..dfb6bb9 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2294,6 +2294,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2 + sizeof(struct ieee80211_ht_info) +
2 + sdata->u.mesh.mesh_id_len +
2 + sizeof(struct ieee80211_meshconf_ie) +
+ 2 + sizeof(struct ieee80211_wmm_param_ie) +
sdata->u.mesh.ie_len);
if (!skb)
goto out;
@@ -2324,6 +2325,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
mesh_add_ht_info_ie(skb, sdata) ||
mesh_add_meshid_ie(skb, sdata) ||
mesh_add_meshconf_ie(skb, sdata) ||
+ ieee80211_add_wmm_ie(&sdata->vif, skb) ||
mesh_add_vendor_ies(skb, sdata)) {
pr_err("o11s: couldn't add ies!\n");
goto out;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 72b3a2e..071b425 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1419,6 +1419,98 @@ u8 *ieee80211_ie_build_ht_info(u8 *pos,
return pos + sizeof(struct ieee80211_ht_info);
}

+static inline u8 ieee80211_wmm_ecw(struct ieee80211_tx_queue_params *txq)
+{
+ u8 cw_min, cw_max, n = 0;
+
+ /* cw_min and cw_max are transmitted as n in 2^n - 1 */
+ while ((txq->cw_min >> n) & 0x01)
+ n++;
+ cw_min = n;
+
+ n = 0;
+ while ((txq->cw_max >> n) & 0x01)
+ n++;
+ cw_max = n;
+
+ return ((cw_min << IEEE80211_WMM_IE_ECWMIN_SHIFT) &
+ IEEE80211_WMM_IE_ECWMIN_MASK) |
+ ((cw_max << IEEE80211_WMM_IE_ECWMAX_SHIFT) &
+ IEEE80211_WMM_IE_ECWMAX_MASK);
+}
+
+static inline u8 ieee80211_aci_to_q(u8 aci)
+{
+ u8 q;
+
+ switch (aci) {
+ case 1: /* BK */
+ q = 3;
+ break;
+ default:
+ case 0: /* BE */
+ q = 2;
+ break;
+ case 2: /* VI */
+ q = 1;
+ break;
+ case 3: /* VO */
+ q = 0;
+ break;
+ }
+
+ return q;
+}
+
+int ieee80211_build_wmm_ie(struct ieee80211_vif *vif, u8 *data)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ struct ieee80211_wmm_param_ie *wmm;
+ struct ieee80211_wmm_ac_param *ac;
+ struct ieee80211_tx_queue_params *txconf;
+ u8 aci;
+
+ wmm = (struct ieee80211_wmm_param_ie *) data;
+ wmm->oui[0] = 0x00;
+ wmm->oui[1] = 0x50;
+ wmm->oui[2] = 0xf2;
+ wmm->oui_type = 2; /* WMM */
+ wmm->oui_subtype = 1; /* WMM param */
+ wmm->version = 1;
+ wmm->qos_info = 0;
+ wmm->reserved = 0;
+
+ for (aci = 0; aci < 4; aci++) {
+ ac = &wmm->ac[aci];
+ txconf = &sdata->tx_conf[ieee80211_aci_to_q(aci)];
+
+ ac->ac_aci_acm_aifsn = (aci << 5) | txconf->aifs;
+ ac->ac_ecwmin_ecwmax = ieee80211_wmm_ecw(txconf);
+ ac->ac_txop_limit = cpu_to_le16(txconf->txop);
+ }
+
+ return 0;
+}
+
+int ieee80211_add_wmm_ie(struct ieee80211_vif *vif,
+ struct sk_buff *skb)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ u8 *pos;
+
+ if (sdata->local->hw.queues < 4)
+ return 0;
+
+ if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_wmm_param_ie))
+ return -ENOMEM;
+
+ pos = skb_put(skb, 2 + sizeof(struct ieee80211_wmm_param_ie));
+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+ *pos++ = sizeof(struct ieee80211_wmm_param_ie);
+
+ return ieee80211_build_wmm_ie(vif, pos);
+}
+
enum nl80211_channel_type
ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info)
{
--
1.7.5.4