diff options
Diffstat (limited to 'drivers/net/wireless/mac80211_hwsim.c')
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 57 |
1 files changed, 37 insertions, 20 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 86fa8abdd66f..9d4a40ee16c4 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -9,7 +9,8 @@ | |||
9 | 9 | ||
10 | /* | 10 | /* |
11 | * TODO: | 11 | * TODO: |
12 | * - IBSS mode simulation (Beacon transmission with competition for "air time") | 12 | * - Add TSF sync and fix IBSS beacon transmission by adding |
13 | * competition for "air time" at TBTT | ||
13 | * - RX filtering based on filter configuration (data->rx_filter) | 14 | * - RX filtering based on filter configuration (data->rx_filter) |
14 | */ | 15 | */ |
15 | 16 | ||
@@ -61,7 +62,7 @@ MODULE_PARM_DESC(fake_hw_scan, "Install fake (no-op) hw-scan handler"); | |||
61 | * an intersection to occur but each device will still use their | 62 | * an intersection to occur but each device will still use their |
62 | * respective regulatory requested domains. Subsequent radios will | 63 | * respective regulatory requested domains. Subsequent radios will |
63 | * use the resulting intersection. | 64 | * use the resulting intersection. |
64 | * @HWSIM_REGTEST_WORLD_ROAM: Used for testing the world roaming. We acomplish | 65 | * @HWSIM_REGTEST_WORLD_ROAM: Used for testing the world roaming. We accomplish |
65 | * this by using a custom beacon-capable regulatory domain for the first | 66 | * this by using a custom beacon-capable regulatory domain for the first |
66 | * radio. All other device world roam. | 67 | * radio. All other device world roam. |
67 | * @HWSIM_REGTEST_CUSTOM_WORLD: Used for testing the custom world regulatory | 68 | * @HWSIM_REGTEST_CUSTOM_WORLD: Used for testing the custom world regulatory |
@@ -308,6 +309,8 @@ struct mac80211_hwsim_data { | |||
308 | */ | 309 | */ |
309 | u64 group; | 310 | u64 group; |
310 | struct dentry *debugfs_group; | 311 | struct dentry *debugfs_group; |
312 | |||
313 | int power_level; | ||
311 | }; | 314 | }; |
312 | 315 | ||
313 | 316 | ||
@@ -496,7 +499,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | |||
496 | rx_status.band = data->channel->band; | 499 | rx_status.band = data->channel->band; |
497 | rx_status.rate_idx = info->control.rates[0].idx; | 500 | rx_status.rate_idx = info->control.rates[0].idx; |
498 | /* TODO: simulate real signal strength (and optional packet loss) */ | 501 | /* TODO: simulate real signal strength (and optional packet loss) */ |
499 | rx_status.signal = -50; | 502 | rx_status.signal = data->power_level - 50; |
500 | 503 | ||
501 | if (data->ps != PS_DISABLED) | 504 | if (data->ps != PS_DISABLED) |
502 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); | 505 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); |
@@ -538,7 +541,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | |||
538 | } | 541 | } |
539 | 542 | ||
540 | 543 | ||
541 | static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 544 | static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
542 | { | 545 | { |
543 | bool ack; | 546 | bool ack; |
544 | struct ieee80211_tx_info *txi; | 547 | struct ieee80211_tx_info *txi; |
@@ -548,7 +551,7 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
548 | if (skb->len < 10) { | 551 | if (skb->len < 10) { |
549 | /* Should not happen; just a sanity check for addr1 use */ | 552 | /* Should not happen; just a sanity check for addr1 use */ |
550 | dev_kfree_skb(skb); | 553 | dev_kfree_skb(skb); |
551 | return NETDEV_TX_OK; | 554 | return; |
552 | } | 555 | } |
553 | 556 | ||
554 | ack = mac80211_hwsim_tx_frame(hw, skb); | 557 | ack = mac80211_hwsim_tx_frame(hw, skb); |
@@ -568,7 +571,6 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
568 | if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack) | 571 | if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack) |
569 | txi->flags |= IEEE80211_TX_STAT_ACK; | 572 | txi->flags |= IEEE80211_TX_STAT_ACK; |
570 | ieee80211_tx_status_irqsafe(hw, skb); | 573 | ieee80211_tx_status_irqsafe(hw, skb); |
571 | return NETDEV_TX_OK; | ||
572 | } | 574 | } |
573 | 575 | ||
574 | 576 | ||
@@ -594,17 +596,34 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, | |||
594 | struct ieee80211_vif *vif) | 596 | struct ieee80211_vif *vif) |
595 | { | 597 | { |
596 | wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", | 598 | wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", |
597 | __func__, vif->type, vif->addr); | 599 | __func__, ieee80211_vif_type_p2p(vif), |
600 | vif->addr); | ||
598 | hwsim_set_magic(vif); | 601 | hwsim_set_magic(vif); |
599 | return 0; | 602 | return 0; |
600 | } | 603 | } |
601 | 604 | ||
602 | 605 | ||
606 | static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw, | ||
607 | struct ieee80211_vif *vif, | ||
608 | enum nl80211_iftype newtype, | ||
609 | bool newp2p) | ||
610 | { | ||
611 | newtype = ieee80211_iftype_p2p(newtype, newp2p); | ||
612 | wiphy_debug(hw->wiphy, | ||
613 | "%s (old type=%d, new type=%d, mac_addr=%pM)\n", | ||
614 | __func__, ieee80211_vif_type_p2p(vif), | ||
615 | newtype, vif->addr); | ||
616 | hwsim_check_magic(vif); | ||
617 | |||
618 | return 0; | ||
619 | } | ||
620 | |||
603 | static void mac80211_hwsim_remove_interface( | 621 | static void mac80211_hwsim_remove_interface( |
604 | struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 622 | struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
605 | { | 623 | { |
606 | wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", | 624 | wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n", |
607 | __func__, vif->type, vif->addr); | 625 | __func__, ieee80211_vif_type_p2p(vif), |
626 | vif->addr); | ||
608 | hwsim_check_magic(vif); | 627 | hwsim_check_magic(vif); |
609 | hwsim_clear_magic(vif); | 628 | hwsim_clear_magic(vif); |
610 | } | 629 | } |
@@ -620,7 +639,8 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
620 | hwsim_check_magic(vif); | 639 | hwsim_check_magic(vif); |
621 | 640 | ||
622 | if (vif->type != NL80211_IFTYPE_AP && | 641 | if (vif->type != NL80211_IFTYPE_AP && |
623 | vif->type != NL80211_IFTYPE_MESH_POINT) | 642 | vif->type != NL80211_IFTYPE_MESH_POINT && |
643 | vif->type != NL80211_IFTYPE_ADHOC) | ||
624 | return; | 644 | return; |
625 | 645 | ||
626 | skb = ieee80211_beacon_get(hw, vif); | 646 | skb = ieee80211_beacon_get(hw, vif); |
@@ -679,6 +699,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) | |||
679 | data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); | 699 | data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); |
680 | 700 | ||
681 | data->channel = conf->channel; | 701 | data->channel = conf->channel; |
702 | data->power_level = conf->power_level; | ||
682 | if (!data->started || !data->beacon_int) | 703 | if (!data->started || !data->beacon_int) |
683 | del_timer(&data->beacon_timer); | 704 | del_timer(&data->beacon_timer); |
684 | else | 705 | else |
@@ -921,7 +942,8 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, | |||
921 | static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, | 942 | static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, |
922 | struct ieee80211_vif *vif, | 943 | struct ieee80211_vif *vif, |
923 | enum ieee80211_ampdu_mlme_action action, | 944 | enum ieee80211_ampdu_mlme_action action, |
924 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 945 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
946 | u8 buf_size) | ||
925 | { | 947 | { |
926 | switch (action) { | 948 | switch (action) { |
927 | case IEEE80211_AMPDU_TX_START: | 949 | case IEEE80211_AMPDU_TX_START: |
@@ -1025,6 +1047,7 @@ static struct ieee80211_ops mac80211_hwsim_ops = | |||
1025 | .start = mac80211_hwsim_start, | 1047 | .start = mac80211_hwsim_start, |
1026 | .stop = mac80211_hwsim_stop, | 1048 | .stop = mac80211_hwsim_stop, |
1027 | .add_interface = mac80211_hwsim_add_interface, | 1049 | .add_interface = mac80211_hwsim_add_interface, |
1050 | .change_interface = mac80211_hwsim_change_interface, | ||
1028 | .remove_interface = mac80211_hwsim_remove_interface, | 1051 | .remove_interface = mac80211_hwsim_remove_interface, |
1029 | .config = mac80211_hwsim_config, | 1052 | .config = mac80211_hwsim_config, |
1030 | .configure_filter = mac80211_hwsim_configure_filter, | 1053 | .configure_filter = mac80211_hwsim_configure_filter, |
@@ -1295,6 +1318,9 @@ static int __init init_mac80211_hwsim(void) | |||
1295 | hw->wiphy->interface_modes = | 1318 | hw->wiphy->interface_modes = |
1296 | BIT(NL80211_IFTYPE_STATION) | | 1319 | BIT(NL80211_IFTYPE_STATION) | |
1297 | BIT(NL80211_IFTYPE_AP) | | 1320 | BIT(NL80211_IFTYPE_AP) | |
1321 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
1322 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
1323 | BIT(NL80211_IFTYPE_ADHOC) | | ||
1298 | BIT(NL80211_IFTYPE_MESH_POINT); | 1324 | BIT(NL80211_IFTYPE_MESH_POINT); |
1299 | 1325 | ||
1300 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | 1326 | hw->flags = IEEE80211_HW_MFP_CAPABLE | |
@@ -1489,19 +1515,10 @@ static int __init init_mac80211_hwsim(void) | |||
1489 | if (hwsim_mon == NULL) | 1515 | if (hwsim_mon == NULL) |
1490 | goto failed; | 1516 | goto failed; |
1491 | 1517 | ||
1492 | rtnl_lock(); | 1518 | err = register_netdev(hwsim_mon); |
1493 | |||
1494 | err = dev_alloc_name(hwsim_mon, hwsim_mon->name); | ||
1495 | if (err < 0) | ||
1496 | goto failed_mon; | ||
1497 | |||
1498 | |||
1499 | err = register_netdevice(hwsim_mon); | ||
1500 | if (err < 0) | 1519 | if (err < 0) |
1501 | goto failed_mon; | 1520 | goto failed_mon; |
1502 | 1521 | ||
1503 | rtnl_unlock(); | ||
1504 | |||
1505 | return 0; | 1522 | return 0; |
1506 | 1523 | ||
1507 | failed_mon: | 1524 | failed_mon: |