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