Search Linux Wireless

[PATCH] mac80211_hwsim: configfs support

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

 



Mac80211_hwsim: Support to configfs operations to create a new radio

Signed-off-by: Igor Trindade Oliveira (igor_trindade@xxxxxxxxxxxx)

diff -upr -X wireless-testing-vanilla/Documentation/dontdiff wireless-testing-vanilla/Documentation/networking/mac80211_hwsim/README wireless-testing/Documentation/networking/mac80211_hwsim/README
--- wireless-testing-vanilla/Documentation/networking/mac80211_hwsim/README	2008-12-20 13:40:41.000000000 -0400
+++ wireless-testing/Documentation/networking/mac80211_hwsim/README	2008-12-20 13:41:25.000000000 -0400
@@ -24,11 +24,10 @@ and always reproduce the same setup for
 since all radio operation is simulated, any channel can be used in
 tests regardless of regulatory rules.
 
-mac80211_hwsim kernel module has a parameter 'radios' that can be used
-to select how many radios are simulated (default 2). This allows
-configuration of both very simply setups (e.g., just a single access
-point and a station) or large scale tests (multiple access points with
-hundreds of stations).
+mac80211_hwsim kernel module has support to configfs that can be used
+to create many radios. This allows configuration of both very simply
+setups (e.g., just a single access point and a station) or large scale
+tests (multiple access points with hundreds of stations).
 
 mac80211_hwsim works by tracking the current channel of each virtual
 radio and copying all transmitted frames to all other radios that are
@@ -44,7 +43,7 @@ regardless of channel.
 
 Simple example
 
-This example shows how to use mac80211_hwsim to simulate two radios:
+This example shows how to use mac80211_hwsim to create and simulate two radios:
 one to act as an access point and the other as a station that
 associates with the AP. hostapd and wpa_supplicant are used to take
 care of WPA2-PSK authentication. In addition, hostapd is also
@@ -56,6 +55,18 @@ processing access point side of associat
 # Load the module
 modprobe mac80211_hwsim
 
+# Mount configfs
+mount -t configfs none /mydir
+
+# Go to mac80211_hwsim directory
+cd /mydir/mac80211_hwsim
+
+# Create one radio
+mkdir radio1
+
+# Create other radio
+mkdir radio2
+
 # Run hostapd (AP) for wlan0
 hostapd hostapd.conf
 
diff -upr -X wireless-testing-vanilla/Documentation/dontdiff wireless-testing-vanilla/drivers/net/wireless/mac80211_hwsim.c wireless-testing/drivers/net/wireless/mac80211_hwsim.c
--- wireless-testing-vanilla/drivers/net/wireless/mac80211_hwsim.c	2008-12-20 13:32:58.000000000 -0400
+++ wireless-testing/drivers/net/wireless/mac80211_hwsim.c	2008-12-20 13:42:06.000000000 -0400
@@ -21,15 +21,13 @@
 #include <linux/if_arp.h>
 #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");
 MODULE_LICENSE("GPL");
 
-static int radios = 2;
-module_param(radios, int, 0444);
-MODULE_PARM_DESC(radios, "Number of simulated radios");
+static int radios;
 
 struct hwsim_vif_priv {
 	u32 magic;
@@ -140,10 +138,15 @@ struct mac80211_hwsim_data {
 		PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL
 	} ps;
 	bool ps_poll_pending;
-	struct dentry *debugfs;
-	struct dentry *debugfs_ps;
+	struct config_item item;
 };
 
+struct mac80211_hwsim_attr {
+	struct configfs_attribute attr;
+	ssize_t(*show)(struct mac80211_hwsim_data *hwsim, char *buf);
+	ssize_t(*store)(struct mac80211_hwsim_data *hwsim,
+			  const char *buf, ssize_t count);
+};
 
 struct hwsim_radiotap_hdr {
 	struct ieee80211_radiotap_header hdr;
@@ -498,8 +501,8 @@ static void mac80211_hwsim_bss_info_chan
 
 	if (changed & BSS_CHANGED_HT) {
 		printk(KERN_DEBUG "  %s: HT: op_mode=0x%x\n",
-		       wiphy_name(hw->wiphy),
-		       info->ht.operation_mode);
+			wiphy_name(hw->wiphy),
+			info->ht.operation_mode);			
 	}
 
 	if (changed & BSS_CHANGED_BASIC_RATES) {
@@ -567,23 +570,6 @@ static const struct ieee80211_ops mac802
 
 static void mac80211_hwsim_free(void)
 {
-	struct list_head tmplist, *i, *tmp;
-	struct mac80211_hwsim_data *data;
-
-	INIT_LIST_HEAD(&tmplist);
-
-	spin_lock_bh(&hwsim_radio_lock);
-	list_for_each_safe(i, tmp, &hwsim_radios)
-		list_move(i, &tmplist);
-	spin_unlock_bh(&hwsim_radio_lock);
-
-	list_for_each_entry(data, &tmplist, list) {
-		debugfs_remove(data->debugfs_ps);
-		debugfs_remove(data->debugfs);
-		ieee80211_unregister_hw(data->hw);
-		device_unregister(data->dev);
-		ieee80211_free_hw(data->hw);
-	}
 	class_destroy(hwsim_class);
 }
 
@@ -685,150 +671,291 @@ static void hwsim_send_nullfunc_no_ps(vo
 	hwsim_send_nullfunc(data, mac, vif, 0);
 }
 
+/*
+ *ConfigFs operations
+ */
 
-static int hwsim_fops_ps_read(void *dat, u64 *val)
+static struct mac80211_hwsim_data *to_target(struct config_item *item)
 {
-	struct mac80211_hwsim_data *data = dat;
-	*val = data->ps;
-	return 0;
+	return item ?
+		container_of(item, struct mac80211_hwsim_data, item) : NULL;
 }
 
-static int hwsim_fops_ps_write(void *dat, u64 val)
+static int show_wiphy_name(struct mac80211_hwsim_data *hwsim, char*buf)
 {
-	struct mac80211_hwsim_data *data = dat;
+	return snprintf(buf, PAGE_SIZE, "%s\n", wiphy_name(hwsim->hw->wiphy));
+}
+
+static int show_ps_status(struct mac80211_hwsim_data *hwsim, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", hwsim->ps);
+}
+
+static int store_ps_status(struct mac80211_hwsim_data *hwsim,
+			   const char *buf, ssize_t count)
+{
+	unsigned long int ps;
 	enum ps_mode old_ps;
+	int ret;
 
-	if (val != PS_DISABLED && val != PS_ENABLED && val != PS_AUTO_POLL &&
-	    val != PS_MANUAL_POLL)
+	ret = strict_strtoul(buf, 10, &ps);
+
+	if (ret)
+		return ret;
+
+	if (ps != PS_DISABLED && ps != PS_ENABLED && ps != PS_AUTO_POLL &&
+	    ps != PS_MANUAL_POLL)
 		return -EINVAL;
 
-	old_ps = data->ps;
-	data->ps = val;
+	old_ps = hwsim->ps;
+	hwsim->ps = ps;
 
-	if (val == PS_MANUAL_POLL) {
-		ieee80211_iterate_active_interfaces(data->hw,
-						    hwsim_send_ps_poll, data);
-		data->ps_poll_pending = true;
-	} else if (old_ps == PS_DISABLED && val != PS_DISABLED) {
-		ieee80211_iterate_active_interfaces(data->hw,
+	if (ps == PS_MANUAL_POLL) {
+		ieee80211_iterate_active_interfaces(hwsim->hw,
+						    hwsim_send_ps_poll, hwsim);
+		hwsim->ps_poll_pending = true;
+	} else if (old_ps == PS_DISABLED && ps != PS_DISABLED) {
+		ieee80211_iterate_active_interfaces(hwsim->hw,
 						    hwsim_send_nullfunc_ps,
-						    data);
-	} else if (old_ps != PS_DISABLED && val == PS_DISABLED) {
-		ieee80211_iterate_active_interfaces(data->hw,
+						    hwsim);
+	} else if (old_ps != PS_DISABLED && ps == PS_DISABLED) {
+		ieee80211_iterate_active_interfaces(hwsim->hw,
 						    hwsim_send_nullfunc_no_ps,
-						    data);
+						    hwsim);
 	}
 
-	return 0;
+	return strnlen(buf, count);
 }
 
-DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write,
-			"%llu\n");
+/*
+ * ConfigFS attribute declaration, to add a new attribute we just need to use 
+ * the MAC_HWSIM_ATTR_FOO macros and insert the new attribute in 
+ * mac80211_hwsim_attrs struct.
+ */
 
+#define MAC80211_HWSIM_ATTR_RO(_name, _show)				\
+static struct mac80211_hwsim_attr mac80211_hwsim_##_name =		\
+		__CONFIGFS_ATTR(_name, S_IRUGO, _show, NULL)
 
-static int __init init_mac80211_hwsim(void)
+#define MAC80211_HWSIM_ATTR_RW(_name, _show, _store)                    \
+static struct  mac80211_hwsim_attr mac80211_hwsim_##_name =	        \
+		__CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, _show, _store)
+
+MAC80211_HWSIM_ATTR_RO(wiphy, show_wiphy_name);
+MAC80211_HWSIM_ATTR_RW(ps, show_ps_status, store_ps_status);
+
+static struct configfs_atribbute *mac80211_hwsim_attrs[] = {
+	&mac80211_hwsim_ps.attr,
+	&mac80211_hwsim_wiphy.attr,
+	NULL,
+};
+
+/*
+ *ConfigFS: Item operations
+ */
+
+static void mac80211_hwsim_release(struct config_item *item)
 {
-	int i, err = 0;
+	kfree(to_target(item));
+}
+
+static ssize_t mac80211_hwsim_attr_show(struct config_item *item,
+					struct configfs_attribute *attr,
+					char *buf)
+{
+	struct mac80211_hwsim_data *data = to_target(item);
+	struct mac80211_hwsim_attr *hwsim_attr =
+		container_of(attr, struct mac80211_hwsim_attr, attr);
+
+	return hwsim_attr->show ? hwsim_attr->show(data, buf) : EINVAL;
+}
+
+static ssize_t mac80211_hwsim_attr_store(struct config_item *item,
+					 struct configfs_attribute *attr,
+					 const char *buf, size_t count)
+{
+	struct mac80211_hwsim_data *data = to_target(item);
+	struct mac80211_hwsim_attr *hwsim_attr =
+		container_of(attr, struct mac80211_hwsim_attr, attr);
+
+	return hwsim_attr->store ? hwsim_attr->store(data, buf, count) : EINVAL;
+}
+
+static struct configfs_item_operations mac80211_hwsim_item_ops = {
+	.release = mac80211_hwsim_release,
+	.show_attribute = mac80211_hwsim_attr_show,
+	.store_attribute = mac80211_hwsim_attr_store,
+};
+
+static struct config_item_type mac80211_hwsim_type = {
+	.ct_attrs = mac80211_hwsim_attrs,
+	.ct_item_ops = &mac80211_hwsim_item_ops,
+	.ct_owner = THIS_MODULE,
+};
+
+
+static struct config_item *make_mac80211_hwsim(struct config_group *group,
+					       const char *name)
+{
+	int err = 0;
 	u8 addr[ETH_ALEN];
 	struct mac80211_hwsim_data *data;
 	struct ieee80211_hw *hw;
 	DECLARE_MAC_BUF(mac);
 
-	if (radios < 1 || radios > 100)
-		return -EINVAL;
-
-	spin_lock_init(&hwsim_radio_lock);
-	INIT_LIST_HEAD(&hwsim_radios);
-
-	hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim");
-	if (IS_ERR(hwsim_class))
-		return PTR_ERR(hwsim_class);
-
 	memset(addr, 0, ETH_ALEN);
 	addr[0] = 0x02;
 
-	for (i = 0; i < radios; i++) {
-		printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n",
-		       i);
-		hw = ieee80211_alloc_hw(sizeof(*data), &mac80211_hwsim_ops);
-		if (!hw) {
-			printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw "
-			       "failed\n");
-			err = -ENOMEM;
+	printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n",
+		       radios);
+	hw = ieee80211_alloc_hw(sizeof(*data), &mac80211_hwsim_ops);
+	if (!hw) {
+		printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw "
+			"failed\n");
+		err = -ENOMEM;
 			goto failed;
-		}
-		data = hw->priv;
-		data->hw = hw;
+	}
+	data = hw->priv;
+	data->hw = hw;
 
-		data->dev = device_create(hwsim_class, NULL, 0, hw,
-					  "hwsim%d", i);
-		if (IS_ERR(data->dev)) {
-			printk(KERN_DEBUG
-			       "mac80211_hwsim: device_create "
-			       "failed (%ld)\n", PTR_ERR(data->dev));
-			err = -ENOMEM;
-			goto failed_drvdata;
-		}
-		data->dev->driver = &mac80211_hwsim_driver;
+	data->dev = device_create(hwsim_class, NULL, 0, hw,
+					  "hwsim%d", radios);
+	if (IS_ERR(data->dev)) {
+		printk(KERN_DEBUG
+			"mac80211_hwsim: device_create "
+			"failed (%ld)\n", PTR_ERR(data->dev));
+		err = -ENOMEM;
+		goto failed_drvdata;
+	}
+	data->dev->driver = &mac80211_hwsim_driver;
+
+	SET_IEEE80211_DEV(hw, data->dev);
+	addr[3] = radios >> 8;
+	addr[4] = radios;
+	SET_IEEE80211_PERM_ADDR(hw, addr);
+
+	hw->channel_change_time = 1;
+	hw->queues = 4;
+	hw->wiphy->interface_modes =
+		BIT(NL80211_IFTYPE_STATION) |
+		BIT(NL80211_IFTYPE_AP) |
+		BIT(NL80211_IFTYPE_MESH_POINT);
+	hw->ampdu_queues = 1;
+
+	/* ask mac80211 to reserve space for magic */
+	hw->vif_data_size = sizeof(struct hwsim_vif_priv);
+	hw->sta_data_size = sizeof(struct hwsim_sta_priv);
+
+	memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels));
+	memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates));
+	data->band.channels = data->channels;
+	data->band.n_channels = ARRAY_SIZE(hwsim_channels);
+	data->band.bitrates = data->rates;
+	data->band.n_bitrates = ARRAY_SIZE(hwsim_rates);
+	data->band.ht_cap.ht_supported = true;
+	data->band.ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+		IEEE80211_HT_CAP_GRN_FLD |
+		IEEE80211_HT_CAP_SGI_40 |
+		IEEE80211_HT_CAP_DSSSCCK40;
+	data->band.ht_cap.ampdu_factor = 0x3;
+	data->band.ht_cap.ampdu_density = 0x6;
+	memset(&data->band.ht_cap.mcs, 0,
+		  sizeof(data->band.ht_cap.mcs));
+	data->band.ht_cap.mcs.rx_mask[0] = 0xff;
+	data->band.ht_cap.mcs.rx_mask[1] = 0xff;
+	data->band.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+	hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band;
+
+	err = ieee80211_register_hw(hw);
+	if (err < 0) {
+		printk(KERN_DEBUG "mac80211_hwsim: "
+		      "ieee80211_register_hw failed (%d)\n", err);
+		goto failed_hw;
+	}
+
+	printk(KERN_DEBUG "%s: hwaddr %s registered\n",
+		  wiphy_name(hw->wiphy),
+		  print_mac(mac, hw->wiphy->perm_addr));
+
+	setup_timer(&data->beacon_timer, mac80211_hwsim_beacon,
+		   (unsigned long) hw);
 
-		SET_IEEE80211_DEV(hw, data->dev);
-		addr[3] = i >> 8;
-		addr[4] = i;
-		SET_IEEE80211_PERM_ADDR(hw, addr);
-
-		hw->channel_change_time = 1;
-		hw->queues = 4;
-		hw->wiphy->interface_modes =
-			BIT(NL80211_IFTYPE_STATION) |
-			BIT(NL80211_IFTYPE_AP) |
-			BIT(NL80211_IFTYPE_MESH_POINT);
-		hw->ampdu_queues = 1;
-
-		/* ask mac80211 to reserve space for magic */
-		hw->vif_data_size = sizeof(struct hwsim_vif_priv);
-		hw->sta_data_size = sizeof(struct hwsim_sta_priv);
-
-		memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels));
-		memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates));
-		data->band.channels = data->channels;
-		data->band.n_channels = ARRAY_SIZE(hwsim_channels);
-		data->band.bitrates = data->rates;
-		data->band.n_bitrates = ARRAY_SIZE(hwsim_rates);
-		data->band.ht_cap.ht_supported = true;
-		data->band.ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
-			IEEE80211_HT_CAP_GRN_FLD |
-			IEEE80211_HT_CAP_SGI_40 |
-			IEEE80211_HT_CAP_DSSSCCK40;
-		data->band.ht_cap.ampdu_factor = 0x3;
-		data->band.ht_cap.ampdu_density = 0x6;
-		memset(&data->band.ht_cap.mcs, 0,
-		       sizeof(data->band.ht_cap.mcs));
-		data->band.ht_cap.mcs.rx_mask[0] = 0xff;
-		data->band.ht_cap.mcs.rx_mask[1] = 0xff;
-		data->band.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
-		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band;
-
-		err = ieee80211_register_hw(hw);
-		if (err < 0) {
-			printk(KERN_DEBUG "mac80211_hwsim: "
-			       "ieee80211_register_hw failed (%d)\n", err);
-			goto failed_hw;
-		}
+	list_add_tail(&data->list, &hwsim_radios);
 
-		printk(KERN_DEBUG "%s: hwaddr %s registered\n",
-		       wiphy_name(hw->wiphy),
-		       print_mac(mac, hw->wiphy->perm_addr));
+	config_item_init_type_name(&data->item, name, &mac80211_hwsim_type);
+	radios++;
+
+	return &data->item;
+
+failed_hw:
+	device_unregister(data->dev);
+failed_drvdata:
+	ieee80211_free_hw(hw);
+failed:
+	mac80211_hwsim_free();
+	return ERR_PTR(err);
+
+}
+
+static void drop_mac80211_hwsim(struct config_group *group,
+                                   struct config_item *item)
+{
+	struct mac80211_hwsim_data *data = to_target(item);
+
+	spin_lock(&hwsim_radio_lock);
+	list_del(&data->list);
+	spin_unlock(&hwsim_radio_lock);
 
-		data->debugfs = debugfs_create_dir("hwsim",
-						   hw->wiphy->debugfsdir);
-		data->debugfs_ps = debugfs_create_file("ps", 0666,
-						       data->debugfs, data,
-						       &hwsim_fops_ps);
+	ieee80211_unregister_hw(data->hw);
+	device_unregister(data->dev);
+	ieee80211_free_hw(data->hw);
 
-		setup_timer(&data->beacon_timer, mac80211_hwsim_beacon,
-			    (unsigned long) hw);
+	config_item_put(&data->item);
+}
 
-		list_add_tail(&data->list, &hwsim_radios);
+static struct configfs_group_operations mac80211_hwsim_group_ops = {
+	.make_item = make_mac80211_hwsim,
+	.drop_item = drop_mac80211_hwsim,
+};
+
+static struct config_item_type mac80211_hwsim_subsys_type = {
+	.ct_group_ops = &mac80211_hwsim_group_ops,
+	.ct_owner = THIS_MODULE,
+};
+
+/*
+ *Mac80211_hwsim Subsystem definition
+ */
+
+static struct configfs_subsystem mac80211_hwsim_subsys = {
+	.su_group = {
+		.cg_item = {
+			.ci_namebuf = "mac80211_hwsim",
+			.ci_type = &mac80211_hwsim_subsys_type,
+		},
+	},
+};
+
+
+static int __init init_mac80211_hwsim(void)
+{
+	int err = 0;
+
+	spin_lock_init(&hwsim_radio_lock);
+	INIT_LIST_HEAD(&hwsim_radios);
+
+	hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim");
+	if (IS_ERR(hwsim_class))
+		return PTR_ERR(hwsim_class);
+
+	config_group_init(&mac80211_hwsim_subsys.su_group);
+	mutex_init(&mac80211_hwsim_subsys.su_mutex);
+	err = configfs_register_subsystem(&mac80211_hwsim_subsys);
+	if (err) {
+		printk(KERN_ERR "Error %d while registering mac80211_hwsim_subsystem %s\n",
+			err,
+			mac80211_hwsim_subsys.su_group.cg_item.ci_namebuf);
+		goto out_unregister;
 	}
 
 	hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup);
@@ -850,16 +977,16 @@ static int __init init_mac80211_hwsim(vo
 
 	return 0;
 
+out_unregister:
+	configfs_unregister_subsystem(&mac80211_hwsim_subsys);
+	return err;
+
 failed_mon:
 	rtnl_unlock();
 	free_netdev(hwsim_mon);
 	mac80211_hwsim_free();
 	return err;
 
-failed_hw:
-	device_unregister(data->dev);
-failed_drvdata:
-	ieee80211_free_hw(hw);
 failed:
 	mac80211_hwsim_free();
 	return err;
@@ -868,8 +995,9 @@ failed:
 
 static void __exit exit_mac80211_hwsim(void)
 {
-	printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n");
+	printk(KERN_DEBUG "mac80211_hwsim: unregister configfs subsystem\n");
 
+	configfs_unregister_subsystem(&mac80211_hwsim_subsys);
 	unregister_netdev(hwsim_mon);
 	mac80211_hwsim_free();
 }


      Veja quais são os assuntos do momento no Yahoo! +Buscados
http://br.maisbuscados.yahoo.com

--
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