2011-06-21 15:47:49

by Alexander Simon

[permalink] [raw]
Subject: [RFC v3 1/3] mac80211: add some helper functions

Add helper functions cfg80211_get_bss_ht, ieee80211_ie_build_ht_cap
and ieee80211_ie_build_ht_info.
These are needed for my IBSS HT patch but are also used to clean up some
multiple code.

Signed-off-by: Alexander Simon <[email protected]>
---
include/net/cfg80211.h | 6 ++
net/mac80211/ieee80211_i.h | 8 +++
net/mac80211/util.c | 116 ++++++++++++++++++++++++++++++++++++++-------
net/mac80211/work.c | 29 -----------
net/wireless/scan.c | 36 +++++++++++++
5 files changed, 148 insertions(+), 47 deletions(-)

diff -Nrup a/include/net/cfg80211.h b/include/net/cfg80211.h
--- a/include/net/cfg80211.h 2011-06-01 21:04:33.000000000 +0200
+++ b/include/net/cfg80211.h 2011-06-21 13:21:38.000000000 +0200
@@ -2530,6 +2531,12 @@ struct cfg80211_bss *cfg80211_get_bss(st
const u8 *bssid,
const u8 *ssid, size_t ssid_len,
u16 capa_mask, u16 capa_val);
+struct cfg80211_bss *cfg80211_get_bss_ht(struct wiphy *wiphy,
+ struct ieee80211_channel *channel,
+ const u8 *bssid,
+ const u8 *ssid, size_t ssid_len,
+ u16 capa_mask, u16 capa_val,
+ enum nl80211_channel_type channel_type);
static inline struct cfg80211_bss *
cfg80211_get_ibss(struct wiphy *wiphy,
struct ieee80211_channel *channel,
diff -Nrup a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
--- a/net/mac80211/ieee80211_i.h 2011-06-01 21:04:32.000000000 +0200
+++ b/net/mac80211/ieee80211_i.h 2011-06-21 13:21:38.000000000 +0200
@@ -1376,6 +1378,12 @@ void ieee80211_recalc_smps(struct ieee80
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);
@@ -1404,6 +1412,8 @@ ieee80211_get_channel_mode(struct ieee80
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 -Nrup a/net/mac80211/util.c b/net/mac80211/util.c
--- a/net/mac80211/util.c 2011-06-01 21:04:32.000000000 +0200
+++ b/net/mac80211/util.c 2011-06-21 13:21:38.000000000 +0200
@@ -1007,23 +1007,8 @@ int ieee80211_build_preq_ies(struct ieee
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
@@ -1462,3 +1447,100 @@ size_t ieee80211_ie_split_vendor(const u

return pos;
}
+
+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;
+}
diff -Nrup a/net/mac80211/work.c b/net/mac80211/work.c
--- a/net/mac80211/work.c 2011-06-01 21:04:33.000000000 +0200
+++ b/net/mac80211/work.c 2011-06-21 13:21:38.000000000 +0200
@@ -117,7 +117,6 @@ static void ieee80211_add_ht_ie(struct s
u8 *pos;
u32 flags = channel->flags;
u16 cap = sband->ht_cap.cap;
- __le16 tmp;

if (!sband->ht_cap.ht_supported)
return;
@@ -168,34 +167,8 @@ static void ieee80211_add_ht_ie(struct s
}

/* 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,
diff -Nrup a/net/wireless/scan.c b/net/wireless/scan.c
--- a/net/wireless/scan.c 2011-06-01 21:04:32.000000000 +0200
+++ b/net/wireless/scan.c 2011-06-21 13:21:38.000000000 +0200
@@ -343,6 +343,18 @@ struct cfg80211_bss *cfg80211_get_bss(st
const u8 *ssid, size_t ssid_len,
u16 capa_mask, u16 capa_val)
{
+ return cfg80211_get_bss_ht(wiphy, channel, bssid, ssid, ssid_len,
+ capa_mask, capa_val, NL80211_CHAN_NO_HT);
+}
+EXPORT_SYMBOL(cfg80211_get_bss);
+
+struct cfg80211_bss *cfg80211_get_bss_ht(struct wiphy *wiphy,
+ struct ieee80211_channel *channel,
+ const u8 *bssid,
+ const u8 *ssid, size_t ssid_len,
+ u16 capa_mask, u16 capa_val,
+ enum nl80211_channel_type channel_type)
+{
struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
struct cfg80211_internal_bss *bss, *res = NULL;
unsigned long now = jiffies;
@@ -352,8 +364,27 @@ struct cfg80211_bss *cfg80211_get_bss(st
list_for_each_entry(bss, &dev->bss_list, list) {
if ((bss->pub.capability & capa_mask) != capa_val)
continue;
- if (channel && bss->pub.channel != channel)
- continue;
+ if (channel) {
+ if (bss->pub.channel != channel)
+ continue;
+ if (channel_type == NL80211_CHAN_HT40MINUS ||
+ channel_type == NL80211_CHAN_HT40PLUS) {
+ struct ieee80211_ht_info *ht_info;
+ ht_info = (struct ieee80211_ht_info *)
+ ieee80211_bss_get_ie(&bss->pub,
+ WLAN_EID_HT_INFORMATION);
+ if (!ht_info)
+ continue;
+ if (channel_type == NL80211_CHAN_HT40MINUS &&
+ !(ht_info->ht_param &
+ IEEE80211_HT_PARAM_CHA_SEC_BELOW))
+ continue;
+ if (channel_type == NL80211_CHAN_HT40PLUS &&
+ !(ht_info->ht_param &
+ IEEE80211_HT_PARAM_CHA_SEC_ABOVE))
+ continue;
+ }
+ }
/* Don't get expired BSS structs */
if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
!atomic_read(&bss->hold))
@@ -370,7 +401,8 @@ struct cfg80211_bss *cfg80211_get_bss(st
return NULL;
return &res->pub;
}
EXPORT_SYMBOL(cfg80211_get_bss);
+EXPORT_SYMBOL(cfg80211_get_bss_ht);

struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy,
struct ieee80211_channel *channel,




2011-06-21 16:01:32

by Alexander Simon

[permalink] [raw]
Subject: patch for iw

Here is a patch for iw to set a ht channel type when joining an IBSS.

diff -Nrup iw-0.9.22/ibss.c iw-0.9.22_ibss_n//ibss.c
--- iw-0.9.22/ibss.c 2011-02-04 13:29:39.000000000 +0100
+++ iw-0.9.22_ibss_n//ibss.c 2011-05-03 21:31:00.000000000 +0200
@@ -27,6 +27,7 @@ static int join_ibss(struct nl80211_stat
char *value = NULL, *sptr = NULL;
float rate;
int bintval;
+ unsigned int htval;

if (argc < 2)
return 1;
@@ -44,6 +45,12 @@ static int join_ibss(struct nl80211_stat
argv++;
argc--;

+ if (argc && parse_channel_type(argv[0], &htval)) {
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, htval);
+ argv++;
+ argc--;
+ }
+
if (argc && strcmp(argv[0], "fixed-freq") == 0) {
NLA_PUT_FLAG(msg, NL80211_ATTR_FREQ_FIXED);
argv++;
@@ -134,7 +141,7 @@ COMMAND(ibss, leave, NULL,
NL80211_CMD_LEAVE_IBSS, 0, CIB_NETDEV, leave_ibss,
"Leave the current IBSS cell.");
COMMAND(ibss, join,
- "<SSID> <freq in MHz> [fixed-freq] [<fixed bssid>] [beacon-interval <TU>]"
+ "<SSID> <freq in MHz> [HT20|HT40+|HT40-] [fixed-freq] [<fixed bssid>] [beacon-interval <TU>]"
" [basic-rates <rate in Mbps,rate2,...>] [mcast-rate <rate in Mbps>] "
"[key d:0:abcde]",
NL80211_CMD_JOIN_IBSS, 0, CIB_NETDEV, join_ibss,
diff -Nrup iw-0.9.22/iw.h iw-0.9.22_ibss_n//iw.h
--- iw-0.9.22/iw.h 2011-02-04 13:29:39.000000000 +0100
+++ iw-0.9.22_ibss_n//iw.h 2011-05-03 14:52:02.000000000 +0200
@@ -130,6 +130,7 @@ void mac_addr_n2a(char *mac_addr, unsign
unsigned char *parse_hex(char *hex, size_t *outlen);

int parse_keys(struct nl_msg *msg, char **argv, int argc);
+int parse_channel_type(const char *str, unsigned int *htval);

void print_ht_mcs(const __u8 *mcs);
void print_ampdu_length(__u8 exponent);
diff -Nrup iw-0.9.22/phy.c iw-0.9.22_ibss_n//phy.c
--- iw-0.9.22/phy.c 2011-02-04 13:29:39.000000000 +0100
+++ iw-0.9.22_ibss_n//phy.c 2011-05-03 14:52:02.000000000 +0200
@@ -33,30 +33,14 @@ static int handle_freqchan(struct nl_msg
int argc, char **argv)
{
char *end;
- static const struct {
- const char *name;
- unsigned int val;
- } htmap[] = {
- { .name = "HT20", .val = NL80211_CHAN_HT20, },
- { .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
- { .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
- };
unsigned int htval = NL80211_CHAN_NO_HT;
unsigned int freq;
- int i;

if (!argc || argc > 2)
return 1;

- if (argc == 2) {
- for (i = 0; i < ARRAY_SIZE(htmap); i++) {
- if (strcasecmp(htmap[i].name, argv[1]) == 0) {
- htval = htmap[i].val;
- break;
- }
- }
- if (htval == NL80211_CHAN_NO_HT)
- return 1;
+ if (argc == 2 && !parse_channel_type(argv[1], &htval)) {
+ return 1;
}

if (!*argv[0])
diff -Nrup iw-0.9.22/util.c iw-0.9.22_ibss_n//util.c
--- iw-0.9.22/util.c 2011-02-04 13:29:39.000000000 +0100
+++ iw-0.9.22_ibss_n//util.c 2011-05-03 14:52:02.000000000 +0200
@@ -345,6 +345,33 @@ int parse_keys(struct nl_msg *msg, char
return 2;
}

+/*
+ * Convert a string "HT20", "HT40+" or "HT40-" into nl80211
+ * value. Conversion is case insensitive. Returns 1 on success, 0 on error.
+ */
+
+int parse_channel_type(const char *str, unsigned int *htval)
+{
+ static const struct {
+ const char *name;
+ unsigned int val;
+ } htmap[] = {
+ { .name = "HT20", .val = NL80211_CHAN_HT20, },
+ { .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
+ { .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(htmap); i++) {
+ if (strcasecmp(htmap[i].name, str) == 0) {
+ *htval = htmap[i].val;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
static void print_mcs_index(const __u8 *mcs)
{
unsigned int mcs_bit, prev_bit = -2, prev_cont = 0;



2011-06-21 15:53:33

by Alexander Simon

[permalink] [raw]
Subject: [RFC v3 3/3] mac80211: HT operation in IBSS

My third try of an HT implementation for IBSS.

* HT mode is proposed by nl80211
* Allow frame aggregation to start for IBSS
* Build HT IEs

For fixed channel, HT mode is also fixed. Merge or join only if HT mode of some
other BSS is the same as set by nl80211.

For proposed channel, HT mode is also proposed. This means, if we join a HT
IBSS, its HT mode is taken.
nl80211 HT mode is taken when we join a non-HT ibss (then we "convert" it into
one).
If we see (from a beacon) that the IBSS has a different HT mode, we switch
(first beacon wins, as we all have the same TSF).


I tested this with the following scenario (using wireshark to confirm):
* opening a IBSS with a Realtek under Windows
* join with an ath9k station A without HT
-> both stations joined, no HT beacons
* join a 2nd ath9k station B in HT40+
-> station B sending HT beacons. Interpreted by A, ignored by windows
* A is switching to HT mode
-> HT communication between A and B up and running. 11g with windows.

Todo:
* When switching HT mode, check if we are allow to do that.

Signed-off-by: Alexander Simon <[email protected]>
---
agg-rx.c | 2
agg-tx.c | 5 +-
ht.c | 2
ibss.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
ieee80211_i.h | 2
rx.c | 6 +-
6 files changed, 120 insertions(+), 19 deletions(-)

diff -Nrup a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
--- a/net/mac80211/agg-rx.c 2011-06-01 21:04:24.000000000 +0200
+++ b/net/mac80211/agg-rx.c 2011-06-21 13:21:38.000000000 +0200
@@ -161,6 +161,8 @@ static void ieee80211_send_addba_resp(st
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);
+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);

mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
diff -Nrup a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
--- a/net/mac80211/agg-tx.c 2011-06-01 21:04:33.000000000 +0200
+++ b/net/mac80211/agg-tx.c 2011-06-21 13:21:38.000000000 +0200
@@ -83,6 +83,8 @@ static void ieee80211_send_addba_request
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);
+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);

mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
@@ -398,7 +400,8 @@ int ieee80211_start_tx_ba_session(struct
*/
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
- sdata->vif.type != NL80211_IFTYPE_AP)
+ sdata->vif.type != NL80211_IFTYPE_AP &&
+ sdata->vif.type != NL80211_IFTYPE_ADHOC)
return -EINVAL;

if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
diff -Nrup a/net/mac80211/ht.c b/net/mac80211/ht.c
--- a/net/mac80211/ht.c 2011-06-01 21:04:24.000000000 +0200
+++ b/net/mac80211/ht.c 2011-06-21 13:21:38.000000000 +0200
@@ -197,6 +197,8 @@ void ieee80211_send_delba(struct ieee802
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);
+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);

mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
diff -Nrup a/net/mac80211/ibss.c b/net/mac80211/ibss.c
--- a/net/mac80211/ibss.c 2011-06-01 21:04:24.000000000 +0200
+++ b/net/mac80211/ibss.c 2011-06-21 13:21:38.000000000 +0200
@@ -64,6 +64,7 @@ static void ieee80211_rx_mgmt_auth_ibss(
static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
const u8 *bssid, const int beacon_int,
struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type,
const u32 basic_rates,
const u16 capability, u64 tsf)
{
@@ -104,8 +105,12 @@ static void __ieee80211_sta_join_ibss(st

sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;

+ /* entering a legacy IBSS. Use given HT configuration. */
+ if (channel_type == NL80211_CHAN_NO_HT)
+ channel_type = ifibss->channel_type;
+
local->oper_channel = chan;
- WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
+ WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type));
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);

sband = local->hw.wiphy->bands[chan->band];
@@ -171,6 +176,17 @@ static void __ieee80211_sta_join_ibss(st
memcpy(skb_put(skb, ifibss->ie_len),
ifibss->ie, ifibss->ie_len);

+ if (channel_type != NL80211_CHAN_NO_HT && sband->ht_cap.ht_supported) {
+ pos = skb_put(skb, 4 +
+ sizeof(struct ieee80211_ht_cap) +
+ sizeof(struct ieee80211_ht_info));
+ pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
+ pos = ieee80211_ie_build_ht_info(pos,
+ &sband->ht_cap,
+ chan,
+ channel_type);
+ }
+
if (local->hw.queues >= 4) {
pos = skb_put(skb, 9);
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
@@ -219,6 +235,8 @@ static void ieee80211_sta_join_ibss(stru
u32 basic_rates;
int i, j;
u16 beacon_int = cbss->beacon_interval;
+ const u8 *ht_info_ie;
+ enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;

lockdep_assert_held(&sdata->u.ibss.mtx);

@@ -242,9 +260,15 @@ static void ieee80211_sta_join_ibss(stru
}
}

+ ht_info_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_INFORMATION);
+ if (ht_info_ie)
+ channel_type = ieee80211_ht_info_to_channel_type(
+ (struct ieee80211_ht_info *) (ht_info_ie + 2));
+
__ieee80211_sta_join_ibss(sdata, cbss->bssid,
beacon_int,
cbss->channel,
+ channel_type,
basic_rates,
cbss->capability,
cbss->tsf);
@@ -310,11 +334,65 @@ static void ieee80211_rx_bss_info(struct
} else
sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
mgmt->sa, supp_rates,
- GFP_ATOMIC);
+ elems->ht_cap_elem, GFP_ATOMIC);
}

- if (sta && elems->wmm_info)
- set_sta_flags(sta, WLAN_STA_WME);
+ if (sta) {
+ if (elems->wmm_info)
+ set_sta_flags(sta, WLAN_STA_WME);
+
+ if (elems->ht_info_elem) {
+ struct ieee80211_supported_band *sband =
+ local->hw.wiphy->bands[channel->band];
+ enum nl80211_channel_type channel_type;
+
+ channel_type =
+ ieee80211_ht_info_to_channel_type(
+ elems->ht_info_elem);
+ if (channel_type != local->_oper_channel_type) {
+ struct sk_buff *skb =
+ sdata->u.ibss.presp;
+ struct sk_buff *nskb;
+ u8 *ht_ie;
+
+ nskb = skb_copy(skb, GFP_ATOMIC);
+ ht_ie = cfg80211_find_ie(
+ WLAN_EID_HT_CAPABILITY,
+ nskb->data + 24 +
+ sizeof(mgmt->u.beacon),
+ nskb->len - 24 -
+ sizeof(mgmt->u.beacon));
+
+ if (!ht_ie)
+ ht_ie = skb_put(nskb, 4 +
+ sizeof(struct ieee80211_ht_cap) +
+ sizeof(struct ieee80211_ht_info));
+ ht_ie = ieee80211_ie_build_ht_cap(ht_ie,
+ sband,
+ sband->ht_cap.cap);
+ ht_ie = ieee80211_ie_build_ht_info(
+ ht_ie,
+ &sband->ht_cap,
+ channel,
+ channel_type);
+ sdata->u.ibss.presp = nskb;
+ kfree_skb(skb);
+
+ local->_oper_channel_type =
+ channel_type;
+ WARN_ON(!ieee80211_set_channel_type(
+ local,
+ sdata,
+ channel_type));
+ ieee80211_hw_config(local,
+ IEEE80211_CONF_CHANGE_CHANNEL);
+ }
+ ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+ elems->ht_cap_elem,
+ &sta->sta.ht_cap);
+
+ }
+ }

rcu_read_unlock();
}
@@ -404,7 +482,7 @@ static void ieee80211_rx_bss_info(struct
ieee80211_sta_join_ibss(sdata, bss);
supp_rates = ieee80211_sta_get_rates(local, elems, band);
ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
- supp_rates, GFP_KERNEL);
+ supp_rates, elems->ht_cap_elem, GFP_KERNEL);
}

put_bss:
@@ -417,7 +495,8 @@ static void ieee80211_rx_bss_info(struct
* must be callable in atomic context.
*/
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
- u8 *bssid,u8 *addr, u32 supp_rates,
+ u8 *bssid, u8 *addr, u32 supp_rates,
+ struct ieee80211_ht_cap *ht_cap,
gfp_t gfp)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
@@ -458,6 +537,11 @@ struct sta_info *ieee80211_ibss_add_sta(
sta->sta.supp_rates[band] = supp_rates |
ieee80211_mandatory_rates(local, band);

+ /* fill in ht rates */
+ if (ht_cap)
+ ieee80211_ht_cap_ie_to_sta_ht_cap(local->hw.wiphy->bands[band],
+ ht_cap, &sta->sta.ht_cap);
+
rate_control_rate_init(sta);

/* If it fails, maybe we raced another insertion? */
@@ -556,8 +640,8 @@ static void ieee80211_sta_create_ibss(st
sdata->drop_unencrypted = 0;

__ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
- ifibss->channel, ifibss->basic_rates,
- capability, 0);
+ ifibss->channel, ifibss->channel_type,
+ ifibss->basic_rates, capability, 0);
}

/*
@@ -594,10 +678,10 @@ static void ieee80211_sta_find_ibss(stru
chan = ifibss->channel;
if (!is_zero_ether_addr(ifibss->bssid))
bssid = ifibss->bssid;
- cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid,
+ cbss = cfg80211_get_bss_ht(local->hw.wiphy, chan, bssid,
ifibss->ssid, ifibss->ssid_len,
WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_PRIVACY,
- capability);
+ capability, ifibss->channel_type);

if (cbss) {
struct ieee80211_bss *bss;
@@ -896,11 +980,16 @@ int ieee80211_ibss_join(struct ieee80211
struct sk_buff *skb;

skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
- 36 /* bitrates */ +
- 34 /* SSID */ +
- 3 /* DS params */ +
- 4 /* IBSS params */ +
- params->ie_len);
+ sizeof(struct ieee80211_hdr_3addr) +
+ 12 /* struct ieee80211_mgmt.u.beacon */ +
+ 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ +
+ 2 + 8 /* max Supported Rates */ +
+ 3 /* max DS params */ +
+ 4 /* IBSS params */ +
+ 2 + (IEEE80211_MAX_SUPP_RATES - 8)
+ 2 + sizeof(struct ieee80211_ht_cap) +
+ 2 + sizeof(struct ieee80211_ht_info) +
+ params->ie_len);
if (!skb)
return -ENOMEM;

@@ -920,13 +1009,14 @@ int ieee80211_ibss_join(struct ieee80211
sdata->vif.bss_conf.beacon_int = params->beacon_interval;

sdata->u.ibss.channel = params->channel;
+ sdata->u.ibss.channel_type = params->channel_type;
sdata->u.ibss.fixed_channel = params->channel_fixed;

/* fix ourselves to that channel now already */
if (params->channel_fixed) {
sdata->local->oper_channel = params->channel;
WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata,
- NL80211_CHAN_NO_HT));
+ params->channel_type));
}

if (params->ie) {
diff -Nrup a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
--- a/net/mac80211/ieee80211_i.h 2011-06-01 21:04:32.000000000 +0200
+++ b/net/mac80211/ieee80211_i.h 2011-06-21 13:21:38.000000000 +0200
@@ -439,6 +439,7 @@ struct ieee80211_if_ibss {
u8 ssid_len, ie_len;
u8 *ie;
struct ieee80211_channel *channel;
+ enum nl80211_channel_type channel_type;

unsigned long ibss_join_req;
/* probe response/beacon for IBSS */
@@ -1124,6 +1125,7 @@ void ieee80211_ibss_notify_scan_complete
void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata);
struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
u8 *bssid, u8 *addr, u32 supp_rates,
+ struct ieee80211_ht_cap *ht_cap,
gfp_t gfp);
int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
struct cfg80211_ibss_params *params);
diff -Nrup a/net/mac80211/rx.c b/net/mac80211/rx.c
--- a/net/mac80211/rx.c 2011-06-01 21:04:32.000000000 +0200
+++ b/net/mac80211/rx.c 2011-06-21 13:21:38.000000000 +0200
@@ -2137,7 +2137,8 @@ ieee80211_rx_h_action(struct ieee80211_r
*/
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
- sdata->vif.type != NL80211_IFTYPE_AP)
+ sdata->vif.type != NL80211_IFTYPE_AP &&
+ sdata->vif.type != NL80211_IFTYPE_ADHOC)
break;

/* verify action_code is present */
@@ -2652,7 +2653,8 @@ static int prepare_for_handlers(struct i
else
rate_idx = status->rate_idx;
rx->sta = ieee80211_ibss_add_sta(sdata, bssid,
- hdr->addr2, BIT(rate_idx), GFP_ATOMIC);
+ hdr->addr2, BIT(rate_idx), NULL,
+ GFP_ATOMIC);
}
break;
case NL80211_IFTYPE_MESH_POINT:




2011-06-27 12:50:49

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC v3 3/3] mac80211: HT operation in IBSS

On Tue, 2011-06-21 at 17:53 +0200, Alexander Simon wrote:
> + /* entering a legacy IBSS. Use given HT configuration. */
> + if (channel_type == NL80211_CHAN_NO_HT)
> + channel_type = ifibss->channel_type;
> +
> local->oper_channel = chan;
> - WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
> + WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type));

I don't think you can now safely assume that set_channel_type() will
succeed, but I didn't check the chan.c code for IBSS now. Please explain
why this is OK now if you think that it is. NO_HT is always compatible,
but the HT mode you used won't necessarily be. I think for fixed-channel
mode this might be an issue.

> + local->_oper_channel_type =
> + channel_type;
> + WARN_ON(!ieee80211_set_channel_type(
> + local,
> + sdata,
> + channel_type));

Same here of course.

> @@ -404,7 +482,7 @@ static void ieee80211_rx_bss_info(struct
> ieee80211_sta_join_ibss(sdata, bss);
> supp_rates = ieee80211_sta_get_rates(local, elems, band);
> ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
> - supp_rates, GFP_KERNEL);
> + supp_rates, elems->ht_cap_elem, GFP_KERNEL);

indentation?

johannes


2011-06-24 18:56:35

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC v3 2/3] nl80211: channel type attribute for IBSS

On 2011-06-21 5:52 PM, Alexander Simon wrote:
> Allow nl80211 to set a ht channel for ibss.
>
> Signed-off-by: Alexander Simon<[email protected]>
>
> diff -Nrup a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> --- a/net/wireless/nl80211.c 2011-06-01 21:04:33.000000000 +0200
> +++ b/net/wireless/nl80211.c 2011-06-21 13:21:38.000000000 +0200
> @@ -4266,12 +4266,37 @@ static int nl80211_join_ibss(struct sk_b
> ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
> }
>
> - ibss.channel = ieee80211_get_channel(wiphy,
> - nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
> - if (!ibss.channel ||
> + if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
> + enum nl80211_channel_type channel_type;
> +
> + channel_type = nla_get_u32(
> + info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
> + if (channel_type != NL80211_CHAN_NO_HT&&
> + channel_type != NL80211_CHAN_HT20&&
> + channel_type != NL80211_CHAN_HT40PLUS&&
> + channel_type != NL80211_CHAN_HT40MINUS)
> + return -EINVAL;
> + ibss.channel_type = channel_type;
> + } else {
> + ibss.channel_type = NL80211_CHAN_NO_HT;
> + }
> +
> + ibss.channel = rdev_freq_to_chan(rdev,
> + nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
> + ibss.channel_type);
> + /*if (!ibss.channel ||
> + ibss.channel->flags& IEEE80211_CHAN_PASSIVE_SCAN ||
> ibss.channel->flags& IEEE80211_CHAN_NO_IBSS ||
> - ibss.channel->flags& IEEE80211_CHAN_DISABLED)
> + ibss.channel->flags& IEEE80211_CHAN_RADAR)
> + return -EINVAL;
> + if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
> + ibss.channel_type == NL80211_CHAN_HT40MINUS)&&
> + !can_beacon_sec_chan(&rdev->wiphy, ibss.chan, ibss.channel_type)) {
> + printk(KERN_DEBUG
> + "cfg80211: Secondary channel not "
> + "allowed to initiate communication\n");
> return -EINVAL;
> + }*/
That last part looks like a debugging hack, you should remove it before
re-submitting that patch.

- Felix

2011-06-24 19:02:00

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC v3 1/3] mac80211: add some helper functions

On 2011-06-21 5:45 PM, Alexander Simon wrote:
> Add helper functions cfg80211_get_bss_ht, ieee80211_ie_build_ht_cap
> and ieee80211_ie_build_ht_info.
> These are needed for my IBSS HT patch but are also used to clean up some
> multiple code.
>
> Signed-off-by: Alexander Simon<[email protected]>
> ---
> include/net/cfg80211.h | 6 ++
> net/mac80211/ieee80211_i.h | 8 +++
> net/mac80211/util.c | 116 ++++++++++++++++++++++++++++++++++++++-------
> net/mac80211/work.c | 29 -----------
> net/wireless/scan.c | 36 +++++++++++++
> 5 files changed, 148 insertions(+), 47 deletions(-)
>
> diff -Nrup a/net/wireless/scan.c b/net/wireless/scan.c
> --- a/net/wireless/scan.c 2011-06-01 21:04:32.000000000 +0200
> +++ b/net/wireless/scan.c 2011-06-21 13:21:38.000000000 +0200
> @@ -370,7 +401,8 @@ struct cfg80211_bss *cfg80211_get_bss(st
> return NULL;
> return&res->pub;
> }
> EXPORT_SYMBOL(cfg80211_get_bss);
> +EXPORT_SYMBOL(cfg80211_get_bss_ht);
Duplicate export of cfg80211_get_bss

- Felix

2011-06-27 12:51:20

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC v3 3/3] mac80211: HT operation in IBSS

A more fundamental question:

How are we going to handle overlapping BSSes for HT40?

johannes


2011-06-27 12:46:43

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC v3 2/3] nl80211: channel type attribute for IBSS

On Tue, 2011-06-21 at 17:52 +0200, Alexander Simon wrote:

> + ibss.channel = rdev_freq_to_chan(rdev,
> + nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
> + ibss.channel_type);
> + /*if (!ibss.channel ||

You must be joking.

johannes



2011-06-24 19:21:09

by Felix Fietkau

[permalink] [raw]
Subject: Re: [RFC v3 3/3] mac80211: HT operation in IBSS

On 2011-06-21 5:53 PM, Alexander Simon wrote:
> My third try of an HT implementation for IBSS.
>
> * HT mode is proposed by nl80211
> * Allow frame aggregation to start for IBSS
> * Build HT IEs
>
> For fixed channel, HT mode is also fixed. Merge or join only if HT mode of some
> other BSS is the same as set by nl80211.
>
> For proposed channel, HT mode is also proposed. This means, if we join a HT
> IBSS, its HT mode is taken.
> nl80211 HT mode is taken when we join a non-HT ibss (then we "convert" it into
> one).
> If we see (from a beacon) that the IBSS has a different HT mode, we switch
> (first beacon wins, as we all have the same TSF).
>
>
> I tested this with the following scenario (using wireshark to confirm):
> * opening a IBSS with a Realtek under Windows
> * join with an ath9k station A without HT
> -> both stations joined, no HT beacons
> * join a 2nd ath9k station B in HT40+
> -> station B sending HT beacons. Interpreted by A, ignored by windows
> * A is switching to HT mode
> -> HT communication between A and B up and running. 11g with windows.
>
> Todo:
> * When switching HT mode, check if we are allow to do that.
>
> Signed-off-by: Alexander Simon<[email protected]>
> ---
> agg-rx.c | 2
> agg-tx.c | 5 +-
> ht.c | 2
> ibss.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
> ieee80211_i.h | 2
> rx.c | 6 +-
> 6 files changed, 120 insertions(+), 19 deletions(-)
>
> diff -Nrup a/net/mac80211/ibss.c b/net/mac80211/ibss.c
> --- a/net/mac80211/ibss.c 2011-06-01 21:04:24.000000000 +0200
> +++ b/net/mac80211/ibss.c 2011-06-21 13:21:38.000000000 +0200
> @@ -310,11 +334,65 @@ static void ieee80211_rx_bss_info(struct
> } else
> sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
> mgmt->sa, supp_rates,
> - GFP_ATOMIC);
> + elems->ht_cap_elem, GFP_ATOMIC);
> }
>
> - if (sta&& elems->wmm_info)
> - set_sta_flags(sta, WLAN_STA_WME);
> + if (sta) {
> + if (elems->wmm_info)
> + set_sta_flags(sta, WLAN_STA_WME);
> +
> + if (elems->ht_info_elem) {
> + struct ieee80211_supported_band *sband =
> + local->hw.wiphy->bands[channel->band];
> + enum nl80211_channel_type channel_type;
> +
> + channel_type =
> + ieee80211_ht_info_to_channel_type(
> + elems->ht_info_elem);
> + if (channel_type != local->_oper_channel_type) {
> + struct sk_buff *skb =
> + sdata->u.ibss.presp;
sdata->u.ibss.presp is RCU protected, you need to use rcu_dereference().

> + struct sk_buff *nskb;
> + u8 *ht_ie;
> +
> + nskb = skb_copy(skb, GFP_ATOMIC);
> + ht_ie = cfg80211_find_ie(
> + WLAN_EID_HT_CAPABILITY,
> + nskb->data + 24 +
> + sizeof(mgmt->u.beacon),
> + nskb->len - 24 -
> + sizeof(mgmt->u.beacon));
cfg80211_find_ie returns a const u8, so the compiler generates a warning.

> @@ -896,11 +980,16 @@ int ieee80211_ibss_join(struct ieee80211
> struct sk_buff *skb;
>
> skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
> - 36 /* bitrates */ +
> - 34 /* SSID */ +
> - 3 /* DS params */ +
> - 4 /* IBSS params */ +
> - params->ie_len);
> + sizeof(struct ieee80211_hdr_3addr) +
> + 12 /* struct ieee80211_mgmt.u.beacon */ +
> + 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ +
> + 2 + 8 /* max Supported Rates */ +
> + 3 /* max DS params */ +
> + 4 /* IBSS params */ +
> + 2 + (IEEE80211_MAX_SUPP_RATES - 8)
Does not compile, missing '+'
> + 2 + sizeof(struct ieee80211_ht_cap) +
> + 2 + sizeof(struct ieee80211_ht_info) +
> + params->ie_len);
> if (!skb)
> return -ENOMEM;
>


2011-06-27 12:46:09

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC v3 1/3] mac80211: add some helper functions

On Tue, 2011-06-21 at 17:45 +0200, Alexander Simon wrote:

> +struct cfg80211_bss *cfg80211_get_bss_ht(struct wiphy *wiphy,
> + struct ieee80211_channel *channel,
> + const u8 *bssid,
> + const u8 *ssid, size_t ssid_len,
> + u16 capa_mask, u16 capa_val,
> + enum nl80211_channel_type channel_type);

indentation confusion?

Also, this definitely doesn't belong into a mac80211 patch. Please split
into mac80211/cfg80211.

> --- a/net/wireless/scan.c 2011-06-01 21:04:32.000000000 +0200
> +++ b/net/wireless/scan.c 2011-06-21 13:21:38.000000000 +0200
> @@ -343,6 +343,18 @@ struct cfg80211_bss *cfg80211_get_bss(st
> const u8 *ssid, size_t ssid_len,
> u16 capa_mask, u16 capa_val)
> {
> + return cfg80211_get_bss_ht(wiphy, channel, bssid, ssid, ssid_len,
> + capa_mask, capa_val, NL80211_CHAN_NO_HT);
> +}
> +EXPORT_SYMBOL(cfg80211_get_bss);

This is misleading/confusing. You're passing NO_HT in order to ignore
the channel bandwidth, but you make it seem like it's a filter. Also,
you didn't update _any_ documentation at all!

johannes


2011-06-21 16:02:37

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC v3 1/3] mac80211: add some helper functions

On Tue, 2011-06-21 at 17:45 +0200, Alexander Simon wrote:
> Add helper functions cfg80211_get_bss_ht, ieee80211_ie_build_ht_cap
> and ieee80211_ie_build_ht_info.
> These are needed for my IBSS HT patch but are also used to clean up some
> multiple code.

I'll review in the next couple of days, but we have a holiday on
Thursday and I'll take Friday off so it might be next week.

johannes


2011-06-21 15:52:27

by Alexander Simon

[permalink] [raw]
Subject: [RFC v3 2/3] nl80211: channel type attribute for IBSS

Allow nl80211 to set a ht channel for ibss.

Signed-off-by: Alexander Simon <[email protected]>
---
include/net/cfg80211.h | 1 +
net/wireless/nl80211.c | 33 +++++++++++++++++++++++++++++----
2 files changed, 30 insertions(+), 4 deletions(-)

diff -Nrup a/include/net/cfg80211.h b/include/net/cfg80211.h
--- a/include/net/cfg80211.h 2011-06-01 21:04:33.000000000 +0200
+++ b/include/net/cfg80211.h 2011-06-21 13:21:38.000000000 +0200
@@ -1038,6 +1038,7 @@ struct cfg80211_ibss_params {
u8 *ssid;
u8 *bssid;
struct ieee80211_channel *channel;
+ enum nl80211_channel_type channel_type;
u8 *ie;
u8 ssid_len, ie_len;
u16 beacon_interval;
diff -Nrup a/net/wireless/nl80211.c b/net/wireless/nl80211.c
--- a/net/wireless/nl80211.c 2011-06-01 21:04:33.000000000 +0200
+++ b/net/wireless/nl80211.c 2011-06-21 13:21:38.000000000 +0200
@@ -4266,12 +4266,37 @@ static int nl80211_join_ibss(struct sk_b
ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
}

- ibss.channel = ieee80211_get_channel(wiphy,
- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
- if (!ibss.channel ||
+ if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
+ enum nl80211_channel_type channel_type;
+
+ channel_type = nla_get_u32(
+ info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
+ if (channel_type != NL80211_CHAN_NO_HT &&
+ channel_type != NL80211_CHAN_HT20 &&
+ channel_type != NL80211_CHAN_HT40PLUS &&
+ channel_type != NL80211_CHAN_HT40MINUS)
+ return -EINVAL;
+ ibss.channel_type = channel_type;
+ } else {
+ ibss.channel_type = NL80211_CHAN_NO_HT;
+ }
+
+ ibss.channel = rdev_freq_to_chan(rdev,
+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
+ ibss.channel_type);
+ /*if (!ibss.channel ||
+ ibss.channel->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
- ibss.channel->flags & IEEE80211_CHAN_DISABLED)
+ ibss.channel->flags & IEEE80211_CHAN_RADAR)
+ return -EINVAL;
+ if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
+ ibss.channel_type == NL80211_CHAN_HT40MINUS) &&
+ !can_beacon_sec_chan(&rdev->wiphy, ibss.chan, ibss.channel_type)) {
+ printk(KERN_DEBUG
+ "cfg80211: Secondary channel not "
+ "allowed to initiate communication\n");
return -EINVAL;
+ }*/

ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];




2011-06-27 12:42:17

by Johannes Berg

[permalink] [raw]
Subject: Re: patch for iw

On Tue, 2011-06-21 at 18:01 +0200, Alexander Simon wrote:

> @@ -44,6 +45,12 @@ static int join_ibss(struct nl80211_stat
> argv++;
> argc--;
>
> + if (argc && parse_channel_type(argv[0], &htval)) {
> + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, htval);
> + argv++;
> + argc--;
> + }

> +/*
> + * Convert a string "HT20", "HT40+" or "HT40-" into nl80211
> + * value. Conversion is case insensitive. Returns 1 on success, 0 on error.
> + */
> +
> +int parse_channel_type(const char *str, unsigned int *htval)

That return value isn't the way other functions return their status in
iw, so I won't apply this, it'll just confuse things.

johannes


2011-07-04 10:10:16

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC v3 2/3] nl80211: channel type attribute for IBSS

On Mon, 2011-07-04 at 12:07 +0200, Alexander Simon wrote:

> Johannes, please don't forget that is still is RFC. And only useful
> comments can help me :).

You're asking me to spend time reviewing this code. Make sure it's in
consumable form first.

johannes


2011-07-04 10:07:14

by Alexander Simon

[permalink] [raw]
Subject: Re: [RFC v3 2/3] nl80211: channel type attribute for IBSS

Of course i would.

I did not delete it as it is needed for the (still to do)
can-we-use-that-channel check (i think i will need to write a new
function for this as i need to check at several points). It didn't run
(yet).

Johannes, please don't forget that is still is RFC. And only useful
comments can help me :).