* [PATCH 4/7] [compat-2.6] Clean up compat-2.6.26.c
From: Hauke Mehrtens @ 2009-08-08 12:38 UTC (permalink / raw)
To: lrodriguez; +Cc: linux-wireless, Hauke Mehrtens
In-Reply-To: <1249735096-27071-1-git-send-email-hauke@hauke-m.de>
The exported methods are not used.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
compat/compat-2.6.26.c | 107 ------------------------------------------------
1 files changed, 0 insertions(+), 107 deletions(-)
diff --git a/compat/compat-2.6.26.c b/compat/compat-2.6.26.c
index 206e2f1..960a79a 100644
--- a/compat/compat-2.6.26.c
+++ b/compat/compat-2.6.26.c
@@ -19,75 +19,6 @@
/* All things not in 2.6.25 */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
-#include <linux/kobject.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/stat.h>
-#include <linux/slab.h>
-
-static void device_create_release(struct device *dev)
-{
- pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
- kfree(dev);
-}
-
-/**
- * device_create_vargs - creates a device and registers it with sysfs
- * @class: pointer to the struct class that this device should be registered to
- * @parent: pointer to the parent struct device of this new device, if any
- * @devt: the dev_t for the char device to be added
- * @drvdata: the data to be added to the device for callbacks
- * @fmt: string for the device's name
- * @args: va_list for the device's name
- *
- * This function can be used by char device classes. A struct device
- * will be created in sysfs, registered to the specified class.
- *
- * A "dev" file will be created, showing the dev_t for the device, if
- * the dev_t is not 0,0.
- * If a pointer to a parent struct device is passed in, the newly created
- * struct device will be a child of that device in sysfs.
- * The pointer to the struct device will be returned from the call.
- * Any further sysfs files that might be required can be created using this
- * pointer.
- *
- * Note: the struct class passed to this function must have previously
- * been created with a call to class_create().
- */
-struct device *device_create_vargs(struct class *class, struct device *parent,
- dev_t devt, void *drvdata, const char *fmt,
- va_list args)
-{
- struct device *dev = NULL;
- int retval = -ENODEV;
-
- if (class == NULL || IS_ERR(class))
- goto error;
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev) {
- retval = -ENOMEM;
- goto error;
- }
-
- dev->devt = devt;
- dev->class = class;
- dev->parent = parent;
- dev->release = device_create_release;
- dev_set_drvdata(dev, drvdata);
-
- vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);
- retval = device_register(dev);
- if (retval)
- goto error;
-
- return dev;
-
-error:
- kfree(dev);
- return ERR_PTR(retval);
-}
-EXPORT_SYMBOL_GPL(device_create_vargs);
/**
* kobject_set_name_vargs - Set the name of an kobject
@@ -134,43 +65,5 @@ int dev_set_name(struct device *dev, const char *fmt, ...)
}
EXPORT_SYMBOL_GPL(dev_set_name);
-
-/**
- * device_create_drvdata - creates a device and registers it with sysfs
- * @class: pointer to the struct class that this device should be registered to
- * @parent: pointer to the parent struct device of this new device, if any
- * @devt: the dev_t for the char device to be added
- * @drvdata: the data to be added to the device for callbacks
- * @fmt: string for the device's name
- *
- * This function can be used by char device classes. A struct device
- * will be created in sysfs, registered to the specified class.
- *
- * A "dev" file will be created, showing the dev_t for the device, if
- * the dev_t is not 0,0.
- * If a pointer to a parent struct device is passed in, the newly created
- * struct device will be a child of that device in sysfs.
- * The pointer to the struct device will be returned from the call.
- * Any further sysfs files that might be required can be created using this
- * pointer.
- *
- * Note: the struct class passed to this function must have previously
- * been created with a call to class_create().
- */
-struct device *device_create_drvdata(struct class *class,
- struct device *parent,
- dev_t devt,
- void *drvdata,
- const char *fmt, ...)
-{
- va_list vargs;
- struct device *dev;
-
- va_start(vargs, fmt);
- dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
- va_end(vargs);
- return dev;
-}
-EXPORT_SYMBOL_GPL(device_create_drvdata);
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) */
--
1.6.2.1
^ permalink raw reply related
* [PATCH 3/7] [compat-2.6] pcmcia_parse_tuple was redefined in pcmcia/cistpl.h
From: Hauke Mehrtens @ 2009-08-08 12:38 UTC (permalink / raw)
To: lrodriguez; +Cc: linux-wireless, Hauke Mehrtens
In-Reply-To: <1249735096-27071-1-git-send-email-hauke@hauke-m.de>
fix build:
undef pcmcia_parse_tuple before redefine it again.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
compat/compat-2.6.28.h | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/compat/compat-2.6.28.h b/compat/compat-2.6.28.h
index fdc021a..e25259f 100644
--- a/compat/compat-2.6.28.h
+++ b/compat/compat-2.6.28.h
@@ -29,7 +29,13 @@
})
#endif /* From include/asm-generic/bug.h */
-#define pcmcia_parse_tuple(tuple, parse) pcmcia_parse_tuple(NULL, tuple, parse)
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#ifdef pcmcia_parse_tuple
+#undef pcmcia_parse_tuple
+#define pcmcia_parse_tuple(tuple, parse) pccard_parse_tuple(tuple, parse)
+#endif
#if 0
extern void usb_poison_urb(struct urb *urb);
--
1.6.2.1
^ permalink raw reply related
* [PATCH 2/7] [compat-2.6] Add missing compat-2.6.*.c files
From: Hauke Mehrtens @ 2009-08-08 12:38 UTC (permalink / raw)
To: lrodriguez; +Cc: linux-wireless, Hauke Mehrtens
In-Reply-To: <1249735096-27071-1-git-send-email-hauke@hauke-m.de>
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
compat/patches/98-add-compat-wireless.patch | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/compat/patches/98-add-compat-wireless.patch b/compat/patches/98-add-compat-wireless.patch
index 1c7b39a..791bc6b 100644
--- a/compat/patches/98-add-compat-wireless.patch
+++ b/compat/patches/98-add-compat-wireless.patch
@@ -19,11 +19,16 @@ added compat.h also for ssb, I forget.
--- a/net/wireless/Makefile 2009-08-07 12:27:50.836497001 -0700
+++ b/net/wireless/Makefile 2009-08-07 12:27:51.952497240 -0700
-@@ -11,3 +11,11 @@
+@@ -11,3 +11,16 @@
cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o wext-sme.o
ccflags-y += -D__CHECK_ENDIAN__
+# Compat-wireless kernel compatibility code
++cfg80211-y += compat-2.6.22.o
++cfg80211-y += compat-2.6.23.o
++cfg80211-y += compat-2.6.24.o
++cfg80211-y += compat-2.6.25.o
++cfg80211-y += compat-2.6.26.o
+cfg80211-y += compat-2.6.27.o
+cfg80211-y += compat-2.6.28.o
+cfg80211-y += compat-2.6.29.o
--
1.6.2.1
^ permalink raw reply related
* [PATCH 1/7] [compat-2.6] Rename the rest of CONFIG_MAC80211_MESH to CONFIG_COMPAT_MAC80211_MESH
From: Hauke Mehrtens @ 2009-08-08 12:38 UTC (permalink / raw)
To: lrodriguez; +Cc: linux-wireless, Hauke Mehrtens
Without this, some symbols can not be resolved because only parts of mesh were disabled.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
compat/patches/08-disable-mesh.patch | 85 ++++++++++++++++++++++++++++++++++
1 files changed, 85 insertions(+), 0 deletions(-)
diff --git a/compat/patches/08-disable-mesh.patch b/compat/patches/08-disable-mesh.patch
index b11be2b..4dee94b 100644
--- a/compat/patches/08-disable-mesh.patch
+++ b/compat/patches/08-disable-mesh.patch
@@ -16,6 +16,17 @@ if your kernel *does* enable it we want to disable
it for you. We do this by relabelling the mesh
kconfig option.
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -679,7 +679,7 @@ struct ieee80211_vif {
+
+ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
+ {
+-#ifdef CONFIG_MAC80211_MESH
++#ifdef CONFIG_COMPAT_MAC80211_MESH
+ return vif->type == NL80211_IFTYPE_MESH_POINT;
+ #endif
+ return false;
--- a/net/mac80211/Makefile 2009-08-04 15:46:36.454027243 -0700
+++ b/net/mac80211/Makefile 2009-08-04 15:50:01.627056156 -0700
@@ -32,7 +32,7 @@
@@ -112,6 +123,80 @@ kconfig option.
del_mesh_stats(sdata);
del_mesh_config(sdata);
#endif
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -83,7 +83,7 @@ struct ieee80211_bss {
+
+ unsigned long last_probe_resp;
+
+-#ifdef CONFIG_MAC80211_MESH
++#ifdef CONFIG_COMPAT_MAC80211_MESH
+ u8 *mesh_id;
+ size_t mesh_id_len;
+ u8 *mesh_cfg;
+@@ -105,7 +105,7 @@ struct ieee80211_bss {
+
+ static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss)
+ {
+-#ifdef CONFIG_MAC80211_MESH
++#ifdef CONFIG_COMPAT_MAC80211_MESH
+ return bss->mesh_cfg;
+ #endif
+ return NULL;
+@@ -113,7 +113,7 @@ static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss)
+
+ static inline u8 *bss_mesh_id(struct ieee80211_bss *bss)
+ {
+-#ifdef CONFIG_MAC80211_MESH
++#ifdef CONFIG_COMPAT_MAC80211_MESH
+ return bss->mesh_id;
+ #endif
+ return NULL;
+@@ -121,7 +121,7 @@ static inline u8 *bss_mesh_id(struct ieee80211_bss *bss)
+
+ static inline u8 bss_mesh_id_len(struct ieee80211_bss *bss)
+ {
+-#ifdef CONFIG_MAC80211_MESH
++#ifdef CONFIG_COMPAT_MAC80211_MESH
+ return bss->mesh_id_len;
+ #endif
+ return 0;
+@@ -384,7 +384,7 @@ struct ieee80211_if_mesh {
+ bool accepting_plinks;
+ };
+
+-#ifdef CONFIG_MAC80211_MESH
++#ifdef CONFIG_COMPAT_MAC80211_MESH
+ #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \
+ do { (msh)->mshstats.name++; } while (0)
+ #else
+@@ -458,7 +458,7 @@ struct ieee80211_sub_if_data {
+ struct ieee80211_if_vlan vlan;
+ struct ieee80211_if_managed mgd;
+ struct ieee80211_if_ibss ibss;
+-#ifdef CONFIG_MAC80211_MESH
++#ifdef CONFIG_COMPAT_MAC80211_MESH
+ struct ieee80211_if_mesh mesh;
+ #endif
+ u32 mntr_flags;
+@@ -503,7 +503,7 @@ struct ieee80211_sub_if_data {
+ struct dentry *default_mgmt_key;
+ } common_debugfs;
+
+-#ifdef CONFIG_MAC80211_MESH
++#ifdef CONFIG_COMPAT_MAC80211_MESH
+ struct dentry *mesh_stats_dir;
+ struct {
+ struct dentry *fwded_frames;
+@@ -546,7 +546,7 @@ static inline void
+ ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata,
+ u8 mesh_id_len, u8 *mesh_id)
+ {
+-#ifdef CONFIG_MAC80211_MESH
++#ifdef CONFIG_COMPAT_MAC80211_MESH
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ ifmsh->mesh_id_len = mesh_id_len;
+ memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len);
--- a/net/mac80211/mesh.h 2009-08-07 12:13:38.500500259 -0700
+++ b/net/mac80211/mesh.h 2009-08-07 12:13:39.504493864 -0700
@@ -267,7 +267,7 @@ void mesh_path_restart(struct ieee80211_
--
1.6.2.1
^ permalink raw reply related
* Re: Libertas: Association request to the driver failed
From: Daniel Mack @ 2009-08-08 12:35 UTC (permalink / raw)
To: John W. Linville; +Cc: libertas-dev, linux-wireless, linux-kernel, Roel Kluin
In-Reply-To: <20090807193610.GK7545@tuxdriver.com>
On Fri, Aug 07, 2009 at 03:36:10PM -0400, John W. Linville wrote:
> On Fri, Aug 07, 2009 at 09:11:56PM +0200, Daniel Mack wrote:
> > Since a recent merge of the wireless tree to Linus' master, my SDIO
> > connected libertas module fails to connect to our WLAN.
> >
> > 'iwlist scanning' works fine, but wpa_supplicant keeps on spitting out
> > the following message:
> >
> > CTRL-EVENT-SCAN-RESULTS
> > Trying to associate with 00:04:0e:4b:c7:b3 (SSID='caiaq' freq=2437 MHz)
> > Association request to the driver failed
> >
> > Haven't done any bisect or deeper inspection of recent changes yet. Can
> > anyone point me in some direction maybe? The change must have been
> > introduced between -rc3 and -rc5. My userspace did not change since
> > then.
>
> Normally a bisect is exactly what you would do.
Hmm, I know. However, in my case, this is not possible as I keep a
number of patches I'm actively working on on top of the history by
rebasing my git tree constantly. And without these patches, the platform
won't boot, so bisect will almost certainly come up with an unbootable
image. But that's just a sidenote :)
> In this case, there
> is only this on libertas patch in the range you mention:
I was wrong with the range I provided. The change came in after -rc5,
and I found 57921c31 ("libertas: Read buffer overflow") to be the
culprit. Reverting it brings my libertas device back to life. I copied
the author.
Thanks,
Daniel
^ permalink raw reply
* Re: [PATCH] cfg80211: fix locking for SIWFREQ
From: Kalle Valo @ 2009-08-08 9:41 UTC (permalink / raw)
To: Johannes Berg; +Cc: John Linville, Reinette Chatre, linux-wireless
In-Reply-To: <1249722238.31670.17.camel@johannes.local>
Johannes Berg <johannes@sipsolutions.net> writes:
> "cfg80211: validate channel settings across interfaces"
> contained a locking bug -- in the managed-mode SIWFREQ
> call it would end up running into a lock recursion.
>
> This fixes it by not checking that particular interface
> for a channel that it needs to stay on, which is as it
> should be as that's the interface we're setting the
> channel for.
Thanks, this fixes the problem I reported.
> Reported-by: Reinette Chatre <reinette.chatre@intel.com>
> Reported-by: Kalle Valo <kalle.valo@iki.fi>
> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Tested-by: Kalle Valo <kalle.valo@iki.fi>
--
Kalle Valo
^ permalink raw reply
* Re: Mesh fixes and improvements
From: Johannes Berg @ 2009-08-08 9:09 UTC (permalink / raw)
To: Javier Cardona; +Cc: linux-wireless, andrey, linville, devel
In-Reply-To: <1249702711-32737-1-git-send-email-javier@cozybit.com>
[-- Attachment #1: Type: text/plain, Size: 1048 bytes --]
On Fri, 2009-08-07 at 20:38 -0700, Javier Cardona wrote:
> [Resent with proper patch numbering...]
>
> This series includes some fixes, testing aids and improvements to the mesh
> stack. It is important to note that the patch
> "Use-3-address-format-for-mesh-broadcast-frames" breaks compatibility with
> previous versions. This is unavoidable and will keep happening as new versions
> of the 802.11s drafts are produced.
That's ok, can you update the Kconfig though to indicate which draft
it's compatible with? It says 1.08 right now.
> Also, I'm not sure if "Simulate-transmission-losses-on-plinks-to-..." should be
> merged upstream, but we find it really useful to test mesh configurations.
> Please comment if you have different opinions on its adequacy or
> implementation.
As I said elsewhere in this thread I don't think that should be in,
especially not, as Kalle points out, using nl80211.
All the other patches look ok on a cursory look, I just wish you'd write
more detailed changelog entries.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* [PATCH] cfg80211: fix locking for SIWFREQ
From: Johannes Berg @ 2009-08-08 9:03 UTC (permalink / raw)
To: John Linville; +Cc: Reinette Chatre, Kalle Valo, linux-wireless
"cfg80211: validate channel settings across interfaces"
contained a locking bug -- in the managed-mode SIWFREQ
call it would end up running into a lock recursion.
This fixes it by not checking that particular interface
for a channel that it needs to stay on, which is as it
should be as that's the interface we're setting the
channel for.
Reported-by: Reinette Chatre <reinette.chatre@intel.com>
Reported-by: Kalle Valo <kalle.valo@iki.fi>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/wireless/chan.c | 3 ++-
net/wireless/core.h | 1 +
net/wireless/nl80211.c | 2 +-
net/wireless/wext-compat.c | 2 +-
net/wireless/wext-sme.c | 2 +-
5 files changed, 6 insertions(+), 4 deletions(-)
--- wireless-testing.orig/net/wireless/chan.c 2009-08-08 10:53:52.000000000 +0200
+++ wireless-testing/net/wireless/chan.c 2009-08-08 10:54:10.000000000 +0200
@@ -42,13 +42,14 @@ rdev_fixed_channel(struct cfg80211_regis
}
int rdev_set_freq(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *for_wdev,
int freq, enum nl80211_channel_type channel_type)
{
struct ieee80211_channel *chan;
struct ieee80211_sta_ht_cap *ht_cap;
int result;
- if (rdev_fixed_channel(rdev, NULL))
+ if (rdev_fixed_channel(rdev, for_wdev))
return -EBUSY;
if (!rdev->ops->set_channel)
--- wireless-testing.orig/net/wireless/core.h 2009-08-08 10:54:29.000000000 +0200
+++ wireless-testing/net/wireless/core.h 2009-08-08 10:54:37.000000000 +0200
@@ -374,6 +374,7 @@ struct ieee80211_channel *
rdev_fixed_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *for_wdev);
int rdev_set_freq(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *for_wdev,
int freq, enum nl80211_channel_type channel_type);
#endif /* __NET_WIRELESS_CORE_H */
--- wireless-testing.orig/net/wireless/nl80211.c 2009-08-08 10:54:51.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.c 2009-08-08 10:54:58.000000000 +0200
@@ -721,7 +721,7 @@ static int nl80211_set_wiphy(struct sk_b
freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
mutex_lock(&rdev->devlist_mtx);
- result = rdev_set_freq(rdev, freq, channel_type);
+ result = rdev_set_freq(rdev, NULL, freq, channel_type);
mutex_unlock(&rdev->devlist_mtx);
if (result)
goto bad_res;
--- wireless-testing.orig/net/wireless/wext-compat.c 2009-08-08 10:54:52.000000000 +0200
+++ wireless-testing/net/wireless/wext-compat.c 2009-08-08 10:55:04.000000000 +0200
@@ -766,7 +766,7 @@ int cfg80211_wext_siwfreq(struct net_dev
if (freq == 0)
return -EINVAL;
mutex_lock(&rdev->devlist_mtx);
- err = rdev_set_freq(rdev, freq, NL80211_CHAN_NO_HT);
+ err = rdev_set_freq(rdev, NULL, freq, NL80211_CHAN_NO_HT);
mutex_unlock(&rdev->devlist_mtx);
return err;
}
--- wireless-testing.orig/net/wireless/wext-sme.c 2009-08-08 10:54:52.000000000 +0200
+++ wireless-testing/net/wireless/wext-sme.c 2009-08-08 10:55:08.000000000 +0200
@@ -106,7 +106,7 @@ int cfg80211_mgd_wext_siwfreq(struct net
/* SSID is not set, we just want to switch channel */
if (chan && !wdev->wext.connect.ssid_len) {
- err = rdev_set_freq(rdev, freq, NL80211_CHAN_NO_HT);
+ err = rdev_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
goto out;
}
^ permalink raw reply
* Re: [PATCH v4] cfg80211: validate channel settings across interfaces
From: Kalle Valo @ 2009-08-08 8:49 UTC (permalink / raw)
To: reinette chatre
Cc: Johannes Berg, John Linville, linux-wireless, Luis R. Rodriguez
In-Reply-To: <1249712383.30019.5561.camel@rc-desk>
reinette chatre <reinette.chatre@intel.com> writes:
> Hi Johannes,
Hi,
> This patch is now in wireless-testing and it is causing a problem for
> me. This was determined using bisect.
>
> I am able to bring the interface up and scan, but when I try to
> associate I get a hang.
>
> For example, when I run:
> $ iwconfig wlan0 channel <ch> essid <essid>
>
> then the command prompt never returns and system becomes progressively
> unresponsive. The logs do not contain any details of the problem.
I see the same problem with my iwl3945. I do 'sudo ifup wlan0' (which
starts wpa_supplicant), command prompt is printed once and then laptop
just hangs.
Reverting this commit fixes the issue:
commit e66cda2a15bede6fc3fa74482337a00ba768983a
Author: Johannes Berg <johannes@sipsolutions.net>
Date: Fri Aug 7 17:22:35 2009 +0200
cfg80211: validate channel settings across interfaces
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH 3/8] mac80211: Simulate transmission losses on plinks to aid in testing mesh metrics.
From: Johannes Berg @ 2009-08-08 8:46 UTC (permalink / raw)
To: Kalle Valo
Cc: Javier Cardona, linux-wireless, Andrey Yurovsky, linville, devel
In-Reply-To: <87d476n2vu.fsf@litku.valot.fi>
[-- Attachment #1: Type: text/plain, Size: 845 bytes --]
On Sat, 2009-08-08 at 11:09 +0300, Kalle Valo wrote:
> Javier Cardona <javier@cozybit.com> writes:
>
> > This enables us to specify a simulated loss probability per mesh peer link.
> > Useful to simulate and test different mesh topologies and test different mesh
> > metrics.
> >
> > The simulated loss rate setting can be configured as a plink action. The
> > intended use is:
> >
> > iw dev mesh station set <MAC> plink_action loss 25
>
> I really would not like to see debug functionality in nl80211 just to
> simplify the maintenance. Debugging belongs to debugfs or somewhere
> else.
I agree, and I also don't think it belongs into mac80211. I think this
is a good case for actually finally writing the userspace frame
forwarding for hwsim, so you can simulate _anything_ with simple
userspace programs.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH v4] cfg80211: validate channel settings across interfaces
From: Johannes Berg @ 2009-08-08 8:43 UTC (permalink / raw)
To: reinette chatre; +Cc: John Linville, linux-wireless, Luis R. Rodriguez
In-Reply-To: <1249712383.30019.5561.camel@rc-desk>
[-- Attachment #1: Type: text/plain, Size: 487 bytes --]
Hi,
> I am able to bring the interface up and scan, but when I try to
> associate I get a hang.
>
> For example, when I run:
> $ iwconfig wlan0 channel <ch> essid <essid>
>
> then the command prompt never returns and system becomes progressively
> unresponsive. The logs do not contain any details of the problem.
Hmm, yes, that's a pretty obvious deadlock, I obviously didn't test
managed-mode 'iwconfig wlan0 channel' setting. I'll send a fix, I'm
sorry.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH] rndis_wlan: wait association to complete
From: Jussi Kivilinna @ 2009-08-08 8:33 UTC (permalink / raw)
To: Dan Williams; +Cc: Johannes Berg, linux-wireless, linville, Jouni Malinen
In-Reply-To: <1249680718.26088.44.camel@localhost.localdomain>
Quoting "Dan Williams" <dcbw@redhat.com>:
> On Thu, 2009-08-06 at 22:34 +0300, Jussi Kivilinna wrote:
>> Quoting "Johannes Berg" <johannes@sipsolutions.net>:
>>
>> > On Thu, 2009-08-06 at 21:17 +0300, Jussi Kivilinna wrote:
>> >> Fix WPA authentication problems by waiting to association to complete.
>> >> Otherwise userspace (wpa_supplicant) receives authentication
>> packets before
>> >> association events from driver.
>> >
>> >> + /* If we return now, userspace would get association events too late
>> >> + * (after receiving first packets from access point). This causes
>> >> + * WPA authentication to fail.
>> >
>> > This is a bit weird, shouldn't you just send the event later then?
>> >
>>
>> rndis_wlan bases on rndis_host/usbnet. Problem is that rndis_host uses
>> polling for rndis_command() results to avoid more complex interrupt
>> based solution. Because rndis_host and therefore rndis_wlan doesn't
>> handle interrupts on command channel, rndis_wlan knows about completed
>> association too late. 'Too late' means here that device starts
>> receiving packets from AP, which end up ignored because userspace
>> thinks device isn't assosiated yet (I think).
>>
>> So this patch adds waiting in set_essid() and active polling for
>> association completion in worker.
>>
>> Real fix would probably be to hold on data channel until association
>> is complete, but that would mean touching usbnet/rndis_host little bit
>> too much than I'd like to.
>
> If this patch ever blocks SIOSIWESSID, then a huge NAK. Setting the
> ESSID is an asynchronous operation, it should *not* block for operation
> to complete. Completion is signaled only when an IWESSID event is sent
> to userspace. What you should be doing is dropping packets from the AP
> on the floor until the firmware things the association is complete.
>
Ok, I noticed that I need to do this 'right way' anyway for
cfg80211-connect conversion. So I'm taking this one back and work out
better fix for/with connect patches.
-Jussi
^ permalink raw reply
* Re: [PATCH 16/16] iwlwifi: disable powersave mode
From: Kalle Valo @ 2009-08-08 8:25 UTC (permalink / raw)
To: Reinette Chatre; +Cc: linville, linux-wireless, ipw3945-devel, Wey-Yi Guy
In-Reply-To: <1249684912-22936-17-git-send-email-reinette.chatre@intel.com>
Reinette Chatre <reinette.chatre@intel.com> writes:
> From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
>
> The enabling of powersaving had a big impact on reliability and
> performance. Throughput on n band suffered especially. With power save
> support enabled we see significant ping response times, dropped frames, and
> reduced throughput. These are captured in the following bug reports:
>
> http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2051
> http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2053
>
> Disable power save by default, add "iwl_support_ps" module parameter
> that can be used to enable it again.
You are again creating driver specific parameters. But we should be
moving away from this and instead use just generic interfaces. Please,
think three times (or even more) whenever creating new driver specific
interfaces, be it module parameters, sysfs files etc.. It's a
maintenance nightmare and also very confusing for the users. We need to
focus on nl80211 and make it work properly with all drivers.
For the problem at hand, I see two options:
1. Users seeing the problem disable power save either via wext or with
CONFIG_CFG80211_DEFAULT_PS and everyone else still can use power
save. The issue will be investigated and fixed. If the AP is buggy,
there isn't much we can do.
2. If you think the problem is widespread, remove
IEEE80211_HW_SUPPORTS_PS from the driver, fix the issues and renable
power save support.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH 3/8] mac80211: Simulate transmission losses on plinks to aid in testing mesh metrics.
From: Kalle Valo @ 2009-08-08 8:09 UTC (permalink / raw)
To: Javier Cardona; +Cc: linux-wireless, Andrey Yurovsky, johannes, linville, devel
In-Reply-To: <1249702711-32737-4-git-send-email-javier@cozybit.com>
Javier Cardona <javier@cozybit.com> writes:
> This enables us to specify a simulated loss probability per mesh peer link.
> Useful to simulate and test different mesh topologies and test different mesh
> metrics.
>
> The simulated loss rate setting can be configured as a plink action. The
> intended use is:
>
> iw dev mesh station set <MAC> plink_action loss 25
I really would not like to see debug functionality in nl80211 just to
simplify the maintenance. Debugging belongs to debugfs or somewhere
else.
Disclaimer: I know nothing about mesh and I may have misunderstood
something.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH] MAINTAINERS: add information for wl1271 wireless driver
From: Kalle Valo @ 2009-08-08 7:40 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1249681805-21015-1-git-send-email-luciano.coelho@nokia.com>
Luciano Coelho <luciano.coelho@nokia.com> writes:
> Add maintainer information section for the wl1271 wireless driver and fix the
> information for wl1271.
>
> Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Thanks.
Acked-by: Kalle Valo <kalle.valo@nokia.com>
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH v4] cfg80211: validate channel settings across interfaces
From: reinette chatre @ 2009-08-08 6:19 UTC (permalink / raw)
To: Johannes Berg; +Cc: John Linville, linux-wireless, Luis R. Rodriguez
In-Reply-To: <1249658555.7194.8.camel@johannes.local>
Hi Johannes,
This patch is now in wireless-testing and it is causing a problem for
me. This was determined using bisect.
I am able to bring the interface up and scan, but when I try to
associate I get a hang.
For example, when I run:
$ iwconfig wlan0 channel <ch> essid <essid>
then the command prompt never returns and system becomes progressively
unresponsive. The logs do not contain any details of the problem.
Reinette
On Fri, 2009-08-07 at 08:22 -0700, Johannes Berg wrote:
> Currently, there's a problem that affects regulatory
> enforcement and connection stability, in that it is
> possible to switch the channel while connected to a
> network or joined to an IBSS.
>
> The problem comes from the fact that we only validate
> the channel against the current interface's type, not
> against any other interface. Thus, you have any type
> of interface up, additionally bring up a monitor mode
> interface and switch the channel on the monitor. This
> will obviously also switch the channel on the other
> interface.
>
> The problem now is that if you do that while sending
> beacons for IBSS mode, you can switch to a disabled
> channel or a channel that doesn't allow beaconing.
> Combined with a managed mode interface connected to
> an AP instead of an IBSS interface, you can easily
> break the connection that way.
>
> To fix this, this patch validates any channel change
> with all available interfaces, and disallows such
> changes on secondary interfaces if another interface
> is connected to an AP or joined to an IBSS.
>
> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
> ---
> v2: * rebase
> v3: * fix error code (-EBUSY instead of -EINVAL)
> * fix locking (need devlist_mtx instead of rdev mtx)
> v4: * use SINGLE_DEPTH_NESTING instead of 1
>
> net/wireless/Makefile | 3 +
> net/wireless/chan.c | 88 +++++++++++++++++++++++++++++++++++++++++++++
> net/wireless/core.h | 6 +++
> net/wireless/ibss.c | 63 ++++++++++++++++++++------------
> net/wireless/nl80211.c | 54 ++++++---------------------
> net/wireless/sme.c | 9 ++++
> net/wireless/wext-compat.c | 55 +++++++++-------------------
> net/wireless/wext-compat.h | 3 -
> net/wireless/wext-sme.c | 67 ++++++++++++++++++----------------
> 9 files changed, 215 insertions(+), 133 deletions(-)
>
> --- wireless-testing.orig/net/wireless/Makefile 2009-08-07 14:50:09.000000000 +0200
> +++ wireless-testing/net/wireless/Makefile 2009-08-07 14:50:11.000000000 +0200
> @@ -5,7 +5,8 @@ obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib8
> obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
> obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
>
> -cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o sme.o
> +cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
> +cfg80211-y += mlme.o ibss.o sme.o chan.o
> cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
> cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o wext-sme.o
>
> --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> +++ wireless-testing/net/wireless/chan.c 2009-08-07 17:20:41.000000000 +0200
> @@ -0,0 +1,88 @@
> +/*
> + * This file contains helper code to handle channel
> + * settings and keeping track of what is possible at
> + * any point in time.
> + *
> + * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
> + */
> +
> +#include <net/cfg80211.h>
> +#include "core.h"
> +
> +struct ieee80211_channel *
> +rdev_fixed_channel(struct cfg80211_registered_device *rdev,
> + struct wireless_dev *for_wdev)
> +{
> + struct wireless_dev *wdev;
> + struct ieee80211_channel *result = NULL;
> +
> + WARN_ON(!mutex_is_locked(&rdev->devlist_mtx));
> +
> + list_for_each_entry(wdev, &rdev->netdev_list, list) {
> + if (wdev == for_wdev)
> + continue;
> +
> + /*
> + * Lock manually to tell lockdep about allowed
> + * nesting here if for_wdev->mtx is held already.
> + * This is ok as it's all under the rdev devlist
> + * mutex and as such can only be done once at any
> + * given time.
> + */
> + mutex_lock_nested(&wdev->mtx, SINGLE_DEPTH_NESTING);
> + if (wdev->current_bss)
> + result = wdev->current_bss->pub.channel;
> + wdev_unlock(wdev);
> +
> + if (result)
> + break;
> + }
> +
> + return result;
> +}
> +
> +int rdev_set_freq(struct cfg80211_registered_device *rdev,
> + int freq, enum nl80211_channel_type channel_type)
> +{
> + struct ieee80211_channel *chan;
> + struct ieee80211_sta_ht_cap *ht_cap;
> + int result;
> +
> + if (rdev_fixed_channel(rdev, NULL))
> + return -EBUSY;
> +
> + if (!rdev->ops->set_channel)
> + return -EOPNOTSUPP;
> +
> + chan = ieee80211_get_channel(&rdev->wiphy, freq);
> +
> + /* Primary channel not allowed */
> + if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
> + return -EINVAL;
> +
> + if (channel_type == NL80211_CHAN_HT40MINUS &&
> + chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
> + return -EINVAL;
> + else if (channel_type == NL80211_CHAN_HT40PLUS &&
> + chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
> + return -EINVAL;
> +
> + ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
> +
> + if (channel_type != NL80211_CHAN_NO_HT) {
> + if (!ht_cap->ht_supported)
> + return -EINVAL;
> +
> + if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
> + ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
> + return -EINVAL;
> + }
> +
> + result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type);
> + if (result)
> + return result;
> +
> + rdev->channel = chan;
> +
> + return 0;
> +}
> --- wireless-testing.orig/net/wireless/core.h 2009-08-07 14:50:09.000000000 +0200
> +++ wireless-testing/net/wireless/core.h 2009-08-07 17:20:31.000000000 +0200
> @@ -366,4 +366,10 @@ void cfg80211_sme_disassoc(struct net_de
> void __cfg80211_scan_done(struct work_struct *wk);
> void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
>
> +struct ieee80211_channel *
> +rdev_fixed_channel(struct cfg80211_registered_device *rdev,
> + struct wireless_dev *for_wdev);
> +int rdev_set_freq(struct cfg80211_registered_device *rdev,
> + int freq, enum nl80211_channel_type channel_type);
> +
> #endif /* __NET_WIRELESS_CORE_H */
> --- wireless-testing.orig/net/wireless/nl80211.c 2009-08-07 14:50:09.000000000 +0200
> +++ wireless-testing/net/wireless/nl80211.c 2009-08-07 17:20:30.000000000 +0200
> @@ -701,15 +701,8 @@ static int nl80211_set_wiphy(struct sk_b
>
> if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
> enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
> - struct ieee80211_channel *chan;
> - struct ieee80211_sta_ht_cap *ht_cap;
> u32 freq;
>
> - if (!rdev->ops->set_channel) {
> - result = -EOPNOTSUPP;
> - goto bad_res;
> - }
> -
> result = -EINVAL;
>
> if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
> @@ -723,42 +716,12 @@ static int nl80211_set_wiphy(struct sk_b
> }
>
> freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
> - chan = ieee80211_get_channel(&rdev->wiphy, freq);
> -
> - /* Primary channel not allowed */
> - if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
> - goto bad_res;
> -
> - if (channel_type == NL80211_CHAN_HT40MINUS &&
> - (chan->flags & IEEE80211_CHAN_NO_HT40MINUS))
> - goto bad_res;
> - else if (channel_type == NL80211_CHAN_HT40PLUS &&
> - (chan->flags & IEEE80211_CHAN_NO_HT40PLUS))
> - goto bad_res;
> -
> - /*
> - * At this point we know if that if HT40 was requested
> - * we are allowed to use it and the extension channel
> - * exists.
> - */
>
> - ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
> -
> - /* no HT capabilities or intolerant */
> - if (channel_type != NL80211_CHAN_NO_HT) {
> - if (!ht_cap->ht_supported)
> - goto bad_res;
> - if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
> - (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT))
> - goto bad_res;
> - }
> -
> - result = rdev->ops->set_channel(&rdev->wiphy, chan,
> - channel_type);
> + mutex_lock(&rdev->devlist_mtx);
> + result = rdev_set_freq(rdev, freq, channel_type);
> + mutex_unlock(&rdev->devlist_mtx);
> if (result)
> goto bad_res;
> -
> - rdev->channel = chan;
> }
>
> changed = 0;
> @@ -3453,7 +3416,7 @@ static int nl80211_associate(struct sk_b
> struct cfg80211_registered_device *rdev;
> struct net_device *dev;
> struct cfg80211_crypto_settings crypto;
> - struct ieee80211_channel *chan;
> + struct ieee80211_channel *chan, *fixedchan;
> const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
> int err, ssid_len, ie_len = 0;
> bool use_mfp = false;
> @@ -3496,6 +3459,15 @@ static int nl80211_associate(struct sk_b
> goto out;
> }
>
> + mutex_lock(&rdev->devlist_mtx);
> + fixedchan = rdev_fixed_channel(rdev, NULL);
> + if (fixedchan && chan != fixedchan) {
> + err = -EBUSY;
> + mutex_unlock(&rdev->devlist_mtx);
> + goto out;
> + }
> + mutex_unlock(&rdev->devlist_mtx);
> +
> ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
> ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
>
> --- wireless-testing.orig/net/wireless/wext-compat.c 2009-08-07 14:50:09.000000000 +0200
> +++ wireless-testing/net/wireless/wext-compat.c 2009-08-07 15:38:35.000000000 +0200
> @@ -267,39 +267,26 @@ EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange
> * @wiphy: the wiphy
> * @freq: the wext freq encoding
> *
> - * Returns a channel, %NULL for auto, or an ERR_PTR for errors!
> + * Returns a frequency, or a negative error code, or 0 for auto.
> */
> -struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
> - struct iw_freq *freq)
> +int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq)
> {
> - struct ieee80211_channel *chan;
> - int f;
> -
> /*
> - * Parse frequency - return NULL for auto and
> + * Parse frequency - return 0 for auto and
> * -EINVAL for impossible things.
> */
> if (freq->e == 0) {
> if (freq->m < 0)
> - return NULL;
> - f = ieee80211_channel_to_frequency(freq->m);
> + return 0;
> + return ieee80211_channel_to_frequency(freq->m);
> } else {
> int i, div = 1000000;
> for (i = 0; i < freq->e; i++)
> div /= 10;
> if (div <= 0)
> - return ERR_PTR(-EINVAL);
> - f = freq->m / div;
> + return -EINVAL;
> + return freq->m / div;
> }
> -
> - /*
> - * Look up channel struct and return -EINVAL when
> - * it cannot be found.
> - */
> - chan = ieee80211_get_channel(wiphy, f);
> - if (!chan)
> - return ERR_PTR(-EINVAL);
> - return chan;
> }
>
> int cfg80211_wext_siwrts(struct net_device *dev,
> @@ -761,33 +748,29 @@ EXPORT_SYMBOL_GPL(cfg80211_wext_giwencod
>
> int cfg80211_wext_siwfreq(struct net_device *dev,
> struct iw_request_info *info,
> - struct iw_freq *freq, char *extra)
> + struct iw_freq *wextfreq, char *extra)
> {
> struct wireless_dev *wdev = dev->ieee80211_ptr;
> struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
> - struct ieee80211_channel *chan;
> - int err;
> + int freq, err;
>
> switch (wdev->iftype) {
> case NL80211_IFTYPE_STATION:
> - return cfg80211_mgd_wext_siwfreq(dev, info, freq, extra);
> + return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
> case NL80211_IFTYPE_ADHOC:
> - return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
> + return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
> default:
> - chan = cfg80211_wext_freq(wdev->wiphy, freq);
> - if (!chan)
> + freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
> + if (freq < 0)
> + return freq;
> + if (freq == 0)
> return -EINVAL;
> - if (IS_ERR(chan))
> - return PTR_ERR(chan);
> - err = rdev->ops->set_channel(wdev->wiphy, chan,
> - NL80211_CHAN_NO_HT);
> - if (err)
> - return err;
> - rdev->channel = chan;
> - return 0;
> + mutex_lock(&rdev->devlist_mtx);
> + err = rdev_set_freq(rdev, freq, NL80211_CHAN_NO_HT);
> + mutex_unlock(&rdev->devlist_mtx);
> + return err;
> }
> }
> -EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq);
>
> int cfg80211_wext_giwfreq(struct net_device *dev,
> struct iw_request_info *info,
> --- wireless-testing.orig/net/wireless/wext-compat.h 2009-08-07 14:50:09.000000000 +0200
> +++ wireless-testing/net/wireless/wext-compat.h 2009-08-07 14:50:11.000000000 +0200
> @@ -42,8 +42,7 @@ int cfg80211_mgd_wext_giwessid(struct ne
> struct iw_request_info *info,
> struct iw_point *data, char *ssid);
>
> -struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
> - struct iw_freq *freq);
> +int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq);
>
>
> extern const struct iw_handler_def cfg80211_wext_handler;
> --- wireless-testing.orig/net/wireless/ibss.c 2009-08-07 14:50:09.000000000 +0200
> +++ wireless-testing/net/wireless/ibss.c 2009-08-07 15:45:29.000000000 +0200
> @@ -78,10 +78,15 @@ int __cfg80211_join_ibss(struct cfg80211
> struct cfg80211_cached_keys *connkeys)
> {
> struct wireless_dev *wdev = dev->ieee80211_ptr;
> + struct ieee80211_channel *chan;
> int err;
>
> ASSERT_WDEV_LOCK(wdev);
>
> + chan = rdev_fixed_channel(rdev, wdev);
> + if (chan && chan != params->channel)
> + return -EBUSY;
> +
> if (wdev->ssid_len)
> return -EALREADY;
>
> @@ -112,9 +117,11 @@ int cfg80211_join_ibss(struct cfg80211_r
> struct wireless_dev *wdev = dev->ieee80211_ptr;
> int err;
>
> + mutex_lock(&rdev->devlist_mtx);
> wdev_lock(wdev);
> err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
> wdev_unlock(wdev);
> + mutex_unlock(&rdev->devlist_mtx);
>
> return err;
> }
> @@ -264,27 +271,32 @@ int cfg80211_ibss_wext_join(struct cfg80
>
> int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
> struct iw_request_info *info,
> - struct iw_freq *freq, char *extra)
> + struct iw_freq *wextfreq, char *extra)
> {
> struct wireless_dev *wdev = dev->ieee80211_ptr;
> - struct ieee80211_channel *chan;
> - int err;
> + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
> + struct ieee80211_channel *chan = NULL;
> + int err, freq;
>
> /* call only for ibss! */
> if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
> return -EINVAL;
>
> - if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss)
> + if (!rdev->ops->join_ibss)
> return -EOPNOTSUPP;
>
> - chan = cfg80211_wext_freq(wdev->wiphy, freq);
> - if (chan && IS_ERR(chan))
> - return PTR_ERR(chan);
> -
> - if (chan &&
> - (chan->flags & IEEE80211_CHAN_NO_IBSS ||
> - chan->flags & IEEE80211_CHAN_DISABLED))
> - return -EINVAL;
> + freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
> + if (freq < 0)
> + return freq;
> +
> + if (freq) {
> + chan = ieee80211_get_channel(wdev->wiphy, freq);
> + if (!chan)
> + return -EINVAL;
> + if (chan->flags & IEEE80211_CHAN_NO_IBSS ||
> + chan->flags & IEEE80211_CHAN_DISABLED)
> + return -EINVAL;
> + }
>
> if (wdev->wext.ibss.channel == chan)
> return 0;
> @@ -292,8 +304,7 @@ int cfg80211_ibss_wext_siwfreq(struct ne
> wdev_lock(wdev);
> err = 0;
> if (wdev->ssid_len)
> - err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
> - dev, true);
> + err = __cfg80211_leave_ibss(rdev, dev, true);
> wdev_unlock(wdev);
>
> if (err)
> @@ -307,9 +318,11 @@ int cfg80211_ibss_wext_siwfreq(struct ne
> wdev->wext.ibss.channel_fixed = false;
> }
>
> + mutex_lock(&rdev->devlist_mtx);
> wdev_lock(wdev);
> - err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
> + err = cfg80211_ibss_wext_join(rdev, wdev);
> wdev_unlock(wdev);
> + mutex_unlock(&rdev->devlist_mtx);
>
> return err;
> }
> @@ -347,6 +360,7 @@ int cfg80211_ibss_wext_siwessid(struct n
> struct iw_point *data, char *ssid)
> {
> struct wireless_dev *wdev = dev->ieee80211_ptr;
> + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
> size_t len = data->length;
> int err;
>
> @@ -354,14 +368,13 @@ int cfg80211_ibss_wext_siwessid(struct n
> if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
> return -EINVAL;
>
> - if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss)
> + if (!rdev->ops->join_ibss)
> return -EOPNOTSUPP;
>
> wdev_lock(wdev);
> err = 0;
> if (wdev->ssid_len)
> - err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
> - dev, true);
> + err = __cfg80211_leave_ibss(rdev, dev, true);
> wdev_unlock(wdev);
>
> if (err)
> @@ -375,9 +388,11 @@ int cfg80211_ibss_wext_siwessid(struct n
> memcpy(wdev->wext.ibss.ssid, ssid, len);
> wdev->wext.ibss.ssid_len = len;
>
> + mutex_lock(&rdev->devlist_mtx);
> wdev_lock(wdev);
> - err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
> + err = cfg80211_ibss_wext_join(rdev, wdev);
> wdev_unlock(wdev);
> + mutex_unlock(&rdev->devlist_mtx);
>
> return err;
> }
> @@ -414,6 +429,7 @@ int cfg80211_ibss_wext_siwap(struct net_
> struct sockaddr *ap_addr, char *extra)
> {
> struct wireless_dev *wdev = dev->ieee80211_ptr;
> + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
> u8 *bssid = ap_addr->sa_data;
> int err;
>
> @@ -421,7 +437,7 @@ int cfg80211_ibss_wext_siwap(struct net_
> if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
> return -EINVAL;
>
> - if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss)
> + if (!rdev->ops->join_ibss)
> return -EOPNOTSUPP;
>
> if (ap_addr->sa_family != ARPHRD_ETHER)
> @@ -443,8 +459,7 @@ int cfg80211_ibss_wext_siwap(struct net_
> wdev_lock(wdev);
> err = 0;
> if (wdev->ssid_len)
> - err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
> - dev, true);
> + err = __cfg80211_leave_ibss(rdev, dev, true);
> wdev_unlock(wdev);
>
> if (err)
> @@ -456,9 +471,11 @@ int cfg80211_ibss_wext_siwap(struct net_
> } else
> wdev->wext.ibss.bssid = NULL;
>
> + mutex_lock(&rdev->devlist_mtx);
> wdev_lock(wdev);
> - err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
> + err = cfg80211_ibss_wext_join(rdev, wdev);
> wdev_unlock(wdev);
> + mutex_unlock(&rdev->devlist_mtx);
>
> return err;
> }
> --- wireless-testing.orig/net/wireless/wext-sme.c 2009-08-07 14:50:09.000000000 +0200
> +++ wireless-testing/net/wireless/wext-sme.c 2009-08-07 17:20:31.000000000 +0200
> @@ -52,25 +52,31 @@ int cfg80211_mgd_wext_connect(struct cfg
>
> int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
> struct iw_request_info *info,
> - struct iw_freq *freq, char *extra)
> + struct iw_freq *wextfreq, char *extra)
> {
> struct wireless_dev *wdev = dev->ieee80211_ptr;
> struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
> - struct ieee80211_channel *chan;
> - int err;
> + struct ieee80211_channel *chan = NULL;
> + int err, freq;
>
> /* call only for station! */
> if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
> return -EINVAL;
>
> - chan = cfg80211_wext_freq(wdev->wiphy, freq);
> - if (chan && IS_ERR(chan))
> - return PTR_ERR(chan);
> -
> - if (chan && (chan->flags & IEEE80211_CHAN_DISABLED))
> - return -EINVAL;
> + freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
> + if (freq < 0)
> + return freq;
> +
> + if (freq) {
> + chan = ieee80211_get_channel(wdev->wiphy, freq);
> + if (!chan)
> + return -EINVAL;
> + if (chan->flags & IEEE80211_CHAN_DISABLED)
> + return -EINVAL;
> + }
>
> cfg80211_lock_rdev(rdev);
> + mutex_lock(&rdev->devlist_mtx);
> wdev_lock(wdev);
>
> if (wdev->sme_state != CFG80211_SME_IDLE) {
> @@ -84,9 +90,8 @@ int cfg80211_mgd_wext_siwfreq(struct net
> /* if SSID set, we'll try right again, avoid event */
> if (wdev->wext.connect.ssid_len)
> event = false;
> - err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
> - dev, WLAN_REASON_DEAUTH_LEAVING,
> - event);
> + err = __cfg80211_disconnect(rdev, dev,
> + WLAN_REASON_DEAUTH_LEAVING, event);
> if (err)
> goto out;
> }
> @@ -95,17 +100,15 @@ int cfg80211_mgd_wext_siwfreq(struct net
> wdev->wext.connect.channel = chan;
>
> /* SSID is not set, we just want to switch channel */
> - if (wdev->wext.connect.ssid_len && chan) {
> - err = -EOPNOTSUPP;
> - if (rdev->ops->set_channel)
> - err = rdev->ops->set_channel(wdev->wiphy, chan,
> - NL80211_CHAN_NO_HT);
> + if (chan && !wdev->wext.connect.ssid_len) {
> + err = rdev_set_freq(rdev, freq, NL80211_CHAN_NO_HT);
> goto out;
> }
>
> - err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
> + err = cfg80211_mgd_wext_connect(rdev, wdev);
> out:
> wdev_unlock(wdev);
> + mutex_unlock(&rdev->devlist_mtx);
> cfg80211_unlock_rdev(rdev);
> return err;
> }
> @@ -143,6 +146,7 @@ int cfg80211_mgd_wext_siwessid(struct ne
> struct iw_point *data, char *ssid)
> {
> struct wireless_dev *wdev = dev->ieee80211_ptr;
> + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
> size_t len = data->length;
> int err;
>
> @@ -157,7 +161,8 @@ int cfg80211_mgd_wext_siwessid(struct ne
> if (len > 0 && ssid[len - 1] == '\0')
> len--;
>
> - cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy));
> + cfg80211_lock_rdev(rdev);
> + mutex_lock(&rdev->devlist_mtx);
> wdev_lock(wdev);
>
> err = 0;
> @@ -173,9 +178,8 @@ int cfg80211_mgd_wext_siwessid(struct ne
> /* if SSID set now, we'll try to connect, avoid event */
> if (len)
> event = false;
> - err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
> - dev, WLAN_REASON_DEAUTH_LEAVING,
> - event);
> + err = __cfg80211_disconnect(rdev, dev,
> + WLAN_REASON_DEAUTH_LEAVING, event);
> if (err)
> goto out;
> }
> @@ -186,10 +190,11 @@ int cfg80211_mgd_wext_siwessid(struct ne
>
> wdev->wext.connect.crypto.control_port = false;
>
> - err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
> + err = cfg80211_mgd_wext_connect(rdev, wdev);
> out:
> wdev_unlock(wdev);
> - cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy));
> + mutex_unlock(&rdev->devlist_mtx);
> + cfg80211_unlock_rdev(rdev);
> return err;
> }
>
> @@ -230,6 +235,7 @@ int cfg80211_mgd_wext_siwap(struct net_d
> struct sockaddr *ap_addr, char *extra)
> {
> struct wireless_dev *wdev = dev->ieee80211_ptr;
> + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
> u8 *bssid = ap_addr->sa_data;
> int err;
>
> @@ -244,7 +250,8 @@ int cfg80211_mgd_wext_siwap(struct net_d
> if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
> bssid = NULL;
>
> - cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy));
> + cfg80211_lock_rdev(rdev);
> + mutex_lock(&rdev->devlist_mtx);
> wdev_lock(wdev);
>
> if (wdev->sme_state != CFG80211_SME_IDLE) {
> @@ -258,9 +265,8 @@ int cfg80211_mgd_wext_siwap(struct net_d
> compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0)
> goto out;
>
> - err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
> - dev, WLAN_REASON_DEAUTH_LEAVING,
> - false);
> + err = __cfg80211_disconnect(rdev, dev,
> + WLAN_REASON_DEAUTH_LEAVING, false);
> if (err)
> goto out;
> }
> @@ -271,10 +277,11 @@ int cfg80211_mgd_wext_siwap(struct net_d
> } else
> wdev->wext.connect.bssid = NULL;
>
> - err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
> + err = cfg80211_mgd_wext_connect(rdev, wdev);
> out:
> wdev_unlock(wdev);
> - cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy));
> + mutex_unlock(&rdev->devlist_mtx);
> + cfg80211_unlock_rdev(rdev);
> return err;
> }
>
> --- wireless-testing.orig/net/wireless/sme.c 2009-08-07 14:50:09.000000000 +0200
> +++ wireless-testing/net/wireless/sme.c 2009-08-07 17:20:31.000000000 +0200
> @@ -256,9 +256,11 @@ void cfg80211_sme_scan_done(struct net_d
> {
> struct wireless_dev *wdev = dev->ieee80211_ptr;
>
> + mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
> wdev_lock(wdev);
> __cfg80211_sme_scan_done(dev);
> wdev_unlock(wdev);
> + mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
> }
>
> void cfg80211_sme_rx_auth(struct net_device *dev,
> @@ -644,6 +646,7 @@ int __cfg80211_connect(struct cfg80211_r
> struct cfg80211_cached_keys *connkeys)
> {
> struct wireless_dev *wdev = dev->ieee80211_ptr;
> + struct ieee80211_channel *chan;
> int err;
>
> ASSERT_WDEV_LOCK(wdev);
> @@ -651,6 +654,10 @@ int __cfg80211_connect(struct cfg80211_r
> if (wdev->sme_state != CFG80211_SME_IDLE)
> return -EALREADY;
>
> + chan = rdev_fixed_channel(rdev, wdev);
> + if (chan && chan != connect->channel)
> + return -EBUSY;
> +
> if (WARN_ON(wdev->connect_keys)) {
> kfree(wdev->connect_keys);
> wdev->connect_keys = NULL;
> @@ -771,9 +778,11 @@ int cfg80211_connect(struct cfg80211_reg
> {
> int err;
>
> + mutex_lock(&rdev->devlist_mtx);
> wdev_lock(dev->ieee80211_ptr);
> err = __cfg80211_connect(rdev, dev, connect, connkeys);
> wdev_unlock(dev->ieee80211_ptr);
> + mutex_unlock(&rdev->devlist_mtx);
>
> return err;
> }
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 8/8] mac80211: Moved mpath and mpp growth to mesh workqueue.
From: Javier Cardona @ 2009-08-08 3:38 UTC (permalink / raw)
To: linux-wireless; +Cc: Javier Cardona, andrey, johannes, linville, devel
In-Reply-To: <1249702711-32737-8-git-send-email-javier@cozybit.com>
This prevents calling rcu_synchronize from within the tx path.
Also, re-enable mesh in Kconfig
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
net/mac80211/Kconfig | 1 -
net/mac80211/ieee80211_i.h | 2 +-
net/mac80211/mesh.c | 75 +++-------------------
net/mac80211/mesh.h | 20 ++++++-
net/mac80211/mesh_pathtbl.c | 146 ++++++++++++++++++++++++++++++++-----------
5 files changed, 139 insertions(+), 105 deletions(-)
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 7dd77b6..9b4fcbc 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -66,7 +66,6 @@ endmenu
config MAC80211_MESH
bool "Enable mac80211 mesh networking (pre-802.11s) support"
depends on MAC80211 && EXPERIMENTAL
- depends on BROKEN
---help---
This options enables support of Draft 802.11s mesh networking.
The implementation is based on Draft 1.08 of the Mesh Networking
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d6bd7dd..a6abc7d 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -355,7 +355,7 @@ struct ieee80211_if_mesh {
unsigned long timers_running;
- bool housekeeping;
+ unsigned long wrkq_flags;
u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
size_t mesh_id_len;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 3b49d39..619364c 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -47,7 +47,7 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- ifmsh->housekeeping = true;
+ ifmsh->wrkq_flags |= MESH_WORK_HOUSEKEEPING;
if (local->quiescing) {
set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
@@ -320,30 +320,6 @@ struct mesh_table *mesh_table_alloc(int size_order)
return newtbl;
}
-static void __mesh_table_free(struct mesh_table *tbl)
-{
- kfree(tbl->hash_buckets);
- kfree(tbl->hashwlock);
- kfree(tbl);
-}
-
-void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
-{
- struct hlist_head *mesh_hash;
- struct hlist_node *p, *q;
- int i;
-
- mesh_hash = tbl->hash_buckets;
- for (i = 0; i <= tbl->hash_mask; i++) {
- spin_lock(&tbl->hashwlock[i]);
- hlist_for_each_safe(p, q, &mesh_hash[i]) {
- tbl->free_node(p, free_leafs);
- atomic_dec(&tbl->entries);
- }
- spin_unlock(&tbl->hashwlock[i]);
- }
- __mesh_table_free(tbl);
-}
static void ieee80211_mesh_path_timer(unsigned long data)
{
@@ -360,44 +336,6 @@ static void ieee80211_mesh_path_timer(unsigned long data)
ieee80211_queue_work(&local->hw, &ifmsh->work);
}
-struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
-{
- struct mesh_table *newtbl;
- struct hlist_head *oldhash;
- struct hlist_node *p, *q;
- int i;
-
- if (atomic_read(&tbl->entries)
- < tbl->mean_chain_len * (tbl->hash_mask + 1))
- goto endgrow;
-
- newtbl = mesh_table_alloc(tbl->size_order + 1);
- if (!newtbl)
- goto endgrow;
-
- newtbl->free_node = tbl->free_node;
- newtbl->mean_chain_len = tbl->mean_chain_len;
- newtbl->copy_node = tbl->copy_node;
- atomic_set(&newtbl->entries, atomic_read(&tbl->entries));
-
- oldhash = tbl->hash_buckets;
- for (i = 0; i <= tbl->hash_mask; i++)
- hlist_for_each(p, &oldhash[i])
- if (tbl->copy_node(p, newtbl) < 0)
- goto errcopy;
-
- return newtbl;
-
-errcopy:
- for (i = 0; i <= newtbl->hash_mask; i++) {
- hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
- tbl->free_node(p, 0);
- }
- __mesh_table_free(newtbl);
-endgrow:
- return NULL;
-}
-
/**
* ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
* @hdr: 802.11 frame header
@@ -487,7 +425,6 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
if (free_plinks != sdata->u.mesh.accepting_plinks)
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
- ifmsh->housekeeping = false;
mod_timer(&ifmsh->housekeeping_timer,
round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
}
@@ -524,7 +461,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = sdata->local;
- ifmsh->housekeeping = true;
+ ifmsh->wrkq_flags |= MESH_WORK_HOUSEKEEPING;
queue_work(local->hw, &ifmsh->work);
sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
@@ -664,7 +601,13 @@ static void ieee80211_mesh_work(struct work_struct *work)
ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval)))
mesh_path_start_discovery(sdata);
- if (ifmsh->housekeeping)
+ if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
+ mesh_mpath_table_grow();
+
+ if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
+ mesh_mpp_table_grow();
+
+ if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags))
ieee80211_mesh_housekeeping(sdata, ifmsh);
}
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index b6ea100..fd4031f 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -44,6 +44,23 @@ enum mesh_path_flags {
};
/**
+ * enum mesh_deferred_task_flags - mac80211 mesh deferred tasks
+ *
+ *
+ *
+ * @MESH_WORK_HOUSEKEEPING: run the periodic mesh housekeeping tasks
+ * @MESH_WORK_GROW_MPATH_TABLE: the mesh path table is full and needs
+ * to grow.
+ * @MESH_WORK_GROW_MPP_TABLE: the mesh portals table is full and needs to
+ * grow
+ */
+enum mesh_deferred_task_flags {
+ MESH_WORK_HOUSEKEEPING,
+ MESH_WORK_GROW_MPATH_TABLE,
+ MESH_WORK_GROW_MPP_TABLE,
+};
+
+/**
* struct mesh_path - mac80211 mesh path structure
*
* @dst: mesh path destination mac address
@@ -251,7 +268,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
/* Mesh tables */
struct mesh_table *mesh_table_alloc(int size_order);
void mesh_table_free(struct mesh_table *tbl, bool free_leafs);
-struct mesh_table *mesh_table_grow(struct mesh_table *tbl);
+void mesh_mpath_table_grow(void);
+void mesh_mpp_table_grow(void);
u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata,
struct mesh_table *tbl);
/* Mesh paths */
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 431865a..97e14bc 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -39,6 +39,69 @@ static struct mesh_table *mesh_paths;
static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */
int mesh_paths_generation;
+static void __mesh_table_free(struct mesh_table *tbl)
+{
+ kfree(tbl->hash_buckets);
+ kfree(tbl->hashwlock);
+ kfree(tbl);
+}
+
+void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
+{
+ struct hlist_head *mesh_hash;
+ struct hlist_node *p, *q;
+ int i;
+
+ mesh_hash = tbl->hash_buckets;
+ for (i = 0; i <= tbl->hash_mask; i++) {
+ spin_lock(&tbl->hashwlock[i]);
+ hlist_for_each_safe(p, q, &mesh_hash[i]) {
+ tbl->free_node(p, free_leafs);
+ atomic_dec(&tbl->entries);
+ }
+ spin_unlock(&tbl->hashwlock[i]);
+ }
+ __mesh_table_free(tbl);
+}
+
+static struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
+{
+ struct mesh_table *newtbl;
+ struct hlist_head *oldhash;
+ struct hlist_node *p, *q;
+ int i;
+
+ if (atomic_read(&tbl->entries)
+ < tbl->mean_chain_len * (tbl->hash_mask + 1))
+ goto endgrow;
+
+ newtbl = mesh_table_alloc(tbl->size_order + 1);
+ if (!newtbl)
+ goto endgrow;
+
+ newtbl->free_node = tbl->free_node;
+ newtbl->mean_chain_len = tbl->mean_chain_len;
+ newtbl->copy_node = tbl->copy_node;
+ atomic_set(&newtbl->entries, atomic_read(&tbl->entries));
+
+ oldhash = tbl->hash_buckets;
+ for (i = 0; i <= tbl->hash_mask; i++)
+ hlist_for_each(p, &oldhash[i])
+ if (tbl->copy_node(p, newtbl) < 0)
+ goto errcopy;
+
+ return newtbl;
+
+errcopy:
+ for (i = 0; i <= newtbl->hash_mask; i++) {
+ hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
+ tbl->free_node(p, 0);
+ }
+ __mesh_table_free(newtbl);
+endgrow:
+ return NULL;
+}
+
/* This lock will have the grow table function as writer and add / delete nodes
* as readers. When reading the table (i.e. doing lookups) we are well protected
@@ -187,6 +250,8 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data
*/
int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct ieee80211_local *local = sdata->local;
struct mesh_path *mpath, *new_mpath;
struct mpath_node *node, *new_node;
struct hlist_head *bucket;
@@ -195,8 +260,6 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
int err = 0;
u32 hash_idx;
- might_sleep();
-
if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
/* never add ourselves as neighbours */
return -ENOTSUPP;
@@ -208,11 +271,11 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
return -ENOSPC;
err = -ENOMEM;
- new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL);
+ new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
if (!new_mpath)
goto err_path_alloc;
- new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
+ new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
if (!new_node)
goto err_node_alloc;
@@ -250,20 +313,8 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
spin_unlock(&mesh_paths->hashwlock[hash_idx]);
read_unlock(&pathtbl_resize_lock);
if (grow) {
- struct mesh_table *oldtbl, *newtbl;
-
- write_lock(&pathtbl_resize_lock);
- oldtbl = mesh_paths;
- newtbl = mesh_table_grow(mesh_paths);
- if (!newtbl) {
- write_unlock(&pathtbl_resize_lock);
- return 0;
- }
- rcu_assign_pointer(mesh_paths, newtbl);
- write_unlock(&pathtbl_resize_lock);
-
- synchronize_rcu();
- mesh_table_free(oldtbl, false);
+ set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
+ queue_work(local->hw.workqueue, &ifmsh->work);
}
return 0;
@@ -278,9 +329,46 @@ err_path_alloc:
return err;
}
+void mesh_mpath_table_grow(void)
+{
+ struct mesh_table *oldtbl, *newtbl;
+
+ write_lock(&pathtbl_resize_lock);
+ oldtbl = mesh_paths;
+ newtbl = mesh_table_grow(mesh_paths);
+ if (!newtbl) {
+ write_unlock(&pathtbl_resize_lock);
+ return;
+ }
+ rcu_assign_pointer(mesh_paths, newtbl);
+ write_unlock(&pathtbl_resize_lock);
+
+ synchronize_rcu();
+ mesh_table_free(oldtbl, false);
+}
+
+void mesh_mpp_table_grow(void)
+{
+ struct mesh_table *oldtbl, *newtbl;
+
+ write_lock(&pathtbl_resize_lock);
+ oldtbl = mpp_paths;
+ newtbl = mesh_table_grow(mpp_paths);
+ if (!newtbl) {
+ write_unlock(&pathtbl_resize_lock);
+ return;
+ }
+ rcu_assign_pointer(mpp_paths, newtbl);
+ write_unlock(&pathtbl_resize_lock);
+
+ synchronize_rcu();
+ mesh_table_free(oldtbl, false);
+}
int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct ieee80211_local *local = sdata->local;
struct mesh_path *mpath, *new_mpath;
struct mpath_node *node, *new_node;
struct hlist_head *bucket;
@@ -289,8 +377,6 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
int err = 0;
u32 hash_idx;
- might_sleep();
-
if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
/* never add ourselves as neighbours */
return -ENOTSUPP;
@@ -299,11 +385,11 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
return -ENOTSUPP;
err = -ENOMEM;
- new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL);
+ new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
if (!new_mpath)
goto err_path_alloc;
- new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
+ new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
if (!new_node)
goto err_node_alloc;
@@ -337,20 +423,8 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
spin_unlock(&mpp_paths->hashwlock[hash_idx]);
read_unlock(&pathtbl_resize_lock);
if (grow) {
- struct mesh_table *oldtbl, *newtbl;
-
- write_lock(&pathtbl_resize_lock);
- oldtbl = mpp_paths;
- newtbl = mesh_table_grow(mpp_paths);
- if (!newtbl) {
- write_unlock(&pathtbl_resize_lock);
- return 0;
- }
- rcu_assign_pointer(mpp_paths, newtbl);
- write_unlock(&pathtbl_resize_lock);
-
- synchronize_rcu();
- mesh_table_free(oldtbl, false);
+ set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags);
+ queue_work(local->hw.workqueue, &ifmsh->work);
}
return 0;
--
1.5.4.3
^ permalink raw reply related
* [PATCH 7/8] mac80211: Assign a default mesh beaconing interval.
From: Javier Cardona @ 2009-08-08 3:38 UTC (permalink / raw)
To: linux-wireless; +Cc: Javier Cardona, andrey, johannes, linville, devel
In-Reply-To: <1249702711-32737-7-git-send-email-javier@cozybit.com>
Incidentally, this fixes mesh beaconing in mac80211_hwsim devices.
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
net/mac80211/mesh.c | 6 ++++--
net/mac80211/mesh.h | 1 +
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 5202d7c..3b49d39 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -525,9 +525,11 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
struct ieee80211_local *local = sdata->local;
ifmsh->housekeeping = true;
- ieee80211_queue_work(&local->hw, &ifmsh->work);
+ queue_work(local->hw, &ifmsh->work);
+ sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
- BSS_CHANGED_BEACON_ENABLED);
+ BSS_CHANGED_BEACON_ENABLED |
+ BSS_CHANGED_BEACON_INT);
}
void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 6cb3db8..b6ea100 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -174,6 +174,7 @@ struct mesh_rmc {
*/
#define MESH_PATH_REFRESH_TIME 1000
#define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
+#define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */
#define MESH_MAX_PREQ_RETRIES 4
#define MESH_PATH_EXPIRE (600 * HZ)
--
1.5.4.3
^ permalink raw reply related
* [PATCH 6/8] mac80211: Early detection of broken mesh paths when using minstrel.
From: Javier Cardona @ 2009-08-08 3:38 UTC (permalink / raw)
To: linux-wireless; +Cc: Javier Cardona, andrey, johannes, linville, devel
In-Reply-To: <1249702711-32737-6-git-send-email-javier@cozybit.com>
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
net/mac80211/mesh_hwmp.c | 1 -
net/mac80211/rc80211_minstrel.c | 8 +++++++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index b4309b2..1cd1e72 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -272,7 +272,6 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
}
last_hop_metric = airtime_link_metric_get(local, sta);
- printk("XXX: last_hop_metric = %d\n", last_hop_metric);
/* Update and check originator routing info */
fresh_info = true;
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 3ea9740..0071649 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -51,6 +51,7 @@
#include <linux/random.h>
#include <linux/ieee80211.h>
#include <net/mac80211.h>
+#include "mesh.h"
#include "rate.h"
#include "rc80211_minstrel.h"
@@ -178,9 +179,14 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) {
mi->r[ndx].success += success;
- if (si)
+ if (si) {
si->fail_avg = (18050 - mi->r[ndx].probability)
/ 180;
+ WARN_ON(si->fail_avg > 100);
+ if (si->fail_avg == 100 &&
+ ieee80211_vif_is_mesh(&si->sdata->vif))
+ mesh_plink_broken(si);
+ }
}
}
--
1.5.4.3
^ permalink raw reply related
* [PATCH 5/8] mac80211: Update the station failed frames average when minstrel is used.
From: Javier Cardona @ 2009-08-08 3:38 UTC (permalink / raw)
To: linux-wireless; +Cc: Javier Cardona, andrey, johannes, linville, devel
In-Reply-To: <1249702711-32737-5-git-send-email-javier@cozybit.com>
The fail_avg value is used to compute the mesh metric, and was only being set
by the pid rate control module. This fixes the mesh path selection mechanism
for cards that use mistrel for rate control.
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
net/mac80211/rc80211_minstrel.c | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 7c51429..3ea9740 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -155,12 +155,16 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct sk_buff *skb)
{
struct minstrel_sta_info *mi = priv_sta;
+ struct minstrel_priv *mp = (struct minstrel_priv *)priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *ar = info->status.rates;
+ struct ieee80211_local *local = hw_to_local(mp->hw);
+ struct sta_info *si;
int i, ndx;
int success;
success = !!(info->flags & IEEE80211_TX_STAT_ACK);
+ si = sta_info_get(local, sta->addr);
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
if (ar[i].idx < 0)
@@ -172,8 +176,12 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
mi->r[ndx].attempts += ar[i].count;
- if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0))
+ if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) {
mi->r[ndx].success += success;
+ if (si)
+ si->fail_avg = (18050 - mi->r[ndx].probability)
+ / 180;
+ }
}
if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0))
--
1.5.4.3
^ permalink raw reply related
* [PATCH 4/8] mac80211: Use 3-address format for mesh broadcast frames.
From: Javier Cardona @ 2009-08-08 3:38 UTC (permalink / raw)
To: linux-wireless; +Cc: Javier Cardona, andrey, johannes, linville, devel
In-Reply-To: <1249702711-32737-4-git-send-email-javier@cozybit.com>
The 11s task group recently changed the frame mesh multicast/broadcast frame
format to use 3-address. This was done to avoid interactions with widely
deployed lazy-WDS access points.
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
net/mac80211/mesh.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++---
net/mac80211/mesh.h | 5 +++-
net/mac80211/rx.c | 45 ++++++++++++++++++++++-------------
net/mac80211/tx.c | 64 +++++++++++++++++++++++++++------------------------
net/wireless/util.c | 16 +++++++++---
5 files changed, 136 insertions(+), 56 deletions(-)
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index d9292a9..5202d7c 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -399,21 +399,75 @@ endgrow:
}
/**
+ * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
+ * @hdr: 802.11 frame header
+ * @fc: frame control field
+ * @meshda: destination address in the mesh
+ * @meshsa: source address address in the mesh. Same as TA, as frame is
+ * locally originated.
+ *
+ * Return the length of the 802.11 (does not include a mesh control header)
+ */
+int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, char
+ *meshda, char *meshsa) {
+ if (is_multicast_ether_addr(meshda)) {
+ *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
+ /* DA TA SA */
+ memcpy(hdr->addr1, meshda, ETH_ALEN);
+ memcpy(hdr->addr2, meshsa, ETH_ALEN);
+ memcpy(hdr->addr3, meshsa, ETH_ALEN);
+ return 24;
+ } else {
+ *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
+ IEEE80211_FCTL_TODS);
+ /* RA TA DA SA */
+ memset(hdr->addr1, 0, ETH_ALEN); /* RA is resolved later */
+ memcpy(hdr->addr2, meshsa, ETH_ALEN);
+ memcpy(hdr->addr3, meshda, ETH_ALEN);
+ memcpy(hdr->addr4, meshsa, ETH_ALEN);
+ return 30;
+ }
+}
+
+/**
* ieee80211_new_mesh_header - create a new mesh header
* @meshhdr: uninitialized mesh header
* @sdata: mesh interface to be used
+ * @addr4: addr4 of the mesh frame (1st in ae header)
+ * may be NULL
+ * @addr5: addr5 of the mesh frame (1st or 2nd in ae header)
+ * may be NULL unless addr6 is present
+ * @addr6: addr6 of the mesh frame (2nd or 3rd in ae header)
+ * may be NULL unless addr5 is present
*
* Return the header length.
*/
int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
- struct ieee80211_sub_if_data *sdata)
+ struct ieee80211_sub_if_data *sdata, char *addr4,
+ char *addr5, char *addr6)
{
- meshhdr->flags = 0;
+ int aelen = 0;
+ memset(meshhdr, 0, sizeof(meshhdr));
meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
sdata->u.mesh.mesh_seqnum++;
-
- return 6;
+ if (addr4) {
+ meshhdr->flags |= MESH_FLAGS_AE_A4;
+ aelen += ETH_ALEN;
+ memcpy(meshhdr->eaddr1, addr4, ETH_ALEN);
+ }
+ if (addr5 && addr6) {
+ meshhdr->flags |= MESH_FLAGS_AE_A5_A6;
+ aelen += 2 * ETH_ALEN;
+ if (!addr4) {
+ memcpy(meshhdr->eaddr1, addr5, ETH_ALEN);
+ memcpy(meshhdr->eaddr2, addr6, ETH_ALEN);
+ } else {
+ memcpy(meshhdr->eaddr2, addr5, ETH_ALEN);
+ memcpy(meshhdr->eaddr3, addr6, ETH_ALEN);
+ }
+ }
+ return 6 + aelen;
}
static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 8e70dae..6cb3db8 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -193,8 +193,11 @@ struct mesh_rmc {
/* Public interfaces */
/* Various */
+int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
+ char *da, char *sa);
int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
- struct ieee80211_sub_if_data *sdata);
+ struct ieee80211_sub_if_data *sdata, char *addr4,
+ char *addr5, char *addr6);
int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
struct ieee80211_sub_if_data *sdata);
bool mesh_matches_local(struct ieee802_11_elems *ie,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 25a669c..e7d8895 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -489,12 +489,21 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ char *dev_addr = rx->dev->dev_addr;
if (ieee80211_is_data(hdr->frame_control)) {
- if (!ieee80211_has_a4(hdr->frame_control))
- return RX_DROP_MONITOR;
- if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0)
- return RX_DROP_MONITOR;
+ if (is_multicast_ether_addr(hdr->addr1)) {
+ if (ieee80211_has_tods(hdr->frame_control) ||
+ !ieee80211_has_fromds(hdr->frame_control))
+ return RX_DROP_MONITOR;
+ if (memcmp(hdr->addr3, dev_addr, ETH_ALEN) == 0)
+ return RX_DROP_MONITOR;
+ } else {
+ if (!ieee80211_has_a4(hdr->frame_control))
+ return RX_DROP_MONITOR;
+ if (memcmp(hdr->addr4, dev_addr, ETH_ALEN) == 0)
+ return RX_DROP_MONITOR;
+ }
}
/* If there is not an established peer link and this is not a peer link
@@ -527,7 +536,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
if (ieee80211_is_data(hdr->frame_control) &&
is_multicast_ether_addr(hdr->addr1) &&
- mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->sdata))
+ mesh_rmc_check(hdr->addr3, msh_h_get(hdr, hdrlen), rx->sdata))
return RX_DROP_MONITOR;
#undef msh_h_get
@@ -1495,7 +1504,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
/* illegal frame */
return RX_DROP_MONITOR;
- if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){
+ if (!is_multicast_ether_addr(hdr->addr1) &&
+ (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6)) {
struct mesh_path *mppath;
rcu_read_lock();
@@ -1512,7 +1522,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
rcu_read_unlock();
}
- if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0)
+ /* Frame has reached destination. Don't forward */
+ if (!is_multicast_ether_addr(hdr->addr1) &&
+ compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0)
return RX_CONTINUE;
mesh_hdr->ttl--;
@@ -1532,22 +1544,21 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
rx->dev->name);
fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
- /*
- * Save TA to addr1 to send TA a path error if a
- * suitable next hop is not found
- */
- memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN);
memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN);
info = IEEE80211_SKB_CB(fwd_skb);
memset(info, 0, sizeof(*info));
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
info->control.vif = &rx->sdata->vif;
ieee80211_select_queue(local, fwd_skb);
- if (is_multicast_ether_addr(fwd_hdr->addr3))
- memcpy(fwd_hdr->addr1, fwd_hdr->addr3,
+ if (!is_multicast_ether_addr(fwd_hdr->addr1)) {
+ int err;
+ /*
+ * Save TA to addr1 to send TA a path error if a
+ * suitable next hop is not found
+ */
+ memcpy(fwd_hdr->addr1, fwd_hdr->addr2,
ETH_ALEN);
- else {
- int err = mesh_nexthop_lookup(fwd_skb, sdata);
+ err = mesh_nexthop_lookup(fwd_skb, sdata);
/* Failed to immediately resolve next hop:
* fwded frame was dropped or will be added
* later to the pending skb queue. */
@@ -1560,7 +1571,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
}
}
- if (is_multicast_ether_addr(hdr->addr3) ||
+ if (is_multicast_ether_addr(hdr->addr1) ||
rx->dev->flags & IFF_PROMISC)
return RX_CONTINUE;
else
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 0df5a96..a97d541 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1461,9 +1461,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
if (ieee80211_vif_is_mesh(&sdata->vif) &&
ieee80211_is_data(hdr->frame_control)) {
- if (is_multicast_ether_addr(hdr->addr3))
- memcpy(hdr->addr1, hdr->addr3, ETH_ALEN);
- else
+ if (!is_multicast_ether_addr(hdr->addr1))
if (mesh_nexthop_lookup(skb, sdata)) {
dev_put(sdata->dev);
return;
@@ -1666,52 +1664,58 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
break;
#ifdef CONFIG_MAC80211_MESH
case NL80211_IFTYPE_MESH_POINT:
- fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
if (!sdata->u.mesh.mshcfg.dot11MeshTTL) {
/* Do not send frames with mesh_ttl == 0 */
sdata->u.mesh.mshstats.dropped_frames_ttl++;
ret = 0;
goto fail;
}
- memset(&mesh_hdr, 0, sizeof(mesh_hdr));
if (compare_ether_addr(dev->dev_addr,
skb->data + ETH_ALEN) == 0) {
- /* RA TA DA SA */
- memset(hdr.addr1, 0, ETH_ALEN);
- memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
- memcpy(hdr.addr3, skb->data, ETH_ALEN);
- memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
- meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata);
+ hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
+ skb->data, skb->data + ETH_ALEN);
+ meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
+ sdata, NULL, NULL, NULL);
} else {
/* packet from other interface */
struct mesh_path *mppath;
+ int is_mesh_mcast = 1;
+ char *mesh_da;
- memset(hdr.addr1, 0, ETH_ALEN);
- memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
- memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN);
-
+ rcu_read_lock();
if (is_multicast_ether_addr(skb->data))
- memcpy(hdr.addr3, skb->data, ETH_ALEN);
+ /* DA TA mSA AE:SA */
+ mesh_da = skb->data;
else {
- rcu_read_lock();
mppath = mpp_path_lookup(skb->data, sdata);
- if (mppath)
- memcpy(hdr.addr3, mppath->mpp, ETH_ALEN);
- else
- memset(hdr.addr3, 0xff, ETH_ALEN);
- rcu_read_unlock();
+ if (mppath) {
+ /* RA TA mDA mSA AE:DA SA */
+ mesh_da = mppath->mpp;
+ is_mesh_mcast = 0;
+ } else
+ /* DA TA mSA AE:SA */
+ mesh_da = dev->broadcast;
}
+ hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
+ mesh_da, dev->dev_addr);
+ rcu_read_unlock();
+ if (is_mesh_mcast)
+ meshhdrlen =
+ ieee80211_new_mesh_header(&mesh_hdr,
+ sdata,
+ skb->data + ETH_ALEN,
+ NULL,
+ NULL);
+ else
+ meshhdrlen =
+ ieee80211_new_mesh_header(&mesh_hdr,
+ sdata,
+ NULL,
+ skb->data,
+ skb->data + ETH_ALEN);
- mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6;
- mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
- put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum);
- memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN);
- memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN);
- sdata->u.mesh.mesh_seqnum++;
- meshhdrlen = 18;
}
- hdrlen = 30;
break;
#endif
case NL80211_IFTYPE_STATION:
diff --git a/net/wireless/util.c b/net/wireless/util.c
index ba387d8..693275a 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -274,11 +274,11 @@ static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
switch (ae) {
case 0:
return 6;
- case 1:
+ case MESH_FLAGS_AE_A4:
return 12;
- case 2:
+ case MESH_FLAGS_AE_A5_A6:
return 18;
- case 3:
+ case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6):
return 24;
default:
return 6;
@@ -333,10 +333,18 @@ int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr,
}
break;
case cpu_to_le16(IEEE80211_FCTL_FROMDS):
- if (iftype != NL80211_IFTYPE_STATION ||
+ if ((iftype != NL80211_IFTYPE_STATION &&
+ iftype != NL80211_IFTYPE_MESH_POINT) ||
(is_multicast_ether_addr(dst) &&
!compare_ether_addr(src, addr)))
return -1;
+ if (iftype == NL80211_IFTYPE_MESH_POINT) {
+ struct ieee80211s_hdr *meshdr =
+ (struct ieee80211s_hdr *) (skb->data + hdrlen);
+ hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
+ if (meshdr->flags & MESH_FLAGS_AE_A4)
+ memcpy(src, meshdr->eaddr1, ETH_ALEN);
+ }
break;
case cpu_to_le16(0):
if (iftype != NL80211_IFTYPE_ADHOC)
--
1.5.4.3
^ permalink raw reply related
* [PATCH 3/8] mac80211: Simulate transmission losses on plinks to aid in testing mesh metrics.
From: Javier Cardona @ 2009-08-08 3:38 UTC (permalink / raw)
To: linux-wireless; +Cc: Javier Cardona, Andrey Yurovsky, johannes, linville, devel
In-Reply-To: <1249702711-32737-3-git-send-email-javier@cozybit.com>
This enables us to specify a simulated loss probability per mesh peer link.
Useful to simulate and test different mesh topologies and test different mesh
metrics.
The simulated loss rate setting can be configured as a plink action. The
intended use is:
iw dev mesh station set <MAC> plink_action loss 25
Signed-off-by: Andrey Yurovsky <andrey@cozybit.com>
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
include/linux/nl80211.h | 4 +++
include/net/cfg80211.h | 4 +++
net/mac80211/cfg.c | 6 +++++
net/mac80211/mesh.c | 1 +
net/mac80211/mesh.h | 1 +
net/mac80211/mesh_hwmp.c | 1 +
net/mac80211/mesh_plink.c | 6 +++++
net/mac80211/sta_info.h | 1 +
net/mac80211/tx.c | 54 +++++++++++++++++++++++++++++++++++++++++++-
net/wireless/nl80211.c | 9 +++++++
10 files changed, 85 insertions(+), 2 deletions(-)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index a8d71ed..3de615b 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -713,6 +713,7 @@ enum nl80211_attrs {
NL80211_ATTR_KEYS,
NL80211_ATTR_PID,
+ NL80211_ATTR_SIM_LOSS,
/* add attributes here, update the policy in nl80211.c */
@@ -1198,6 +1199,8 @@ enum nl80211_mntr_flags {
*
* @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
*
+ * @NL80211_MESHCONF_SIM_LOSS_RATE: simulated loss rate at this MP.
+ *
* @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
*/
enum nl80211_meshconf_params {
@@ -1215,6 +1218,7 @@ enum nl80211_meshconf_params {
NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
+ NL80211_MESHCONF_SIM_LOSS_RATE,
/* keep last */
__NL80211_MESHCONF_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d5756c9..6bc5957 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -265,6 +265,7 @@ enum plink_actions {
PLINK_ACTION_INVALID,
PLINK_ACTION_OPEN,
PLINK_ACTION_BLOCK,
+ PLINK_ACTION_LOSS,
};
/**
@@ -282,6 +283,7 @@ enum plink_actions {
* (bitmask of BIT(NL80211_STA_FLAG_...))
* @listen_interval: listen interval or -1 for no change
* @aid: AID or zero for no change
+ * @sim_loss_rate: simulated TX probable loss percentage
*/
struct station_parameters {
u8 *supported_rates;
@@ -292,6 +294,7 @@ struct station_parameters {
u8 supported_rates_len;
u8 plink_action;
struct ieee80211_ht_cap *ht_capa;
+ u8 sim_loss_rate;
};
/**
@@ -508,6 +511,7 @@ struct mesh_config {
u32 dot11MeshHWMPactivePathTimeout;
u16 dot11MeshHWMPpreqMinInterval;
u16 dot11MeshHWMPnetDiameterTraversalTime;
+ u8 dot11MeshSimLossRate;
};
/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5608f6c..8067f66 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -693,6 +693,9 @@ static void sta_apply_parameters(struct ieee80211_local *local,
case PLINK_ACTION_BLOCK:
mesh_plink_block(sta);
break;
+ case PLINK_ACTION_LOSS:
+ mesh_plink_sim_loss(sta, params->sim_loss_rate);
+ break;
}
}
}
@@ -1043,6 +1046,9 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy,
mask))
conf->dot11MeshHWMPnetDiameterTraversalTime =
nconf->dot11MeshHWMPnetDiameterTraversalTime;
+ if (_chg_mesh_attr(NL80211_MESHCONF_SIM_LOSS_RATE, mask))
+ conf->dot11MeshSimLossRate =
+ nconf->dot11MeshSimLossRate;
return 0;
}
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 8c068e2..d9292a9 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -653,6 +653,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
MESH_PATH_REFRESH_TIME;
ifmsh->mshcfg.min_discovery_timeout =
MESH_MIN_DISCOVERY_TIMEOUT;
+ ifmsh->mshcfg.dot11MeshSimLossRate = 0;
ifmsh->accepting_plinks = true;
ifmsh->preq_id = 0;
ifmsh->dsn = 0;
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 6aaf1ec..8e70dae 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -238,6 +238,7 @@ void mesh_plink_broken(struct sta_info *sta);
void mesh_plink_deactivate(struct sta_info *sta);
int mesh_plink_open(struct sta_info *sta);
void mesh_plink_block(struct sta_info *sta);
+void mesh_plink_sim_loss(struct sta_info *sta, u8 rate);
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len,
struct ieee80211_rx_status *rx_status);
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 1cd1e72..b4309b2 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -272,6 +272,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
}
last_hop_metric = airtime_link_metric_get(local, sta);
+ printk("XXX: last_hop_metric = %d\n", last_hop_metric);
/* Update and check originator routing info */
fresh_info = true;
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index cb14253..7c49c95 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -382,6 +382,12 @@ void mesh_plink_block(struct sta_info *sta)
spin_unlock_bh(&sta->lock);
}
+void mesh_plink_sim_loss(struct sta_info *sta, u8 rate)
+{
+ spin_lock_bh(&sta->lock);
+ sta->plink_sim_loss = rate;
+ spin_unlock_bh(&sta->lock);
+}
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt,
size_t len, struct ieee80211_rx_status *rx_status)
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index ccc3adf..a248a8b 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -294,6 +294,7 @@ struct sta_info {
bool ignore_plink_timer;
bool plink_timer_was_running;
enum plink_state plink_state;
+ u8 plink_sim_loss;
u32 plink_timeout;
struct timer_list plink_timer;
#endif
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index c9be9dc..0df5a96 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -18,6 +18,7 @@
#include <linux/etherdevice.h>
#include <linux/bitmap.h>
#include <linux/rcupdate.h>
+#include <linux/random.h>
#include <net/net_namespace.h>
#include <net/ieee80211_radiotap.h>
#include <net/cfg80211.h>
@@ -39,6 +40,47 @@
/* misc utils */
+/* Decide whether we should simulate the loss of a frame based on the simulated
+ * plink loss probability and the frame's destination. Used for testing.
+ *
+ * Must be invoked with the rcu read lock held.
+ * */
+static int random_tx_loss(struct ieee80211_sub_if_data *sdata, struct
+ ieee80211_hdr *hdr)
+{
+ struct sta_info *sta;
+ u8 r = 0;
+
+ get_random_bytes(&r, sizeof(r));
+
+ list_for_each_entry(sta, &sdata->local->sta_list, list) {
+ if (!memcmp(sta->sta.addr, hdr->addr1, 6))
+ if (r*25 < sta->plink_sim_loss*64)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int simulate_tx_loss(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_hdr *hdr, struct sk_buff *skb)
+{
+ struct ieee80211_hw *hw = &sdata->local->hw;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ ieee80211_tx_info_clear_status(info);
+ info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS;
+
+ info->status.rates[0].idx = 0;
+ info->status.rates[0].count = hw->max_rate_tries;
+
+ ieee80211_tx_status_irqsafe(hw, skb);
+
+ /* this will ensure that the frame is not queued in the tx path */
+ return IEEE80211_TX_OK;
+}
+
static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
int next_frag_len)
{
@@ -1244,6 +1286,7 @@ static void ieee80211_tx(struct ieee80211_sub_if_data *sdata,
struct ieee80211_tx_data tx;
ieee80211_tx_result res_prepare;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct sk_buff *next;
unsigned long flags;
int ret, retries;
@@ -1278,7 +1321,10 @@ static void ieee80211_tx(struct ieee80211_sub_if_data *sdata,
retries = 0;
retry:
- ret = __ieee80211_tx(local, &tx.skb, tx.sta, txpending);
+ if (ieee80211_vif_is_mesh(&sdata->vif) && random_tx_loss(sdata, hdr))
+ ret = simulate_tx_loss(sdata, hdr, skb);
+ else
+ ret = __ieee80211_tx(local, &tx.skb, tx.sta, txpending);
switch (ret) {
case IEEE80211_TX_OK:
break;
@@ -1857,7 +1903,11 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
hdr = (struct ieee80211_hdr *)skb->data;
sta = sta_info_get(local, hdr->addr1);
- ret = __ieee80211_tx(local, &skb, sta, true);
+ if (ieee80211_vif_is_mesh(&sdata->vif) &&
+ random_tx_loss(sdata, hdr))
+ ret = simulate_tx_loss(sdata, hdr, skb);
+ else
+ ret = __ieee80211_tx(local, &skb, sta, true);
if (ret != IEEE80211_TX_OK)
result = false;
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 667a87d..1dfe8ea 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1878,6 +1878,10 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
params.plink_action =
nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
+ if (info->attrs[NL80211_ATTR_SIM_LOSS])
+ params.sim_loss_rate =
+ nla_get_u8(info->attrs[NL80211_ATTR_SIM_LOSS]);
+
rtnl_lock();
err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
@@ -2619,6 +2623,8 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
cur_params.dot11MeshHWMPpreqMinInterval);
NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
cur_params.dot11MeshHWMPnetDiameterTraversalTime);
+ NLA_PUT_U8(msg, NL80211_MESHCONF_SIM_LOSS_RATE,
+ cur_params.dot11MeshSimLossRate);
nla_nest_end(msg, pinfoattr);
genlmsg_end(msg, hdr);
err = genlmsg_reply(msg, info);
@@ -2661,6 +2667,7 @@ nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] __read_mostly = {
[NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
[NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 },
[NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },
+ [NL80211_MESHCONF_SIM_LOSS_RATE] = { .type = NLA_U8 },
};
static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
@@ -2729,6 +2736,8 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
dot11MeshHWMPnetDiameterTraversalTime,
mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
nla_get_u16);
+ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshSimLossRate,
+ mask, NL80211_MESHCONF_SIM_LOSS_RATE, nla_get_u8);
/* Apply changes */
err = rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask);
--
1.5.4.3
^ permalink raw reply related
* [PATCH 2/8] mac80211: Use correct sign for mesh active path refresh.
From: Javier Cardona @ 2009-08-08 3:38 UTC (permalink / raw)
To: linux-wireless; +Cc: Andrey Yurovsky, Javier Cardona, johannes, linville, devel
In-Reply-To: <1249702711-32737-2-git-send-email-javier@cozybit.com>
From: Andrey Yurovsky <andrey@cozybit.com>
On locally originated traffic, we refresh active paths after a timeout. The
decision to do this was using the wrong sign and therefore the refresh timer
was triggered for every frame.
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
net/mac80211/mesh_hwmp.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index b54c21c..1cd1e72 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -791,7 +791,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
}
if (mpath->flags & MESH_PATH_ACTIVE) {
- if (time_after(jiffies, mpath->exp_time -
+ if (time_after(jiffies, mpath->exp_time +
msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time))
&& !memcmp(sdata->dev->dev_addr, hdr->addr4,
ETH_ALEN)
--
1.5.4.3
^ permalink raw reply related
* [PATCH 1/8] mac80211: Improve dequeing from mpath frame queue.
From: Javier Cardona @ 2009-08-08 3:38 UTC (permalink / raw)
To: linux-wireless; +Cc: Andrey Yurovsky, Javier Cardona, johannes, linville, devel
In-Reply-To: <1249702711-32737-1-git-send-email-javier@cozybit.com>
From: Andrey Yurovsky <andrey@cozybit.com>
Also, fix typo in comment.
Signed-off-by: Javier Cardona <javier@cozybit.com>
---
net/mac80211/mesh.h | 2 +-
net/mac80211/mesh_hwmp.c | 6 ++----
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index ce53881..6aaf1ec 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -61,7 +61,7 @@ enum mesh_path_flags {
* retry
* @discovery_retries: number of discovery retries
* @flags: mesh path flags, as specified on &enum mesh_path_flags
- * @state_lock: mesh pat state lock
+ * @state_lock: mesh path state lock
*
*
* The combination of dst and sdata is unique in the mesh path table. Since the
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index e1a763e..b54c21c 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -810,10 +810,8 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
}
if (skb_queue_len(&mpath->frame_queue) >=
- MESH_FRAME_QUEUE_LEN) {
- skb_to_free = mpath->frame_queue.next;
- skb_unlink(skb_to_free, &mpath->frame_queue);
- }
+ MESH_FRAME_QUEUE_LEN)
+ skb_to_free = skb_dequeue(&mpath->frame_queue);
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
skb_queue_tail(&mpath->frame_queue, skb);
--
1.5.4.3
^ permalink raw reply related
* Mesh fixes and improvements
From: Javier Cardona @ 2009-08-08 3:38 UTC (permalink / raw)
To: linux-wireless; +Cc: andrey, johannes, linville, devel
[Resent with proper patch numbering...]
This series includes some fixes, testing aids and improvements to the mesh
stack. It is important to note that the patch
"Use-3-address-format-for-mesh-broadcast-frames" breaks compatibility with
previous versions. This is unavoidable and will keep happening as new versions
of the 802.11s drafts are produced.
Also, I'm not sure if "Simulate-transmission-losses-on-plinks-to-..." should be
merged upstream, but we find it really useful to test mesh configurations.
Please comment if you have different opinions on its adequacy or
implementation.
Cheers,
Javier
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox