aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mac80211_hwsim.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mac80211_hwsim.c')
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c211
1 files changed, 168 insertions, 43 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 248d31a7aa33..c9e4a435b2fc 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -14,6 +14,8 @@
14 * - RX filtering based on filter configuration (data->rx_filter) 14 * - RX filtering based on filter configuration (data->rx_filter)
15 */ 15 */
16 16
17#include <linux/list.h>
18#include <linux/spinlock.h>
17#include <net/mac80211.h> 19#include <net/mac80211.h>
18#include <net/ieee80211_radiotap.h> 20#include <net/ieee80211_radiotap.h>
19#include <linux/if_arp.h> 21#include <linux/if_arp.h>
@@ -28,11 +30,56 @@ static int radios = 2;
28module_param(radios, int, 0444); 30module_param(radios, int, 0444);
29MODULE_PARM_DESC(radios, "Number of simulated radios"); 31MODULE_PARM_DESC(radios, "Number of simulated radios");
30 32
33struct hwsim_vif_priv {
34 u32 magic;
35};
36
37#define HWSIM_VIF_MAGIC 0x69537748
38
39static inline void hwsim_check_magic(struct ieee80211_vif *vif)
40{
41 struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
42 WARN_ON(vp->magic != HWSIM_VIF_MAGIC);
43}
44
45static inline void hwsim_set_magic(struct ieee80211_vif *vif)
46{
47 struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
48 vp->magic = HWSIM_VIF_MAGIC;
49}
50
51static inline void hwsim_clear_magic(struct ieee80211_vif *vif)
52{
53 struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
54 vp->magic = 0;
55}
56
57struct hwsim_sta_priv {
58 u32 magic;
59};
60
61#define HWSIM_STA_MAGIC 0x6d537748
62
63static inline void hwsim_check_sta_magic(struct ieee80211_sta *sta)
64{
65 struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
66 WARN_ON(sp->magic != HWSIM_VIF_MAGIC);
67}
68
69static inline void hwsim_set_sta_magic(struct ieee80211_sta *sta)
70{
71 struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
72 sp->magic = HWSIM_VIF_MAGIC;
73}
74
75static inline void hwsim_clear_sta_magic(struct ieee80211_sta *sta)
76{
77 struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
78 sp->magic = 0;
79}
31 80
32static struct class *hwsim_class; 81static struct class *hwsim_class;
33 82
34static struct ieee80211_hw **hwsim_radios;
35static int hwsim_radio_count;
36static struct net_device *hwsim_mon; /* global monitor netdev */ 83static struct net_device *hwsim_mon; /* global monitor netdev */
37 84
38 85
@@ -68,7 +115,12 @@ static const struct ieee80211_rate hwsim_rates[] = {
68 { .bitrate = 540 } 115 { .bitrate = 540 }
69}; 116};
70 117
118static spinlock_t hwsim_radio_lock;
119static struct list_head hwsim_radios;
120
71struct mac80211_hwsim_data { 121struct mac80211_hwsim_data {
122 struct list_head list;
123 struct ieee80211_hw *hw;
72 struct device *dev; 124 struct device *dev;
73 struct ieee80211_supported_band band; 125 struct ieee80211_supported_band band;
74 struct ieee80211_channel channels[ARRAY_SIZE(hwsim_channels)]; 126 struct ieee80211_channel channels[ARRAY_SIZE(hwsim_channels)];
@@ -144,11 +196,11 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
144} 196}
145 197
146 198
147static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, 199static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
148 struct sk_buff *skb) 200 struct sk_buff *skb)
149{ 201{
150 struct mac80211_hwsim_data *data = hw->priv; 202 struct mac80211_hwsim_data *data = hw->priv, *data2;
151 int i, ack = 0; 203 bool ack = false;
152 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 204 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
153 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 205 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
154 struct ieee80211_rx_status rx_status; 206 struct ieee80211_rx_status rx_status;
@@ -161,13 +213,13 @@ static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
161 /* TODO: simulate signal strength (and optional packet drop) */ 213 /* TODO: simulate signal strength (and optional packet drop) */
162 214
163 /* Copy skb to all enabled radios that are on the current frequency */ 215 /* Copy skb to all enabled radios that are on the current frequency */
164 for (i = 0; i < hwsim_radio_count; i++) { 216 spin_lock(&hwsim_radio_lock);
165 struct mac80211_hwsim_data *data2; 217 list_for_each_entry(data2, &hwsim_radios, list) {
166 struct sk_buff *nskb; 218 struct sk_buff *nskb;
167 219
168 if (hwsim_radios[i] == NULL || hwsim_radios[i] == hw) 220 if (data == data2)
169 continue; 221 continue;
170 data2 = hwsim_radios[i]->priv; 222
171 if (!data2->started || !data2->radio_enabled || 223 if (!data2->started || !data2->radio_enabled ||
172 data->channel->center_freq != data2->channel->center_freq) 224 data->channel->center_freq != data2->channel->center_freq)
173 continue; 225 continue;
@@ -176,11 +228,12 @@ static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
176 if (nskb == NULL) 228 if (nskb == NULL)
177 continue; 229 continue;
178 230
179 if (memcmp(hdr->addr1, hwsim_radios[i]->wiphy->perm_addr, 231 if (memcmp(hdr->addr1, data2->hw->wiphy->perm_addr,
180 ETH_ALEN) == 0) 232 ETH_ALEN) == 0)
181 ack = 1; 233 ack = true;
182 ieee80211_rx_irqsafe(hwsim_radios[i], nskb, &rx_status); 234 ieee80211_rx_irqsafe(data2->hw, nskb, &rx_status);
183 } 235 }
236 spin_unlock(&hwsim_radio_lock);
184 237
185 return ack; 238 return ack;
186} 239}
@@ -189,7 +242,7 @@ static int mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
189static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) 242static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
190{ 243{
191 struct mac80211_hwsim_data *data = hw->priv; 244 struct mac80211_hwsim_data *data = hw->priv;
192 int ack; 245 bool ack;
193 struct ieee80211_tx_info *txi; 246 struct ieee80211_tx_info *txi;
194 247
195 mac80211_hwsim_monitor_rx(hw, skb); 248 mac80211_hwsim_monitor_rx(hw, skb);
@@ -210,6 +263,12 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
210 ack = mac80211_hwsim_tx_frame(hw, skb); 263 ack = mac80211_hwsim_tx_frame(hw, skb);
211 264
212 txi = IEEE80211_SKB_CB(skb); 265 txi = IEEE80211_SKB_CB(skb);
266
267 if (txi->control.vif)
268 hwsim_check_magic(txi->control.vif);
269 if (txi->control.sta)
270 hwsim_check_sta_magic(txi->control.sta);
271
213 memset(&txi->status, 0, sizeof(txi->status)); 272 memset(&txi->status, 0, sizeof(txi->status));
214 if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) { 273 if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) {
215 if (ack) 274 if (ack)
@@ -246,6 +305,7 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
246 printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n", 305 printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n",
247 wiphy_name(hw->wiphy), __func__, conf->type, 306 wiphy_name(hw->wiphy), __func__, conf->type,
248 print_mac(mac, conf->mac_addr)); 307 print_mac(mac, conf->mac_addr));
308 hwsim_set_magic(conf->vif);
249 return 0; 309 return 0;
250} 310}
251 311
@@ -257,6 +317,8 @@ static void mac80211_hwsim_remove_interface(
257 printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n", 317 printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n",
258 wiphy_name(hw->wiphy), __func__, conf->type, 318 wiphy_name(hw->wiphy), __func__, conf->type,
259 print_mac(mac, conf->mac_addr)); 319 print_mac(mac, conf->mac_addr));
320 hwsim_check_magic(conf->vif);
321 hwsim_clear_magic(conf->vif);
260} 322}
261 323
262 324
@@ -267,7 +329,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
267 struct sk_buff *skb; 329 struct sk_buff *skb;
268 struct ieee80211_tx_info *info; 330 struct ieee80211_tx_info *info;
269 331
270 if (vif->type != IEEE80211_IF_TYPE_AP) 332 hwsim_check_magic(vif);
333
334 if (vif->type != NL80211_IFTYPE_AP)
271 return; 335 return;
272 336
273 skb = ieee80211_beacon_get(hw, vif); 337 skb = ieee80211_beacon_get(hw, vif);
@@ -341,7 +405,45 @@ static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw,
341 *total_flags = data->rx_filter; 405 *total_flags = data->rx_filter;
342} 406}
343 407
408static int mac80211_hwsim_config_interface(struct ieee80211_hw *hw,
409 struct ieee80211_vif *vif,
410 struct ieee80211_if_conf *conf)
411{
412 hwsim_check_magic(vif);
413 return 0;
414}
415
416static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
417 struct ieee80211_vif *vif,
418 struct ieee80211_bss_conf *info,
419 u32 changed)
420{
421 hwsim_check_magic(vif);
422}
423
424static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw,
425 struct ieee80211_vif *vif,
426 enum sta_notify_cmd cmd,
427 struct ieee80211_sta *sta)
428{
429 hwsim_check_magic(vif);
430 switch (cmd) {
431 case STA_NOTIFY_ADD:
432 hwsim_set_sta_magic(sta);
433 break;
434 case STA_NOTIFY_REMOVE:
435 hwsim_clear_sta_magic(sta);
436 break;
437 }
438}
344 439
440static int mac80211_hwsim_set_tim(struct ieee80211_hw *hw,
441 struct ieee80211_sta *sta,
442 bool set)
443{
444 hwsim_check_sta_magic(sta);
445 return 0;
446}
345 447
346static const struct ieee80211_ops mac80211_hwsim_ops = 448static const struct ieee80211_ops mac80211_hwsim_ops =
347{ 449{
@@ -352,23 +454,30 @@ static const struct ieee80211_ops mac80211_hwsim_ops =
352 .remove_interface = mac80211_hwsim_remove_interface, 454 .remove_interface = mac80211_hwsim_remove_interface,
353 .config = mac80211_hwsim_config, 455 .config = mac80211_hwsim_config,
354 .configure_filter = mac80211_hwsim_configure_filter, 456 .configure_filter = mac80211_hwsim_configure_filter,
457 .config_interface = mac80211_hwsim_config_interface,
458 .bss_info_changed = mac80211_hwsim_bss_info_changed,
459 .sta_notify = mac80211_hwsim_sta_notify,
460 .set_tim = mac80211_hwsim_set_tim,
355}; 461};
356 462
357 463
358static void mac80211_hwsim_free(void) 464static void mac80211_hwsim_free(void)
359{ 465{
360 int i; 466 struct list_head tmplist, *i, *tmp;
361 467 struct mac80211_hwsim_data *data;
362 for (i = 0; i < hwsim_radio_count; i++) { 468
363 if (hwsim_radios[i]) { 469 INIT_LIST_HEAD(&tmplist);
364 struct mac80211_hwsim_data *data; 470
365 data = hwsim_radios[i]->priv; 471 spin_lock_bh(&hwsim_radio_lock);
366 ieee80211_unregister_hw(hwsim_radios[i]); 472 list_for_each_safe(i, tmp, &hwsim_radios)
367 device_unregister(data->dev); 473 list_move(i, &tmplist);
368 ieee80211_free_hw(hwsim_radios[i]); 474 spin_unlock_bh(&hwsim_radio_lock);
369 } 475
476 list_for_each_entry(data, &tmplist, list) {
477 ieee80211_unregister_hw(data->hw);
478 device_unregister(data->dev);
479 ieee80211_free_hw(data->hw);
370 } 480 }
371 kfree(hwsim_radios);
372 class_destroy(hwsim_class); 481 class_destroy(hwsim_class);
373} 482}
374 483
@@ -398,37 +507,32 @@ static int __init init_mac80211_hwsim(void)
398 struct ieee80211_hw *hw; 507 struct ieee80211_hw *hw;
399 DECLARE_MAC_BUF(mac); 508 DECLARE_MAC_BUF(mac);
400 509
401 if (radios < 1 || radios > 65535) 510 if (radios < 1 || radios > 100)
402 return -EINVAL; 511 return -EINVAL;
403 512
404 hwsim_radio_count = radios; 513 spin_lock_init(&hwsim_radio_lock);
405 hwsim_radios = kcalloc(hwsim_radio_count, 514 INIT_LIST_HEAD(&hwsim_radios);
406 sizeof(struct ieee80211_hw *), GFP_KERNEL);
407 if (hwsim_radios == NULL)
408 return -ENOMEM;
409 515
410 hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim"); 516 hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim");
411 if (IS_ERR(hwsim_class)) { 517 if (IS_ERR(hwsim_class))
412 kfree(hwsim_radios);
413 return PTR_ERR(hwsim_class); 518 return PTR_ERR(hwsim_class);
414 }
415 519
416 memset(addr, 0, ETH_ALEN); 520 memset(addr, 0, ETH_ALEN);
417 addr[0] = 0x02; 521 addr[0] = 0x02;
418 522
419 for (i = 0; i < hwsim_radio_count; i++) { 523 for (i = 0; i < radios; i++) {
420 printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n", 524 printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n",
421 i); 525 i);
422 hw = ieee80211_alloc_hw(sizeof(*data), &mac80211_hwsim_ops); 526 hw = ieee80211_alloc_hw(sizeof(*data), &mac80211_hwsim_ops);
423 if (hw == NULL) { 527 if (!hw) {
424 printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw " 528 printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw "
425 "failed\n"); 529 "failed\n");
426 err = -ENOMEM; 530 err = -ENOMEM;
427 goto failed; 531 goto failed;
428 } 532 }
429 hwsim_radios[i] = hw;
430
431 data = hw->priv; 533 data = hw->priv;
534 data->hw = hw;
535
432 data->dev = device_create_drvdata(hwsim_class, NULL, 0, hw, 536 data->dev = device_create_drvdata(hwsim_class, NULL, 0, hw,
433 "hwsim%d", i); 537 "hwsim%d", i);
434 if (IS_ERR(data->dev)) { 538 if (IS_ERR(data->dev)) {
@@ -446,7 +550,15 @@ static int __init init_mac80211_hwsim(void)
446 SET_IEEE80211_PERM_ADDR(hw, addr); 550 SET_IEEE80211_PERM_ADDR(hw, addr);
447 551
448 hw->channel_change_time = 1; 552 hw->channel_change_time = 1;
449 hw->queues = 1; 553 hw->queues = 4;
554 hw->wiphy->interface_modes =
555 BIT(NL80211_IFTYPE_STATION) |
556 BIT(NL80211_IFTYPE_AP);
557 hw->ampdu_queues = 1;
558
559 /* ask mac80211 to reserve space for magic */
560 hw->vif_data_size = sizeof(struct hwsim_vif_priv);
561 hw->sta_data_size = sizeof(struct hwsim_sta_priv);
450 562
451 memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels)); 563 memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels));
452 memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); 564 memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates));
@@ -454,6 +566,19 @@ static int __init init_mac80211_hwsim(void)
454 data->band.n_channels = ARRAY_SIZE(hwsim_channels); 566 data->band.n_channels = ARRAY_SIZE(hwsim_channels);
455 data->band.bitrates = data->rates; 567 data->band.bitrates = data->rates;
456 data->band.n_bitrates = ARRAY_SIZE(hwsim_rates); 568 data->band.n_bitrates = ARRAY_SIZE(hwsim_rates);
569 data->band.ht_info.ht_supported = 1;
570 data->band.ht_info.cap = IEEE80211_HT_CAP_SUP_WIDTH |
571 IEEE80211_HT_CAP_GRN_FLD |
572 IEEE80211_HT_CAP_SGI_40 |
573 IEEE80211_HT_CAP_DSSSCCK40;
574 data->band.ht_info.ampdu_factor = 0x3;
575 data->band.ht_info.ampdu_density = 0x6;
576 memset(data->band.ht_info.supp_mcs_set, 0,
577 sizeof(data->band.ht_info.supp_mcs_set));
578 data->band.ht_info.supp_mcs_set[0] = 0xff;
579 data->band.ht_info.supp_mcs_set[1] = 0xff;
580 data->band.ht_info.supp_mcs_set[12] =
581 IEEE80211_HT_CAP_MCS_TX_DEFINED;
457 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band; 582 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band;
458 583
459 err = ieee80211_register_hw(hw); 584 err = ieee80211_register_hw(hw);
@@ -469,6 +594,8 @@ static int __init init_mac80211_hwsim(void)
469 594
470 setup_timer(&data->beacon_timer, mac80211_hwsim_beacon, 595 setup_timer(&data->beacon_timer, mac80211_hwsim_beacon,
471 (unsigned long) hw); 596 (unsigned long) hw);
597
598 list_add_tail(&data->list, &hwsim_radios);
472 } 599 }
473 600
474 hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup); 601 hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup);
@@ -500,7 +627,6 @@ failed_hw:
500 device_unregister(data->dev); 627 device_unregister(data->dev);
501failed_drvdata: 628failed_drvdata:
502 ieee80211_free_hw(hw); 629 ieee80211_free_hw(hw);
503 hwsim_radios[i] = NULL;
504failed: 630failed:
505 mac80211_hwsim_free(); 631 mac80211_hwsim_free();
506 return err; 632 return err;
@@ -509,8 +635,7 @@ failed:
509 635
510static void __exit exit_mac80211_hwsim(void) 636static void __exit exit_mac80211_hwsim(void)
511{ 637{
512 printk(KERN_DEBUG "mac80211_hwsim: unregister %d radios\n", 638 printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n");
513 hwsim_radio_count);
514 639
515 unregister_netdev(hwsim_mon); 640 unregister_netdev(hwsim_mon);
516 mac80211_hwsim_free(); 641 mac80211_hwsim_free();