aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2014-01-06 17:29:20 -0500
committerJohannes Berg <johannes.berg@intel.com>2014-01-10 14:12:59 -0500
commitbc7910989601fbde02b3dd485d595a614d21ef1e (patch)
tree1f42c4c6259207f293f8ee0e7cee1bbee72b7c83
parentc5ac08548b53c3292aa3cbd02de6ae99ca7271e6 (diff)
mac80211_hwsim: allow creating/destroying radios on the fly
Add new commands to the hwsim generic netlink family to allow creating and destroying radios on the fly. The number of channels a radio supports can be specified when it's created, if it isn't the module parameter will be used as default. This should be extended in the future to allow other parameters to be specified, e.g. * list of channels * interface combinations, particularly P2P_DEVICE support * regtest * and pretty much all other hardware capabilities Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c60
-rw-r--r--drivers/net/wireless/mac80211_hwsim.h11
2 files changed, 65 insertions, 6 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 5bad3d4ccdba..056dae73b25c 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -273,7 +273,7 @@ struct mac80211_hwsim_data {
273 struct ieee80211_iface_combination if_combination; 273 struct ieee80211_iface_combination if_combination;
274 274
275 struct mac_address addresses[2]; 275 struct mac_address addresses[2];
276 int channels; 276 int channels, idx;
277 277
278 struct ieee80211_channel *tmp_chan; 278 struct ieee80211_channel *tmp_chan;
279 struct delayed_work roc_done; 279 struct delayed_work roc_done;
@@ -352,6 +352,8 @@ static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
352 .len = IEEE80211_TX_MAX_RATES * 352 .len = IEEE80211_TX_MAX_RATES *
353 sizeof(struct hwsim_tx_rate)}, 353 sizeof(struct hwsim_tx_rate)},
354 [HWSIM_ATTR_COOKIE] = { .type = NLA_U64 }, 354 [HWSIM_ATTR_COOKIE] = { .type = NLA_U64 },
355 [HWSIM_ATTR_CHANNELS] = { .type = NLA_U32 },
356 [HWSIM_ATTR_RADIO_ID] = { .type = NLA_U32 },
355}; 357};
356 358
357static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, 359static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
@@ -1818,7 +1820,7 @@ static const struct ieee80211_ops mac80211_hwsim_ops = {
1818 1820
1819static struct ieee80211_ops mac80211_hwsim_mchan_ops; 1821static struct ieee80211_ops mac80211_hwsim_mchan_ops;
1820 1822
1821static int __init mac80211_hwsim_create_radio(void) 1823static int mac80211_hwsim_create_radio(int channels)
1822{ 1824{
1823 int err; 1825 int err;
1824 u8 addr[ETH_ALEN]; 1826 u8 addr[ETH_ALEN];
@@ -1873,6 +1875,7 @@ static int __init mac80211_hwsim_create_radio(void)
1873 hw->wiphy->addresses = data->addresses; 1875 hw->wiphy->addresses = data->addresses;
1874 1876
1875 data->channels = channels; 1877 data->channels = channels;
1878 data->idx = idx;
1876 1879
1877 if (data->channels > 1) { 1880 if (data->channels > 1) {
1878 hw->wiphy->max_scan_ssids = 255; 1881 hw->wiphy->max_scan_ssids = 255;
@@ -2023,7 +2026,7 @@ static int __init mac80211_hwsim_create_radio(void)
2023 list_add_tail(&data->list, &hwsim_radios); 2026 list_add_tail(&data->list, &hwsim_radios);
2024 spin_unlock_bh(&hwsim_radio_lock); 2027 spin_unlock_bh(&hwsim_radio_lock);
2025 2028
2026 return 0; 2029 return idx;
2027 2030
2028failed_hw: 2031failed_hw:
2029 device_unregister(data->dev); 2032 device_unregister(data->dev);
@@ -2270,6 +2273,39 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2,
2270 return 0; 2273 return 0;
2271} 2274}
2272 2275
2276static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info)
2277{
2278 unsigned int chans = channels;
2279
2280 if (info->attrs[HWSIM_ATTR_CHANNELS])
2281 chans = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]);
2282
2283 return mac80211_hwsim_create_radio(chans);
2284}
2285
2286static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info)
2287{
2288 struct mac80211_hwsim_data *data;
2289 int idx;
2290
2291 if (!info->attrs[HWSIM_ATTR_RADIO_ID])
2292 return -EINVAL;
2293 idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]);
2294
2295 spin_lock_bh(&hwsim_radio_lock);
2296 list_for_each_entry(data, &hwsim_radios, list) {
2297 if (data->idx != idx)
2298 continue;
2299 list_del(&data->list);
2300 spin_unlock_bh(&hwsim_radio_lock);
2301 mac80211_hwsim_destroy_radio(data);
2302 return 0;
2303 }
2304 spin_unlock_bh(&hwsim_radio_lock);
2305
2306 return -ENODEV;
2307}
2308
2273/* Generic Netlink operations array */ 2309/* Generic Netlink operations array */
2274static const struct genl_ops hwsim_ops[] = { 2310static const struct genl_ops hwsim_ops[] = {
2275 { 2311 {
@@ -2288,6 +2324,18 @@ static const struct genl_ops hwsim_ops[] = {
2288 .policy = hwsim_genl_policy, 2324 .policy = hwsim_genl_policy,
2289 .doit = hwsim_tx_info_frame_received_nl, 2325 .doit = hwsim_tx_info_frame_received_nl,
2290 }, 2326 },
2327 {
2328 .cmd = HWSIM_CMD_CREATE_RADIO,
2329 .policy = hwsim_genl_policy,
2330 .doit = hwsim_create_radio_nl,
2331 .flags = GENL_ADMIN_PERM,
2332 },
2333 {
2334 .cmd = HWSIM_CMD_DESTROY_RADIO,
2335 .policy = hwsim_genl_policy,
2336 .doit = hwsim_destroy_radio_nl,
2337 .flags = GENL_ADMIN_PERM,
2338 },
2291}; 2339};
2292 2340
2293static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, 2341static int mac80211_hwsim_netlink_notify(struct notifier_block *nb,
@@ -2345,7 +2393,7 @@ static int __init init_mac80211_hwsim(void)
2345{ 2393{
2346 int i, err; 2394 int i, err;
2347 2395
2348 if (radios < 1 || radios > 100) 2396 if (radios < 0 || radios > 100)
2349 return -EINVAL; 2397 return -EINVAL;
2350 2398
2351 if (channels < 1) 2399 if (channels < 1)
@@ -2380,8 +2428,8 @@ static int __init init_mac80211_hwsim(void)
2380 } 2428 }
2381 2429
2382 for (i = 0; i < radios; i++) { 2430 for (i = 0; i < radios; i++) {
2383 err = mac80211_hwsim_create_radio(); 2431 err = mac80211_hwsim_create_radio(channels);
2384 if (err) 2432 if (err < 0)
2385 goto out_free_radios; 2433 goto out_free_radios;
2386 } 2434 }
2387 2435
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h
index afaad5a443b6..fb9920a99396 100644
--- a/drivers/net/wireless/mac80211_hwsim.h
+++ b/drivers/net/wireless/mac80211_hwsim.h
@@ -65,6 +65,9 @@ enum hwsim_tx_control_flags {
65 * kernel, uses: 65 * kernel, uses:
66 * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS, 66 * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS,
67 * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE 67 * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE
68 * @HWSIM_CMD_CREATE_RADIO: create a new radio with the given parameters,
69 * returns the radio ID (>= 0) or negative on errors
70 * @HWSIM_CMD_DESTROY_RADIO: destroy a radio
68 * @__HWSIM_CMD_MAX: enum limit 71 * @__HWSIM_CMD_MAX: enum limit
69 */ 72 */
70enum { 73enum {
@@ -72,6 +75,8 @@ enum {
72 HWSIM_CMD_REGISTER, 75 HWSIM_CMD_REGISTER,
73 HWSIM_CMD_FRAME, 76 HWSIM_CMD_FRAME,
74 HWSIM_CMD_TX_INFO_FRAME, 77 HWSIM_CMD_TX_INFO_FRAME,
78 HWSIM_CMD_CREATE_RADIO,
79 HWSIM_CMD_DESTROY_RADIO,
75 __HWSIM_CMD_MAX, 80 __HWSIM_CMD_MAX,
76}; 81};
77#define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1) 82#define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1)
@@ -94,6 +99,10 @@ enum {
94 space 99 space
95 * @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array 100 * @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array
96 * @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame 101 * @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame
102 * @HWSIM_ATTR_CHANNELS: u32 attribute used with the %HWSIM_CMD_CREATE_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
105 * only to destroy a radio
97 * @__HWSIM_ATTR_MAX: enum limit 106 * @__HWSIM_ATTR_MAX: enum limit
98 */ 107 */
99 108
@@ -108,6 +117,8 @@ enum {
108 HWSIM_ATTR_SIGNAL, 117 HWSIM_ATTR_SIGNAL,
109 HWSIM_ATTR_TX_INFO, 118 HWSIM_ATTR_TX_INFO,
110 HWSIM_ATTR_COOKIE, 119 HWSIM_ATTR_COOKIE,
120 HWSIM_ATTR_CHANNELS,
121 HWSIM_ATTR_RADIO_ID,
111 __HWSIM_ATTR_MAX, 122 __HWSIM_ATTR_MAX,
112}; 123};
113#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) 124#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)