diff options
Diffstat (limited to 'drivers/net/wireless/mac80211_hwsim.c')
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index ba16f05df0f..b4f6cb3298a 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -27,6 +27,7 @@ #include <linux/etherdevice.h> #include <linux/debugfs.h> #include <linux/module.h> +#include <linux/ktime.h> #include <net/genetlink.h> #include "mac80211_hwsim.h" @@ -321,11 +322,15 @@ struct mac80211_hwsim_data { struct dentry *debugfs_group; int power_level; + + /* difference between this hw's clock and the real clock, in usecs */ + u64 tsf_offset; }; struct hwsim_radiotap_hdr { struct ieee80211_radiotap_header hdr; + __le64 rt_tsft; u8 rt_flags; u8 rt_rate; __le16 rt_channel; @@ -367,6 +372,28 @@ static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } +static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data) +{ + struct timeval tv = ktime_to_timeval(ktime_get_real()); + u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec; + return cpu_to_le64(now + data->tsf_offset); +} + +static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mac80211_hwsim_data *data = hw->priv; + return le64_to_cpu(__mac80211_hwsim_get_tsf(data)); +} + +static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u64 tsf) +{ + struct mac80211_hwsim_data *data = hw->priv; + struct timeval tv = ktime_to_timeval(ktime_get_real()); + u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec; + data->tsf_offset = tsf - now; +} static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, struct sk_buff *tx_skb) @@ -391,7 +418,9 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr)); hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | (1 << IEEE80211_RADIOTAP_RATE) | + (1 << IEEE80211_RADIOTAP_TSFT) | (1 << IEEE80211_RADIOTAP_CHANNEL)); + hdr->rt_tsft = __mac80211_hwsim_get_tsf(data); hdr->rt_flags = 0; hdr->rt_rate = txrate->bitrate / 5; hdr->rt_channel = cpu_to_le16(data->channel->center_freq); @@ -610,7 +639,8 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, } memset(&rx_status, 0, sizeof(rx_status)); - /* TODO: set mactime */ + rx_status.mactime = le64_to_cpu(__mac80211_hwsim_get_tsf(data)); + rx_status.flag |= RX_FLAG_MACTIME_MPDU; rx_status.freq = data->channel->center_freq; rx_status.band = data->channel->band; rx_status.rate_idx = info->control.rates[0].idx; @@ -667,6 +697,12 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) bool ack; struct ieee80211_tx_info *txi; u32 _pid; + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; + struct mac80211_hwsim_data *data = hw->priv; + + if (ieee80211_is_beacon(mgmt->frame_control) || + ieee80211_is_probe_resp(mgmt->frame_control)) + mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data); mac80211_hwsim_monitor_rx(hw, skb); @@ -763,9 +799,11 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, struct ieee80211_vif *vif) { struct ieee80211_hw *hw = arg; + struct mac80211_hwsim_data *data = hw->priv; struct sk_buff *skb; struct ieee80211_tx_info *info; u32 _pid; + struct ieee80211_mgmt *mgmt; hwsim_check_magic(vif); @@ -779,6 +817,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, return; info = IEEE80211_SKB_CB(skb); + mgmt = (struct ieee80211_mgmt *) skb->data; + mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data); + mac80211_hwsim_monitor_rx(hw, skb); /* wmediumd mode check */ @@ -1199,6 +1240,8 @@ static struct ieee80211_ops mac80211_hwsim_ops = .sw_scan_start = mac80211_hwsim_sw_scan, .sw_scan_complete = mac80211_hwsim_sw_scan_complete, .flush = mac80211_hwsim_flush, + .get_tsf = mac80211_hwsim_get_tsf, + .set_tsf = mac80211_hwsim_set_tsf, }; |