diff options
author | Johannes Berg <johannes.berg@intel.com> | 2014-01-10 07:37:38 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-01-10 14:12:59 -0500 |
commit | 26b0e411d37a2ca5992d02884dc3fa4e1907e598 (patch) | |
tree | 2fffe6b38d20c7199f2dbf638910215624b33137 | |
parent | bc7910989601fbde02b3dd485d595a614d21ef1e (diff) |
mac80211_hwsim: restore regulatory testing functionality
Restore the original regulatory testing functionality and also
make it more flexible by allowing the parameters to be specified
when creating a dynamic radio.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 218 | ||||
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.h | 7 |
2 files changed, 222 insertions, 3 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 056dae73b25c..dc7f72e3a4e7 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -57,6 +57,117 @@ static bool rctbl = false; | |||
57 | module_param(rctbl, bool, 0444); | 57 | module_param(rctbl, bool, 0444); |
58 | MODULE_PARM_DESC(rctbl, "Handle rate control table"); | 58 | MODULE_PARM_DESC(rctbl, "Handle rate control table"); |
59 | 59 | ||
60 | /** | ||
61 | * enum hwsim_regtest - the type of regulatory tests we offer | ||
62 | * | ||
63 | * These are the different values you can use for the regtest | ||
64 | * module parameter. This is useful to help test world roaming | ||
65 | * and the driver regulatory_hint() call and combinations of these. | ||
66 | * If you want to do specific alpha2 regulatory domain tests simply | ||
67 | * use the userspace regulatory request as that will be respected as | ||
68 | * well without the need of this module parameter. This is designed | ||
69 | * only for testing the driver regulatory request, world roaming | ||
70 | * and all possible combinations. | ||
71 | * | ||
72 | * @HWSIM_REGTEST_DISABLED: No regulatory tests are performed, | ||
73 | * this is the default value. | ||
74 | * @HWSIM_REGTEST_DRIVER_REG_FOLLOW: Used for testing the driver regulatory | ||
75 | * hint, only one driver regulatory hint will be sent as such the | ||
76 | * secondary radios are expected to follow. | ||
77 | * @HWSIM_REGTEST_DRIVER_REG_ALL: Used for testing the driver regulatory | ||
78 | * request with all radios reporting the same regulatory domain. | ||
79 | * @HWSIM_REGTEST_DIFF_COUNTRY: Used for testing the drivers calling | ||
80 | * different regulatory domains requests. Expected behaviour is for | ||
81 | * an intersection to occur but each device will still use their | ||
82 | * respective regulatory requested domains. Subsequent radios will | ||
83 | * use the resulting intersection. | ||
84 | * @HWSIM_REGTEST_WORLD_ROAM: Used for testing the world roaming. We accomplish | ||
85 | * this by using a custom beacon-capable regulatory domain for the first | ||
86 | * radio. All other device world roam. | ||
87 | * @HWSIM_REGTEST_CUSTOM_WORLD: Used for testing the custom world regulatory | ||
88 | * domain requests. All radios will adhere to this custom world regulatory | ||
89 | * domain. | ||
90 | * @HWSIM_REGTEST_CUSTOM_WORLD_2: Used for testing 2 custom world regulatory | ||
91 | * domain requests. The first radio will adhere to the first custom world | ||
92 | * regulatory domain, the second one to the second custom world regulatory | ||
93 | * domain. All other devices will world roam. | ||
94 | * @HWSIM_REGTEST_STRICT_FOLLOW_: Used for testing strict regulatory domain | ||
95 | * settings, only the first radio will send a regulatory domain request | ||
96 | * and use strict settings. The rest of the radios are expected to follow. | ||
97 | * @HWSIM_REGTEST_STRICT_ALL: Used for testing strict regulatory domain | ||
98 | * settings. All radios will adhere to this. | ||
99 | * @HWSIM_REGTEST_STRICT_AND_DRIVER_REG: Used for testing strict regulatory | ||
100 | * domain settings, combined with secondary driver regulatory domain | ||
101 | * settings. The first radio will get a strict regulatory domain setting | ||
102 | * using the first driver regulatory request and the second radio will use | ||
103 | * non-strict settings using the second driver regulatory request. All | ||
104 | * other devices should follow the intersection created between the | ||
105 | * first two. | ||
106 | * @HWSIM_REGTEST_ALL: Used for testing every possible mix. You will need | ||
107 | * at least 6 radios for a complete test. We will test in this order: | ||
108 | * 1 - driver custom world regulatory domain | ||
109 | * 2 - second custom world regulatory domain | ||
110 | * 3 - first driver regulatory domain request | ||
111 | * 4 - second driver regulatory domain request | ||
112 | * 5 - strict regulatory domain settings using the third driver regulatory | ||
113 | * domain request | ||
114 | * 6 and on - should follow the intersection of the 3rd, 4rth and 5th radio | ||
115 | * regulatory requests. | ||
116 | */ | ||
117 | enum hwsim_regtest { | ||
118 | HWSIM_REGTEST_DISABLED = 0, | ||
119 | HWSIM_REGTEST_DRIVER_REG_FOLLOW = 1, | ||
120 | HWSIM_REGTEST_DRIVER_REG_ALL = 2, | ||
121 | HWSIM_REGTEST_DIFF_COUNTRY = 3, | ||
122 | HWSIM_REGTEST_WORLD_ROAM = 4, | ||
123 | HWSIM_REGTEST_CUSTOM_WORLD = 5, | ||
124 | HWSIM_REGTEST_CUSTOM_WORLD_2 = 6, | ||
125 | HWSIM_REGTEST_STRICT_FOLLOW = 7, | ||
126 | HWSIM_REGTEST_STRICT_ALL = 8, | ||
127 | HWSIM_REGTEST_STRICT_AND_DRIVER_REG = 9, | ||
128 | HWSIM_REGTEST_ALL = 10, | ||
129 | }; | ||
130 | |||
131 | /* Set to one of the HWSIM_REGTEST_* values above */ | ||
132 | static int regtest = HWSIM_REGTEST_DISABLED; | ||
133 | module_param(regtest, int, 0444); | ||
134 | MODULE_PARM_DESC(regtest, "The type of regulatory test we want to run"); | ||
135 | |||
136 | static const char *hwsim_alpha2s[] = { | ||
137 | "FI", | ||
138 | "AL", | ||
139 | "US", | ||
140 | "DE", | ||
141 | "JP", | ||
142 | "AL", | ||
143 | }; | ||
144 | |||
145 | static const struct ieee80211_regdomain hwsim_world_regdom_custom_01 = { | ||
146 | .n_reg_rules = 4, | ||
147 | .alpha2 = "99", | ||
148 | .reg_rules = { | ||
149 | REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), | ||
150 | REG_RULE(2484-10, 2484+10, 40, 0, 20, 0), | ||
151 | REG_RULE(5150-10, 5240+10, 40, 0, 30, 0), | ||
152 | REG_RULE(5745-10, 5825+10, 40, 0, 30, 0), | ||
153 | } | ||
154 | }; | ||
155 | |||
156 | static const struct ieee80211_regdomain hwsim_world_regdom_custom_02 = { | ||
157 | .n_reg_rules = 2, | ||
158 | .alpha2 = "99", | ||
159 | .reg_rules = { | ||
160 | REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), | ||
161 | REG_RULE(5725-10, 5850+10, 40, 0, 30, | ||
162 | NL80211_RRF_NO_IR), | ||
163 | } | ||
164 | }; | ||
165 | |||
166 | static const struct ieee80211_regdomain *hwsim_world_regdom_custom[] = { | ||
167 | &hwsim_world_regdom_custom_01, | ||
168 | &hwsim_world_regdom_custom_02, | ||
169 | }; | ||
170 | |||
60 | struct hwsim_vif_priv { | 171 | struct hwsim_vif_priv { |
61 | u32 magic; | 172 | u32 magic; |
62 | u8 bssid[ETH_ALEN]; | 173 | u8 bssid[ETH_ALEN]; |
@@ -354,6 +465,9 @@ static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { | |||
354 | [HWSIM_ATTR_COOKIE] = { .type = NLA_U64 }, | 465 | [HWSIM_ATTR_COOKIE] = { .type = NLA_U64 }, |
355 | [HWSIM_ATTR_CHANNELS] = { .type = NLA_U32 }, | 466 | [HWSIM_ATTR_CHANNELS] = { .type = NLA_U32 }, |
356 | [HWSIM_ATTR_RADIO_ID] = { .type = NLA_U32 }, | 467 | [HWSIM_ATTR_RADIO_ID] = { .type = NLA_U32 }, |
468 | [HWSIM_ATTR_REG_HINT_ALPHA2] = { .type = NLA_STRING, .len = 2 }, | ||
469 | [HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 }, | ||
470 | [HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG }, | ||
357 | }; | 471 | }; |
358 | 472 | ||
359 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | 473 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, |
@@ -1820,7 +1934,9 @@ static const struct ieee80211_ops mac80211_hwsim_ops = { | |||
1820 | 1934 | ||
1821 | static struct ieee80211_ops mac80211_hwsim_mchan_ops; | 1935 | static struct ieee80211_ops mac80211_hwsim_mchan_ops; |
1822 | 1936 | ||
1823 | static int mac80211_hwsim_create_radio(int channels) | 1937 | static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, |
1938 | const struct ieee80211_regdomain *regd, | ||
1939 | bool reg_strict) | ||
1824 | { | 1940 | { |
1825 | int err; | 1941 | int err; |
1826 | u8 addr[ETH_ALEN]; | 1942 | u8 addr[ETH_ALEN]; |
@@ -2000,6 +2116,15 @@ static int mac80211_hwsim_create_radio(int channels) | |||
2000 | hw->max_rates = 4; | 2116 | hw->max_rates = 4; |
2001 | hw->max_rate_tries = 11; | 2117 | hw->max_rate_tries = 11; |
2002 | 2118 | ||
2119 | if (reg_strict) | ||
2120 | hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG; | ||
2121 | if (regd) { | ||
2122 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; | ||
2123 | wiphy_apply_custom_regulatory(hw->wiphy, regd); | ||
2124 | /* give the regulatory workqueue a chance to run */ | ||
2125 | schedule_timeout_interruptible(1); | ||
2126 | } | ||
2127 | |||
2003 | err = ieee80211_register_hw(hw); | 2128 | err = ieee80211_register_hw(hw); |
2004 | if (err < 0) { | 2129 | if (err < 0) { |
2005 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n", | 2130 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n", |
@@ -2009,6 +2134,9 @@ static int mac80211_hwsim_create_radio(int channels) | |||
2009 | 2134 | ||
2010 | wiphy_debug(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr); | 2135 | wiphy_debug(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr); |
2011 | 2136 | ||
2137 | if (reg_alpha2) | ||
2138 | regulatory_hint(hw->wiphy, reg_alpha2); | ||
2139 | |||
2012 | data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir); | 2140 | data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir); |
2013 | debugfs_create_file("ps", 0666, data->debugfs, data, &hwsim_fops_ps); | 2141 | debugfs_create_file("ps", 0666, data->debugfs, data, &hwsim_fops_ps); |
2014 | debugfs_create_file("group", 0666, data->debugfs, data, | 2142 | debugfs_create_file("group", 0666, data->debugfs, data, |
@@ -2276,11 +2404,25 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2, | |||
2276 | static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info) | 2404 | static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info) |
2277 | { | 2405 | { |
2278 | unsigned int chans = channels; | 2406 | unsigned int chans = channels; |
2407 | const char *alpha2 = NULL; | ||
2408 | const struct ieee80211_regdomain *regd = NULL; | ||
2409 | bool reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; | ||
2279 | 2410 | ||
2280 | if (info->attrs[HWSIM_ATTR_CHANNELS]) | 2411 | if (info->attrs[HWSIM_ATTR_CHANNELS]) |
2281 | chans = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]); | 2412 | chans = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]); |
2282 | 2413 | ||
2283 | return mac80211_hwsim_create_radio(chans); | 2414 | if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]) |
2415 | alpha2 = nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]); | ||
2416 | |||
2417 | if (info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]) { | ||
2418 | u32 idx = nla_get_u32(info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]); | ||
2419 | |||
2420 | if (idx >= ARRAY_SIZE(hwsim_world_regdom_custom)) | ||
2421 | return -EINVAL; | ||
2422 | regd = hwsim_world_regdom_custom[idx]; | ||
2423 | } | ||
2424 | |||
2425 | return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict); | ||
2284 | } | 2426 | } |
2285 | 2427 | ||
2286 | static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info) | 2428 | static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info) |
@@ -2428,7 +2570,77 @@ static int __init init_mac80211_hwsim(void) | |||
2428 | } | 2570 | } |
2429 | 2571 | ||
2430 | for (i = 0; i < radios; i++) { | 2572 | for (i = 0; i < radios; i++) { |
2431 | err = mac80211_hwsim_create_radio(channels); | 2573 | const char *reg_alpha2 = NULL; |
2574 | const struct ieee80211_regdomain *regd = NULL; | ||
2575 | bool reg_strict = false; | ||
2576 | |||
2577 | switch (regtest) { | ||
2578 | case HWSIM_REGTEST_DIFF_COUNTRY: | ||
2579 | if (i < ARRAY_SIZE(hwsim_alpha2s)) | ||
2580 | reg_alpha2 = hwsim_alpha2s[i]; | ||
2581 | break; | ||
2582 | case HWSIM_REGTEST_DRIVER_REG_FOLLOW: | ||
2583 | if (!i) | ||
2584 | reg_alpha2 = hwsim_alpha2s[0]; | ||
2585 | break; | ||
2586 | case HWSIM_REGTEST_STRICT_ALL: | ||
2587 | reg_strict = true; | ||
2588 | case HWSIM_REGTEST_DRIVER_REG_ALL: | ||
2589 | reg_alpha2 = hwsim_alpha2s[0]; | ||
2590 | break; | ||
2591 | case HWSIM_REGTEST_WORLD_ROAM: | ||
2592 | if (i == 0) | ||
2593 | regd = &hwsim_world_regdom_custom_01; | ||
2594 | break; | ||
2595 | case HWSIM_REGTEST_CUSTOM_WORLD: | ||
2596 | regd = &hwsim_world_regdom_custom_01; | ||
2597 | break; | ||
2598 | case HWSIM_REGTEST_CUSTOM_WORLD_2: | ||
2599 | if (i == 0) | ||
2600 | regd = &hwsim_world_regdom_custom_01; | ||
2601 | else if (i == 1) | ||
2602 | regd = &hwsim_world_regdom_custom_02; | ||
2603 | break; | ||
2604 | case HWSIM_REGTEST_STRICT_FOLLOW: | ||
2605 | if (i == 0) { | ||
2606 | reg_strict = true; | ||
2607 | reg_alpha2 = hwsim_alpha2s[0]; | ||
2608 | } | ||
2609 | break; | ||
2610 | case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: | ||
2611 | if (i == 0) { | ||
2612 | reg_strict = true; | ||
2613 | reg_alpha2 = hwsim_alpha2s[0]; | ||
2614 | } else if (i == 1) { | ||
2615 | reg_alpha2 = hwsim_alpha2s[1]; | ||
2616 | } | ||
2617 | break; | ||
2618 | case HWSIM_REGTEST_ALL: | ||
2619 | switch (i) { | ||
2620 | case 0: | ||
2621 | regd = &hwsim_world_regdom_custom_01; | ||
2622 | break; | ||
2623 | case 1: | ||
2624 | regd = &hwsim_world_regdom_custom_02; | ||
2625 | break; | ||
2626 | case 2: | ||
2627 | reg_alpha2 = hwsim_alpha2s[0]; | ||
2628 | break; | ||
2629 | case 3: | ||
2630 | reg_alpha2 = hwsim_alpha2s[1]; | ||
2631 | break; | ||
2632 | case 4: | ||
2633 | reg_strict = true; | ||
2634 | reg_alpha2 = hwsim_alpha2s[2]; | ||
2635 | break; | ||
2636 | } | ||
2637 | break; | ||
2638 | default: | ||
2639 | break; | ||
2640 | } | ||
2641 | |||
2642 | err = mac80211_hwsim_create_radio(channels, reg_alpha2, | ||
2643 | regd, reg_strict); | ||
2432 | if (err < 0) | 2644 | if (err < 0) |
2433 | goto out_free_radios; | 2645 | goto out_free_radios; |
2434 | } | 2646 | } |
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h index fb9920a99396..2747cce5a269 100644 --- a/drivers/net/wireless/mac80211_hwsim.h +++ b/drivers/net/wireless/mac80211_hwsim.h | |||
@@ -103,6 +103,10 @@ enum { | |||
103 | * command giving the number of channels supported by the new radio | 103 | * command giving the number of channels supported by the new radio |
104 | * @HWSIM_ATTR_RADIO_ID: u32 attribute used with %HWSIM_CMD_DESTROY_RADIO | 104 | * @HWSIM_ATTR_RADIO_ID: u32 attribute used with %HWSIM_CMD_DESTROY_RADIO |
105 | * only to destroy a radio | 105 | * only to destroy a radio |
106 | * @HWSIM_ATTR_REG_HINT_ALPHA2: alpha2 for regulatoro driver hint | ||
107 | * (nla string, length 2) | ||
108 | * @HWSIM_ATTR_REG_CUSTOM_REG: custom regulatory domain index (u32 attribute) | ||
109 | * @HWSIM_ATTR_REG_STRICT_REG: request REGULATORY_STRICT_REG (flag attribute) | ||
106 | * @__HWSIM_ATTR_MAX: enum limit | 110 | * @__HWSIM_ATTR_MAX: enum limit |
107 | */ | 111 | */ |
108 | 112 | ||
@@ -119,6 +123,9 @@ enum { | |||
119 | HWSIM_ATTR_COOKIE, | 123 | HWSIM_ATTR_COOKIE, |
120 | HWSIM_ATTR_CHANNELS, | 124 | HWSIM_ATTR_CHANNELS, |
121 | HWSIM_ATTR_RADIO_ID, | 125 | HWSIM_ATTR_RADIO_ID, |
126 | HWSIM_ATTR_REG_HINT_ALPHA2, | ||
127 | HWSIM_ATTR_REG_CUSTOM_REG, | ||
128 | HWSIM_ATTR_REG_STRICT_REG, | ||
122 | __HWSIM_ATTR_MAX, | 129 | __HWSIM_ATTR_MAX, |
123 | }; | 130 | }; |
124 | #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) | 131 | #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) |