32
32
#include <net/genetlink.h>
33
33
#include <net/net_namespace.h>
34
34
#include <net/netns/generic.h>
35
+ #include <linux/rhashtable.h>
35
36
#include "mac80211_hwsim.h"
36
37
37
38
#define WARN_QUEUE 100
@@ -490,6 +491,7 @@ static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = {
490
491
static spinlock_t hwsim_radio_lock ;
491
492
static LIST_HEAD (hwsim_radios );
492
493
static struct workqueue_struct * hwsim_wq ;
494
+ static struct rhashtable hwsim_radios_rht ;
493
495
static int hwsim_radio_idx ;
494
496
495
497
static struct platform_driver mac80211_hwsim_driver = {
@@ -500,6 +502,7 @@ static struct platform_driver mac80211_hwsim_driver = {
500
502
501
503
struct mac80211_hwsim_data {
502
504
struct list_head list ;
505
+ struct rhash_head rht ;
503
506
struct ieee80211_hw * hw ;
504
507
struct device * dev ;
505
508
struct ieee80211_supported_band bands [NUM_NL80211_BANDS ];
@@ -574,6 +577,13 @@ struct mac80211_hwsim_data {
574
577
u64 tx_failed ;
575
578
};
576
579
580
+ static const struct rhashtable_params hwsim_rht_params = {
581
+ .nelem_hint = 2 ,
582
+ .automatic_shrinking = true,
583
+ .key_len = ETH_ALEN ,
584
+ .key_offset = offsetof(struct mac80211_hwsim_data , addresses [1 ]),
585
+ .head_offset = offsetof(struct mac80211_hwsim_data , rht ),
586
+ };
577
587
578
588
struct hwsim_radiotap_hdr {
579
589
struct ieee80211_radiotap_header hdr ;
@@ -1009,6 +1019,36 @@ static int hwsim_unicast_netgroup(struct mac80211_hwsim_data *data,
1009
1019
return res ;
1010
1020
}
1011
1021
1022
+ static inline u16 trans_tx_rate_flags_ieee2hwsim (struct ieee80211_tx_rate * rate )
1023
+ {
1024
+ u16 result = 0 ;
1025
+
1026
+ if (rate -> flags & IEEE80211_TX_RC_USE_RTS_CTS )
1027
+ result |= MAC80211_HWSIM_TX_RC_USE_RTS_CTS ;
1028
+ if (rate -> flags & IEEE80211_TX_RC_USE_CTS_PROTECT )
1029
+ result |= MAC80211_HWSIM_TX_RC_USE_CTS_PROTECT ;
1030
+ if (rate -> flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE )
1031
+ result |= MAC80211_HWSIM_TX_RC_USE_SHORT_PREAMBLE ;
1032
+ if (rate -> flags & IEEE80211_TX_RC_MCS )
1033
+ result |= MAC80211_HWSIM_TX_RC_MCS ;
1034
+ if (rate -> flags & IEEE80211_TX_RC_GREEN_FIELD )
1035
+ result |= MAC80211_HWSIM_TX_RC_GREEN_FIELD ;
1036
+ if (rate -> flags & IEEE80211_TX_RC_40_MHZ_WIDTH )
1037
+ result |= MAC80211_HWSIM_TX_RC_40_MHZ_WIDTH ;
1038
+ if (rate -> flags & IEEE80211_TX_RC_DUP_DATA )
1039
+ result |= MAC80211_HWSIM_TX_RC_DUP_DATA ;
1040
+ if (rate -> flags & IEEE80211_TX_RC_SHORT_GI )
1041
+ result |= MAC80211_HWSIM_TX_RC_SHORT_GI ;
1042
+ if (rate -> flags & IEEE80211_TX_RC_VHT_MCS )
1043
+ result |= MAC80211_HWSIM_TX_RC_VHT_MCS ;
1044
+ if (rate -> flags & IEEE80211_TX_RC_80_MHZ_WIDTH )
1045
+ result |= MAC80211_HWSIM_TX_RC_80_MHZ_WIDTH ;
1046
+ if (rate -> flags & IEEE80211_TX_RC_160_MHZ_WIDTH )
1047
+ result |= MAC80211_HWSIM_TX_RC_160_MHZ_WIDTH ;
1048
+
1049
+ return result ;
1050
+ }
1051
+
1012
1052
static void mac80211_hwsim_tx_frame_nl (struct ieee80211_hw * hw ,
1013
1053
struct sk_buff * my_skb ,
1014
1054
int dst_portid )
@@ -1021,6 +1061,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
1021
1061
unsigned int hwsim_flags = 0 ;
1022
1062
int i ;
1023
1063
struct hwsim_tx_rate tx_attempts [IEEE80211_TX_MAX_RATES ];
1064
+ struct hwsim_tx_rate_flag tx_attempts_flags [IEEE80211_TX_MAX_RATES ];
1024
1065
uintptr_t cookie ;
1025
1066
1026
1067
if (data -> ps != PS_DISABLED )
@@ -1072,14 +1113,23 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
1072
1113
1073
1114
for (i = 0 ; i < IEEE80211_TX_MAX_RATES ; i ++ ) {
1074
1115
tx_attempts [i ].idx = info -> status .rates [i ].idx ;
1116
+ tx_attempts_flags [i ].idx = info -> status .rates [i ].idx ;
1075
1117
tx_attempts [i ].count = info -> status .rates [i ].count ;
1118
+ tx_attempts_flags [i ].flags =
1119
+ trans_tx_rate_flags_ieee2hwsim (
1120
+ & info -> status .rates [i ]);
1076
1121
}
1077
1122
1078
1123
if (nla_put (skb , HWSIM_ATTR_TX_INFO ,
1079
1124
sizeof (struct hwsim_tx_rate )* IEEE80211_TX_MAX_RATES ,
1080
1125
tx_attempts ))
1081
1126
goto nla_put_failure ;
1082
1127
1128
+ if (nla_put (skb , HWSIM_ATTR_TX_INFO_FLAGS ,
1129
+ sizeof (struct hwsim_tx_rate_flag ) * IEEE80211_TX_MAX_RATES ,
1130
+ tx_attempts_flags ))
1131
+ goto nla_put_failure ;
1132
+
1083
1133
/* We create a cookie to identify this skb */
1084
1134
data -> pending_cookie ++ ;
1085
1135
cookie = data -> pending_cookie ;
@@ -2732,6 +2782,15 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
2732
2782
CLOCK_MONOTONIC , HRTIMER_MODE_ABS );
2733
2783
2734
2784
spin_lock_bh (& hwsim_radio_lock );
2785
+ err = rhashtable_insert_fast (& hwsim_radios_rht , & data -> rht ,
2786
+ hwsim_rht_params );
2787
+ if (err < 0 ) {
2788
+ pr_debug ("mac80211_hwsim: radio index %d already present\n" ,
2789
+ idx );
2790
+ spin_unlock_bh (& hwsim_radio_lock );
2791
+ goto failed_final_insert ;
2792
+ }
2793
+
2735
2794
list_add_tail (& data -> list , & hwsim_radios );
2736
2795
spin_unlock_bh (& hwsim_radio_lock );
2737
2796
@@ -2740,6 +2799,9 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
2740
2799
2741
2800
return idx ;
2742
2801
2802
+ failed_final_insert :
2803
+ debugfs_remove_recursive (data -> debugfs );
2804
+ ieee80211_unregister_hw (data -> hw );
2743
2805
failed_hw :
2744
2806
device_release_driver (data -> dev );
2745
2807
failed_bind :
@@ -2875,22 +2937,9 @@ static void hwsim_mon_setup(struct net_device *dev)
2875
2937
2876
2938
static struct mac80211_hwsim_data * get_hwsim_data_ref_from_addr (const u8 * addr )
2877
2939
{
2878
- struct mac80211_hwsim_data * data ;
2879
- bool _found = false;
2880
-
2881
- spin_lock_bh (& hwsim_radio_lock );
2882
- list_for_each_entry (data , & hwsim_radios , list ) {
2883
- if (memcmp (data -> addresses [1 ].addr , addr , ETH_ALEN ) == 0 ) {
2884
- _found = true;
2885
- break ;
2886
- }
2887
- }
2888
- spin_unlock_bh (& hwsim_radio_lock );
2889
-
2890
- if (!_found )
2891
- return NULL ;
2892
-
2893
- return data ;
2940
+ return rhashtable_lookup_fast (& hwsim_radios_rht ,
2941
+ addr ,
2942
+ hwsim_rht_params );
2894
2943
}
2895
2944
2896
2945
static void hwsim_register_wmediumd (struct net * net , u32 portid )
@@ -2975,7 +3024,6 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
2975
3024
for (i = 0 ; i < IEEE80211_TX_MAX_RATES ; i ++ ) {
2976
3025
txi -> status .rates [i ].idx = tx_attempts [i ].idx ;
2977
3026
txi -> status .rates [i ].count = tx_attempts [i ].count ;
2978
- /*txi->status.rates[i].flags = 0;*/
2979
3027
}
2980
3028
2981
3029
txi -> status .ack_signal = nla_get_u32 (info -> attrs [HWSIM_ATTR_SIGNAL ]);
@@ -3155,8 +3203,10 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
3155
3203
if (info -> attrs [HWSIM_ATTR_REG_CUSTOM_REG ]) {
3156
3204
u32 idx = nla_get_u32 (info -> attrs [HWSIM_ATTR_REG_CUSTOM_REG ]);
3157
3205
3158
- if (idx >= ARRAY_SIZE (hwsim_world_regdom_custom ))
3206
+ if (idx >= ARRAY_SIZE (hwsim_world_regdom_custom )) {
3207
+ kfree (hwname );
3159
3208
return - EINVAL ;
3209
+ }
3160
3210
param .regd = hwsim_world_regdom_custom [idx ];
3161
3211
}
3162
3212
@@ -3197,6 +3247,8 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
3197
3247
continue ;
3198
3248
3199
3249
list_del (& data -> list );
3250
+ rhashtable_remove_fast (& hwsim_radios_rht , & data -> rht ,
3251
+ hwsim_rht_params );
3200
3252
spin_unlock_bh (& hwsim_radio_lock );
3201
3253
mac80211_hwsim_del_radio (data , wiphy_name (data -> hw -> wiphy ),
3202
3254
info );
@@ -3352,6 +3404,8 @@ static void remove_user_radios(u32 portid)
3352
3404
list_for_each_entry_safe (entry , tmp , & hwsim_radios , list ) {
3353
3405
if (entry -> destroy_on_close && entry -> portid == portid ) {
3354
3406
list_del (& entry -> list );
3407
+ rhashtable_remove_fast (& hwsim_radios_rht , & entry -> rht ,
3408
+ hwsim_rht_params );
3355
3409
INIT_WORK (& entry -> destroy_work , destroy_radio );
3356
3410
queue_work (hwsim_wq , & entry -> destroy_work );
3357
3411
}
@@ -3427,6 +3481,8 @@ static void __net_exit hwsim_exit_net(struct net *net)
3427
3481
continue ;
3428
3482
3429
3483
list_del (& data -> list );
3484
+ rhashtable_remove_fast (& hwsim_radios_rht , & data -> rht ,
3485
+ hwsim_rht_params );
3430
3486
INIT_WORK (& data -> destroy_work , destroy_radio );
3431
3487
queue_work (hwsim_wq , & data -> destroy_work );
3432
3488
}
@@ -3463,6 +3519,7 @@ static int __init init_mac80211_hwsim(void)
3463
3519
hwsim_wq = alloc_workqueue ("hwsim_wq" ,WQ_MEM_RECLAIM ,0 );
3464
3520
if (!hwsim_wq )
3465
3521
return - ENOMEM ;
3522
+ rhashtable_init (& hwsim_radios_rht , & hwsim_rht_params );
3466
3523
3467
3524
err = register_pernet_device (& hwsim_net_ops );
3468
3525
if (err )
@@ -3604,6 +3661,7 @@ static void __exit exit_mac80211_hwsim(void)
3604
3661
mac80211_hwsim_free ();
3605
3662
flush_workqueue (hwsim_wq );
3606
3663
3664
+ rhashtable_destroy (& hwsim_radios_rht );
3607
3665
unregister_netdev (hwsim_mon );
3608
3666
platform_driver_unregister (& mac80211_hwsim_driver );
3609
3667
unregister_pernet_device (& hwsim_net_ops );
0 commit comments