Search Linux Wireless

Re: [RFC] Simulate medium behavior

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Apr 22, 2009 at 01:35:56PM +0200, Daniel Wagner wrote:
> On Wed, Apr 22, 2009 at 11:38:08AM +0200, Johannes Berg wrote:
> > Hi,
> > 
> > > Writing a 0 to /debug/ieee80211/phy*/hwsim/medium enables rx/tx for
> > > the specific phy. Writing anything but 0 disables rx/tx.  Not a very
> > > good API. It could be made something more realistic like reception
> > > quality is 80% associated some statistical dropping algorithm. Any
> > > thoughts?
> > > 
> > > Is this the right direction I'm heading to?
> > 
> > This looks like a very simple knob, just a little more work could get
> > you much further -- have you seen this email/thread?
> > 
> > http://thread.gmane.org/gmane.linux.kernel.wireless.general/25001
> 
> No, I haven't. Yep, my solution is really too simple.  I like the
> virtual air grouping. I'll implement it.

After a bit studying how to use configfs (and getting a bit lost)
I found netconsole.c which uses configfs. So this version is a copy&past
thing. Of course, this needs more work. 

Is this what do did have in mind?

How it works:

# modprobe mac80211_hwsim
# mount -t configfs none /config

Make phy0 radio member of group 1: 
# mkdir /config/mac80211_hwsim/phy0
# echo "phy0" > /config/mac80211_hwsim/phy0/dev_name
# echo 1 > /config/mac80211_hwsim/phy0/group
# echo 1 > /config/mac80211_hwsim/phy0/enable

I have only tested it very short, no problems found. Works as expected :)
 
cheers,
daniel

---
 drivers/net/wireless/Kconfig          |    9 +
 drivers/net/wireless/mac80211_hwsim.c |  324 ++++++++++++++++++++++++++++++++-
 2 files changed, 332 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 2d8434f..5316675 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -481,6 +481,15 @@ config MAC80211_HWSIM
 	  To compile this driver as a module, choose M here: the module will be
 	  called mac80211_hwsim.  If unsure, say N.
 
+config MAC80211_HWSIM_VGROUP
+	bool "enable virtual air grouping"
+	depends on MAC80211_HWSIM
+	default y
+	help
+	  This option enables virtual air grouping.
+
+	  If unsure, say N.
+
 config MWL8K
 	tristate "Marvell 88W8xxx PCI/PCIe Wireless support"
 	depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index d4fdc8b..bafe451 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -21,6 +21,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/etherdevice.h>
 #include <linux/debugfs.h>
+#include <linux/configfs.h>
 
 MODULE_AUTHOR("Jouni Malinen");
 MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211");
@@ -291,6 +292,8 @@ struct mac80211_hwsim_data {
 	bool ps_poll_pending;
 	struct dentry *debugfs;
 	struct dentry *debugfs_ps;
+
+	unsigned int group;
 };
 
 
@@ -412,7 +415,8 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
 
 		if (!data2->started || !data2->radio_enabled ||
 		    !hwsim_ps_rx_ok(data2, skb) ||
-		    data->channel->center_freq != data2->channel->center_freq)
+		    data->channel->center_freq != data2->channel->center_freq ||
+		    !(data->group & data2->group))
 			continue;
 
 		nskb = skb_copy(skb, GFP_ATOMIC);
@@ -877,6 +881,320 @@ DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write,
 			"%llu\n");
 
 
+#ifdef CONFIG_MAC80211_HWSIM_VGROUP
+
+/* Linked list of all configured targets */
+static LIST_HEAD(target_list);
+
+/* XXX document the spinlock */
+static DEFINE_SPINLOCK(target_list_lock);
+
+/**
+ * struct mac80211_hwsim_target - Represents a configured mac80211_hwsim target.
+ * @list:	Links this target into the target_list.
+ * @item:	Links us into the configfs subsystem hierarchy.
+ * @enabled:	On / off knob to enable / disable target.
+ *		Visible from userspace (read-write).
+ *		Contains the other userspace visible parameters:
+ *		dev_name	(read-write)
+ *		local_port	(read-write)
+ *		group		(read-write)
+ */
+struct mac80211_hwsim_target {
+	struct list_head	list;
+	struct config_item	item;
+	int			enabled;
+	char		        dev_name[IFNAMSIZ];
+	long			group;
+};
+
+
+/*
+ * Our subsystem hierarchy is:
+ *
+ * /config/mac80211_hwsim/
+ *				|
+ *				<target>/
+ *				|	enabled
+ *				|	dev_name
+ *				|	group
+ *				|
+ *				<target>/...
+ */
+
+struct mac80211_hwsim_target_attr {
+	struct configfs_attribute	attr;
+	ssize_t				(*show)(struct mac80211_hwsim_target *nt,
+						char *buf);
+	ssize_t				(*store)(struct mac80211_hwsim_target *nt,
+						 const char *buf,
+						 size_t count);
+};
+
+static struct mac80211_hwsim_target *to_target(struct config_item *item)
+{
+	return item ?
+		container_of(item, struct mac80211_hwsim_target, item) :
+		NULL;
+}
+
+
+/*
+ * Attribute operations for mac80211_hwsim_target.
+ */
+
+static ssize_t show_enabled(struct mac80211_hwsim_target *nt, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", nt->enabled);
+}
+
+static ssize_t show_dev_name(struct mac80211_hwsim_target *nt, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", nt->dev_name);
+}
+
+static ssize_t show_group(struct mac80211_hwsim_target *nt, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%ld\n", nt->group);
+}
+
+
+static ssize_t store_enabled(struct mac80211_hwsim_target *nt,
+			     const char *buf,
+			     size_t count)
+{
+	char *p = (char *) buf;
+	int tmp;
+	struct mac80211_hwsim_data *data;
+
+	tmp = simple_strtoul(p, &p, 10);
+	if (!p || (*p && (*p != '\n')))
+		return -EINVAL;
+
+	if (tmp != 0 && tmp != 1)
+		return -ERANGE;
+
+	spin_lock(&hwsim_radio_lock);
+	list_for_each_entry(data, &hwsim_radios, list) {
+		if (strcmp(wiphy_name(data->hw->wiphy), nt->dev_name) == 0) {
+			data->group = nt->group;
+			break;
+		}
+	}
+	spin_unlock(&hwsim_radio_lock);
+
+	nt->enabled = tmp;
+
+	return strnlen(buf, count);
+}
+
+static ssize_t store_dev_name(struct mac80211_hwsim_target *nt,
+			      const char *buf,
+			      size_t count)
+{
+	size_t len;
+
+	if (nt->enabled) {
+		printk(KERN_ERR "mac80211_hwsim: target (%s) is enabled, "
+				"disable to update parameters\n",
+				config_item_name(&nt->item));
+		return -EINVAL;
+	}
+
+	strlcpy(nt->dev_name, buf, IFNAMSIZ);
+
+	/* Get rid of possible trailing newline from echo(1) */
+	len = strnlen(nt->dev_name, IFNAMSIZ);
+	if (nt->dev_name[len - 1] == '\n')
+		nt->dev_name[len - 1] = '\0';
+
+	return strnlen(buf, count);
+}
+
+static ssize_t store_group(struct mac80211_hwsim_target *nt,
+			   const char *buf,
+			   size_t count)
+{
+	char *p = (char *) buf;
+
+	if (nt->enabled) {
+		printk(KERN_ERR "mac80211_hwsim: target (%s) is enabled, "
+				"disable to update parameters\n",
+				config_item_name(&nt->item));
+		return -EINVAL;
+	}
+	
+	nt->group = simple_strtoul(p, &p, 16);
+
+	return strnlen(buf, count);
+}
+
+
+/*
+ * Attribute definitions for mac80211_hwsim_target.
+ */
+
+#define MAC80211_HWSIM_TARGET_ATTR_RO(_name)				\
+static struct mac80211_hwsim_target_attr mac80211_hwsim_target_##_name =	\
+	__CONFIGFS_ATTR(_name, S_IRUGO, show_##_name, NULL)
+
+#define MAC80211_HWSIM_TARGET_ATTR_RW(_name)				\
+static struct mac80211_hwsim_target_attr mac80211_hwsim_target_##_name =	\
+	__CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, show_##_name, store_##_name)
+
+MAC80211_HWSIM_TARGET_ATTR_RW(enabled);
+MAC80211_HWSIM_TARGET_ATTR_RW(dev_name);
+MAC80211_HWSIM_TARGET_ATTR_RW(group);
+
+static struct configfs_attribute *mac80211_hwsim_target_attrs[] = {
+	&mac80211_hwsim_target_enabled.attr,
+	&mac80211_hwsim_target_dev_name.attr,
+	&mac80211_hwsim_target_group.attr,
+	NULL,
+};
+
+/*
+ * Item operations and type for mac80211_hwsim_target.
+ */
+
+static void mac80211_hwsim_target_release(struct config_item *item)
+{
+	kfree(to_target(item));
+}
+
+static ssize_t mac80211_hwsim_target_attr_show(struct config_item *item,
+					   struct configfs_attribute *attr,
+					   char *buf)
+{
+	ssize_t ret = -EINVAL;
+	struct mac80211_hwsim_target *nt = to_target(item);
+	struct mac80211_hwsim_target_attr *na =
+		container_of(attr, struct mac80211_hwsim_target_attr, attr);
+
+	if (na->show)
+		ret = na->show(nt, buf);
+
+	return ret;
+}
+
+static ssize_t mac80211_hwsim_target_attr_store(struct config_item *item,
+					    struct configfs_attribute *attr,
+					    const char *buf,
+					    size_t count)
+{
+	ssize_t ret = -EINVAL;
+	struct mac80211_hwsim_target *nt = to_target(item);
+	struct mac80211_hwsim_target_attr *na =
+		container_of(attr, struct mac80211_hwsim_target_attr, attr);
+
+	if (na->store)
+		ret = na->store(nt, buf, count);
+
+	return ret;
+}
+
+static struct configfs_item_operations mac80211_hwsim_target_item_ops = {
+	.release		= mac80211_hwsim_target_release,
+	.show_attribute		= mac80211_hwsim_target_attr_show,
+	.store_attribute	= mac80211_hwsim_target_attr_store,
+};
+
+static struct config_item_type mac80211_hwsim_target_type = {
+	.ct_attrs		= mac80211_hwsim_target_attrs,
+	.ct_item_ops		= &mac80211_hwsim_target_item_ops,
+	.ct_owner		= THIS_MODULE,
+};
+
+/*
+ * Group operations and type for mac80211_hwsim_subsys.
+ */
+
+static struct config_item *make_mac80211_hwsim_target(struct config_group *group,
+						  const char *name)
+{
+	unsigned long flags;
+	struct mac80211_hwsim_target *nt;
+
+	/*
+	 * Allocate and initialize with defaults.
+	 * Target is disabled at creation (enabled == 0).
+	 */
+	nt = kzalloc(sizeof(*nt), GFP_KERNEL);
+	if (!nt) {
+		printk(KERN_ERR "mac80211_hwsim: failed to allocate memory\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* Initialize the config_item member */
+	config_item_init_type_name(&nt->item, name, &mac80211_hwsim_target_type);
+
+	/* Adding, but it is disabled */
+	spin_lock_irqsave(&target_list_lock, flags);
+	list_add(&nt->list, &target_list);
+	spin_unlock_irqrestore(&target_list_lock, flags);
+
+	return &nt->item;
+}
+
+static void drop_mac80211_hwsim_target(struct config_group *group,
+				   struct config_item *item)
+{
+	unsigned long flags;
+	struct mac80211_hwsim_target *nt = to_target(item);
+
+	spin_lock_irqsave(&target_list_lock, flags);
+	list_del(&nt->list);
+	spin_unlock_irqrestore(&target_list_lock, flags);
+
+
+	config_item_put(&nt->item);
+}
+
+static struct configfs_group_operations mac80211_hwsim_subsys_group_ops = {
+	.make_item	= make_mac80211_hwsim_target,
+	.drop_item	= drop_mac80211_hwsim_target,
+};
+
+static struct config_item_type mac80211_hwsim_subsys_type = {
+	.ct_group_ops	= &mac80211_hwsim_subsys_group_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+/* The mac80211_hwsim configfs subsystem */
+static struct configfs_subsystem mac80211_hwsim_subsys = {
+	.su_group	= {
+		.cg_item	= {
+			.ci_namebuf	= "mac80211_hwsim",
+			.ci_type	= &mac80211_hwsim_subsys_type,
+		},
+	},
+};
+
+static int __init configfs_mac80211_hwsim_init(void)
+{
+	config_group_init(&mac80211_hwsim_subsys.su_group);
+	mutex_init(&mac80211_hwsim_subsys.su_mutex);
+	return configfs_register_subsystem(&mac80211_hwsim_subsys);
+}
+
+static void __exit configfs_mac80211_hwsim_exit(void)
+{
+	configfs_unregister_subsystem(&mac80211_hwsim_subsys);
+}
+
+#else /* !CONFIg_MAC80211_HWSIM_VGROUP */
+
+static int __init configfs_mac80211_hwsim_init(void)
+{
+	return 0;
+}
+
+static void __exit configfs_mac80211_hwsim_exit(void)
+{
+}
+
+#endif /* CONFIG_MAC80211_HWSIM_VGROUP */
+
 static int __init init_mac80211_hwsim(void)
 {
 	int i, err = 0;
@@ -1122,6 +1440,9 @@ static int __init init_mac80211_hwsim(void)
 	if (err < 0)
 		goto failed_mon;
 
+	err = configfs_mac80211_hwsim_init();
+	if (err)
+		goto failed_mon;
 
 	err = register_netdevice(hwsim_mon);
 	if (err < 0)
@@ -1152,6 +1473,7 @@ static void __exit exit_mac80211_hwsim(void)
 	printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n");
 
 	unregister_netdev(hwsim_mon);
+	configfs_mac80211_hwsim_exit();
 	mac80211_hwsim_free();
 }
 
-- 
1.6.2.4

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux