2010-06-08 12:34:38

by Teemu Paasikivi

[permalink] [raw]
Subject: [RFC 0/3] mac80211: Add support for configuring ibss basic rates

This patch set implements support for configuring basic rates for ibss network when joining/creating one. First two patches are basically patch proposed by Johannes Berg on linux-wireless posting list split in two. These implement interface to nl80211 to do actual configuration from user space. Last patch is to fix a problem when leaving and joining back to self created ibss network, without this basic rates would be left unset. That is caused by the fact that the stack holds information for the self created bss and when rejoining it looks like already existing ibss network. This causes little annoyance (bug?) by preventing changing basic rates once ibss is created as long as the stack holds the information.

Teemu Paasikivi (3):
mac80211: Set basic rates while joining ibss network
mac80211: Set changed basic rates flag
mac80211: Store basic rates for bss when joining ibss network

include/net/cfg80211.h | 2 +
net/mac80211/ibss.c | 19 ++++++++++++++++-
net/mac80211/ieee80211_i.h | 2 +
net/wireless/nl80211.c | 49 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 71 insertions(+), 1 deletions(-)



2010-06-09 04:46:22

by Teemu Paasikivi

[permalink] [raw]
Subject: Re: [RFC 3/3] mac80211: Store basic rates for bss when joining ibss network

On Tue, 2010-06-08 at 14:48 +0200, ext Johannes Berg wrote:
> On Tue, 2010-06-08 at 15:34 +0300, Teemu Paasikivi wrote:
> > When joinig a ibss network, basic rates for bss were not stored. When
> > network was self created, leaving and (re)joining same network has
> > caused basic rates to be left unset. With this patch stored values are
> > used.
>
> > bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel,
> > mgmt, skb->len, 0, GFP_KERNEL);
> > +
> > + ibss = (struct ieee80211_bss *)(bss->priv);
>
> Watch out -- bss can be NULL here if memory allocation fails. It's just
> that put_bss(NULL) is valid.
>

That's correct. My fault, how could I miss that? Obviously easily.


> > + for (i = 0; i < sband->n_bitrates; i++) {
> > + u8 basic = 0x00;
> > + if (basic_rates & BIT(i))
> > + basic = 0x80;
> > +
> > + ibss->supp_rates[i] = supp_rates[i] | basic;
> > + }
> > +
> > + ibss->supp_rates_len = i;
> > +
> > cfg80211_put_bss(bss);
>
>
> However this kinda confuses me.
>
> We had a long-standing TODO item on our list at
> http://wireless.kernel.org/en/developers/todo-list
>
> "when leaving an IBSS and we were the only member, remove it from
> cfg80211's BSS list"
>
> Maybe that would help here too?
>

Yes, I think that would propably solve that issue where IBSS was
recreated and requested basic rates are changed.

> However I don't understand the scenario anyway. If you create an IBSS,
> you start beaconing and tell cfg80211 about it with a frame that
> includes the supported and basic rates. Then you leave, but the BSS
> stays around in cfg80211 for 15 seconds. If you re-join within those 15
> seconds, the scan results will pick up the old IBSS that no longer
> exists, and we "join" it rather than creating it.
>
> However -- joining it will take the basic rates from it. So wouldn't you
> get the old basic rates which is fine? What do you mean by "left unset"?
>

By "left unset" I mean that in the sniffer logs there's no rates marked
as basic rates in the beacons. No old ones or new ones.

> What happens if you join an IBSS that already exists?
>

It works, but I haven't captured what's in the air. That's one reason
why I sent these patches as RFC.



Teemu



2010-06-08 12:35:04

by Teemu Paasikivi

[permalink] [raw]
Subject: [RFC 3/3] mac80211: Store basic rates for bss when joining ibss network

When joinig a ibss network, basic rates for bss were not stored. When
network was self created, leaving and (re)joining same network has
caused basic rates to be left unset. With this patch stored values are
used.

Signed-off-by: Teemu Paasikivi <[email protected]>
---
net/mac80211/ibss.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index d984ab2..72407f0 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -77,6 +77,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
struct cfg80211_bss *bss;
u32 bss_change;
u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
+ struct ieee80211_bss *ibss;

/* Reset own TSF to allow time synchronization work. */
drv_reset_tsf(local);
@@ -191,6 +192,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,

bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel,
mgmt, skb->len, 0, GFP_KERNEL);
+
+ ibss = (struct ieee80211_bss *)(bss->priv);
+
+ for (i = 0; i < sband->n_bitrates; i++) {
+ u8 basic = 0x00;
+ if (basic_rates & BIT(i))
+ basic = 0x80;
+
+ ibss->supp_rates[i] = supp_rates[i] | basic;
+ }
+
+ ibss->supp_rates_len = i;
+
cfg80211_put_bss(bss);
cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
}
--
1.5.6.3


2010-06-08 12:34:39

by Teemu Paasikivi

[permalink] [raw]
Subject: [RFC 1/3] mac80211: Set basic rates while joining ibss network

This patch adds support to nl80211 and mac80211 to set basic rates when
joining/creating ibss network.

Original patch was posted by Johannes Berg on the linux-wireless posting list.

Signed-off-by: Teemu Paasikivi <[email protected]>
---
include/net/cfg80211.h | 2 +
net/mac80211/ibss.c | 4 ++-
net/mac80211/ieee80211_i.h | 2 +
net/wireless/nl80211.c | 49 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 56 insertions(+), 1 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 0c3c214..4ff4e1f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -801,6 +801,7 @@ struct cfg80211_disassoc_request {
* @beacon_interval: beacon interval to use
* @privacy: this is a protected network, keys will be configured
* after joining
+ * @basic_rates: bitmap of basic rates to use when creating the IBSS
*/
struct cfg80211_ibss_params {
u8 *ssid;
@@ -809,6 +810,7 @@ struct cfg80211_ibss_params {
u8 *ie;
u8 ssid_len, ie_len;
u16 beacon_interval;
+ u32 basic_rates;
bool channel_fixed;
bool privacy;
};
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index d7a96ce..8be5a96 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -172,6 +172,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
rcu_assign_pointer(ifibss->presp, skb);

sdata->vif.bss_conf.beacon_int = beacon_int;
+ sdata->vif.bss_conf.basic_rates = basic_rates;
bss_change = BSS_CHANGED_BEACON_INT;
bss_change |= ieee80211_reset_erp_info(sdata);
bss_change |= BSS_CHANGED_BSSID;
@@ -529,7 +530,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
sdata->drop_unencrypted = 0;

__ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
- ifibss->channel, 3, /* first two are basic */
+ ifibss->channel, ifibss->basic_rates,
capability, 0);
}

@@ -910,6 +911,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
sdata->u.ibss.fixed_bssid = false;

sdata->u.ibss.privacy = params->privacy;
+ sdata->u.ibss.basic_rates = params->basic_rates;

sdata->vif.bss_conf.beacon_int = params->beacon_interval;

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4d3883e..fde058b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -393,6 +393,8 @@ struct ieee80211_if_ibss {
unsigned long request;
unsigned long last_scan_completed;

+ u32 basic_rates;
+
bool timer_running;

bool fixed_bssid;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 90ab3c8..324b4a5 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3955,6 +3955,55 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
}
}

+ if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
+ u8 *rates =
+ nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
+ int n_rates =
+ nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
+ struct ieee80211_supported_band *sband =
+ wiphy->bands[ibss.channel->band];
+ int i, j;
+
+ if (n_rates == 0) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < n_rates; i++) {
+ int rate = (rates[i] & 0x7f) * 5;
+ bool found = false;
+
+ for (j = 0; j < sband->n_bitrates; j++) {
+ if (sband->bitrates[j].bitrate == rate) {
+ found = true;
+ ibss.basic_rates |= BIT(j);
+ break;
+ }
+ }
+ if (!found) {
+ err = -EINVAL;
+ goto out;
+ }
+ }
+ } else {
+ /*
+ * If no rates were explicitly configured,
+ * use the mandatory rate set for 11b or
+ * 11a for maximum compatibility.
+ */
+ struct ieee80211_supported_band *sband =
+ wiphy->bands[ibss.channel->band];
+ int j;
+ u32 flag = ibss.channel->band == IEEE80211_BAND_5GHZ ?
+ IEEE80211_RATE_MANDATORY_A :
+ IEEE80211_RATE_MANDATORY_B;
+
+ for (j = 0; j < sband->n_bitrates; j++) {
+ if (sband->bitrates[j].flags & flag)
+ ibss.basic_rates |= BIT(j);
+ }
+ }
+
err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);

out:
--
1.5.6.3


2010-06-09 07:37:00

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC 3/3] mac80211: Store basic rates for bss when joining ibss network

On Wed, 2010-06-09 at 07:45 +0300, Teemu Paasikivi wrote:

> > However this kinda confuses me.
> >
> > We had a long-standing TODO item on our list at
> > http://wireless.kernel.org/en/developers/todo-list
> >
> > "when leaving an IBSS and we were the only member, remove it from
> > cfg80211's BSS list"
> >
> > Maybe that would help here too?
> >
>
> Yes, I think that would propably solve that issue where IBSS was
> recreated and requested basic rates are changed.

Want to take a look at it? It shouldn't be too hard -- just call
cfg80211_unlink_bss() somewhere where we still have the BSS pointer.
Actually we don't keep it as you saw with the update, so need to find it
first and then unlink it.

> > However I don't understand the scenario anyway. If you create an IBSS,
> > you start beaconing and tell cfg80211 about it with a frame that
> > includes the supported and basic rates. Then you leave, but the BSS
> > stays around in cfg80211 for 15 seconds. If you re-join within those 15
> > seconds, the scan results will pick up the old IBSS that no longer
> > exists, and we "join" it rather than creating it.
> >
> > However -- joining it will take the basic rates from it. So wouldn't you
> > get the old basic rates which is fine? What do you mean by "left unset"?
> >
>
> By "left unset" I mean that in the sniffer logs there's no rates marked
> as basic rates in the beacons. No old ones or new ones.

Ok that's what I thought. But ... are they marked in our TX beacons when
we _first_ created the IBSS?

> > What happens if you join an IBSS that already exists?
> >
>
> It works, but I haven't captured what's in the air. That's one reason
> why I sent these patches as RFC.

I don't really see how the two scenarios differ, so that's odd...

johannes


2010-06-08 12:48:46

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC 3/3] mac80211: Store basic rates for bss when joining ibss network

On Tue, 2010-06-08 at 15:34 +0300, Teemu Paasikivi wrote:
> When joinig a ibss network, basic rates for bss were not stored. When
> network was self created, leaving and (re)joining same network has
> caused basic rates to be left unset. With this patch stored values are
> used.

> bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel,
> mgmt, skb->len, 0, GFP_KERNEL);
> +
> + ibss = (struct ieee80211_bss *)(bss->priv);

Watch out -- bss can be NULL here if memory allocation fails. It's just
that put_bss(NULL) is valid.

> + for (i = 0; i < sband->n_bitrates; i++) {
> + u8 basic = 0x00;
> + if (basic_rates & BIT(i))
> + basic = 0x80;
> +
> + ibss->supp_rates[i] = supp_rates[i] | basic;
> + }
> +
> + ibss->supp_rates_len = i;
> +
> cfg80211_put_bss(bss);


However this kinda confuses me.

We had a long-standing TODO item on our list at
http://wireless.kernel.org/en/developers/todo-list

"when leaving an IBSS and we were the only member, remove it from
cfg80211's BSS list"

Maybe that would help here too?

However I don't understand the scenario anyway. If you create an IBSS,
you start beaconing and tell cfg80211 about it with a frame that
includes the supported and basic rates. Then you leave, but the BSS
stays around in cfg80211 for 15 seconds. If you re-join within those 15
seconds, the scan results will pick up the old IBSS that no longer
exists, and we "join" it rather than creating it.

However -- joining it will take the basic rates from it. So wouldn't you
get the old basic rates which is fine? What do you mean by "left unset"?

What happens if you join an IBSS that already exists?

johannes


2010-06-10 11:38:20

by Teemu Paasikivi

[permalink] [raw]
Subject: Re: [RFC 3/3] mac80211: Store basic rates for bss when joining ibss network

On Wed, 2010-06-09 at 09:36 +0200, ext Johannes Berg wrote:
> On Wed, 2010-06-09 at 07:45 +0300, Teemu Paasikivi wrote:
>
> > > However this kinda confuses me.
> > >
> > > We had a long-standing TODO item on our list at
> > > http://wireless.kernel.org/en/developers/todo-list
> > >
> > > "when leaving an IBSS and we were the only member, remove it from
> > > cfg80211's BSS list"
> > >
> > > Maybe that would help here too?
> > >
> >
> > Yes, I think that would propably solve that issue where IBSS was
> > recreated and requested basic rates are changed.
>
> Want to take a look at it? It shouldn't be too hard -- just call
> cfg80211_unlink_bss() somewhere where we still have the BSS pointer.
> Actually we don't keep it as you saw with the update, so need to find it
> first and then unlink it.
>

I'll take a look at this. I think BSS can be got by the same method as
in the ieee80211_sta_find_ibss function.

> > > However I don't understand the scenario anyway. If you create an IBSS,
> > > you start beaconing and tell cfg80211 about it with a frame that
> > > includes the supported and basic rates. Then you leave, but the BSS
> > > stays around in cfg80211 for 15 seconds. If you re-join within those 15
> > > seconds, the scan results will pick up the old IBSS that no longer
> > > exists, and we "join" it rather than creating it.
> > >
> > > However -- joining it will take the basic rates from it. So wouldn't you
> > > get the old basic rates which is fine? What do you mean by "left unset"?
> > >
> >
> > By "left unset" I mean that in the sniffer logs there's no rates marked
> > as basic rates in the beacons. No old ones or new ones.
>
> Ok that's what I thought. But ... are they marked in our TX beacons when
> we _first_ created the IBSS?

Yes those were marked. In any case, lets see if this is an issue after
implementing that removal of the BSS from the cfg80211's list.

>
> > > What happens if you join an IBSS that already exists?
> > >
> >
> > It works, but I haven't captured what's in the air. That's one reason
> > why I sent these patches as RFC.
>
> I don't really see how the two scenarios differ, so that's odd...
>
> johannes
>

Teemu



2010-06-08 12:34:44

by Teemu Paasikivi

[permalink] [raw]
Subject: [RFC 2/3] mac80211: Set changed basic rates flag

Add changed basic rates flag to bss_changed while joinig ibss network.

This patch is split from the patch containing support for setting basic
rates when creating ibss network. Original patch was posted by Johannes
Berg on the linux-wireless posting list.

Signed-off-by: Teemu Paasikivi <[email protected]>
---
net/mac80211/ibss.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 8be5a96..d984ab2 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -179,6 +179,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
bss_change |= BSS_CHANGED_BEACON;
bss_change |= BSS_CHANGED_BEACON_ENABLED;
bss_change |= BSS_CHANGED_IBSS;
+ bss_change |= BSS_CHANGED_BASIC_RATES;
sdata->vif.bss_conf.ibss_joined = true;
ieee80211_bss_info_change_notify(sdata, bss_change);

--
1.5.6.3