diff options
author | Thomas Pedersen <thomas@cozybit.com> | 2013-01-07 17:48:07 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-01-11 14:49:58 -0500 |
commit | b66851c3c89629e72a2eaa54d1b838fb74dad644 (patch) | |
tree | dd914ded35614222b2fde3970a35b6d191d9c2b9 | |
parent | 29b7d9ad9112a95757c8030421dc3bd1b28ad8b5 (diff) |
mac80211_hwsim: fix beacon timestamp and mactime
Set the beacon timestamp once during "transmission" so the
monitor interface also gets a timestamped beacon.
Also use a common base between TX timestamp and RX
mactime. This eliminates "TX" path delay, which shows up
as a constant error in Toffset.
Get the global TSF once before iterating over all RX HWs,
so they all set a mactime with the same time base.
Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index b6e2caa024a7..b73e497fe770 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -363,6 +363,8 @@ struct mac80211_hwsim_data { | |||
363 | /* difference between this hw's clock and the real clock, in usecs */ | 363 | /* difference between this hw's clock and the real clock, in usecs */ |
364 | s64 tsf_offset; | 364 | s64 tsf_offset; |
365 | s64 bcn_delta; | 365 | s64 bcn_delta; |
366 | /* absolute beacon transmission time. Used to cover up "tx" delay. */ | ||
367 | u64 abs_bcn_ts; | ||
366 | }; | 368 | }; |
367 | 369 | ||
368 | 370 | ||
@@ -410,15 +412,19 @@ static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb, | |||
410 | return NETDEV_TX_OK; | 412 | return NETDEV_TX_OK; |
411 | } | 413 | } |
412 | 414 | ||
415 | static inline u64 mac80211_hwsim_get_tsf_raw(void) | ||
416 | { | ||
417 | return ktime_to_us(ktime_get_real()); | ||
418 | } | ||
419 | |||
413 | static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data) | 420 | static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data) |
414 | { | 421 | { |
415 | struct timeval tv = ktime_to_timeval(ktime_get_real()); | 422 | u64 now = mac80211_hwsim_get_tsf_raw(); |
416 | u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec; | ||
417 | return cpu_to_le64(now + data->tsf_offset); | 423 | return cpu_to_le64(now + data->tsf_offset); |
418 | } | 424 | } |
419 | 425 | ||
420 | static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw, | 426 | static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw, |
421 | struct ieee80211_vif *vif) | 427 | struct ieee80211_vif *vif) |
422 | { | 428 | { |
423 | struct mac80211_hwsim_data *data = hw->priv; | 429 | struct mac80211_hwsim_data *data = hw->priv; |
424 | return le64_to_cpu(__mac80211_hwsim_get_tsf(data)); | 430 | return le64_to_cpu(__mac80211_hwsim_get_tsf(data)); |
@@ -705,7 +711,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
705 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 711 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
706 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 712 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
707 | struct ieee80211_rx_status rx_status; | 713 | struct ieee80211_rx_status rx_status; |
708 | struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info); | 714 | u64 now; |
709 | 715 | ||
710 | memset(&rx_status, 0, sizeof(rx_status)); | 716 | memset(&rx_status, 0, sizeof(rx_status)); |
711 | rx_status.flag |= RX_FLAG_MACTIME_START; | 717 | rx_status.flag |= RX_FLAG_MACTIME_START; |
@@ -731,11 +737,23 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
731 | secpath_reset(skb); | 737 | secpath_reset(skb); |
732 | nf_reset(skb); | 738 | nf_reset(skb); |
733 | 739 | ||
740 | /* | ||
741 | * Get absolute mactime here so all HWs RX at the "same time", and | ||
742 | * absolute TX time for beacon mactime so the timestamp matches. | ||
743 | * Giving beacons a different mactime than non-beacons looks messy, but | ||
744 | * it helps the Toffset be exact and a ~10us mactime discrepancy | ||
745 | * probably doesn't really matter. | ||
746 | */ | ||
747 | if (ieee80211_is_beacon(hdr->frame_control) || | ||
748 | ieee80211_is_probe_resp(hdr->frame_control)) | ||
749 | now = data->abs_bcn_ts; | ||
750 | else | ||
751 | now = mac80211_hwsim_get_tsf_raw(); | ||
752 | |||
734 | /* Copy skb to all enabled radios that are on the current frequency */ | 753 | /* Copy skb to all enabled radios that are on the current frequency */ |
735 | spin_lock(&hwsim_radio_lock); | 754 | spin_lock(&hwsim_radio_lock); |
736 | list_for_each_entry(data2, &hwsim_radios, list) { | 755 | list_for_each_entry(data2, &hwsim_radios, list) { |
737 | struct sk_buff *nskb; | 756 | struct sk_buff *nskb; |
738 | struct ieee80211_mgmt *mgmt; | ||
739 | struct tx_iter_data tx_iter_data = { | 757 | struct tx_iter_data tx_iter_data = { |
740 | .receive = false, | 758 | .receive = false, |
741 | .channel = chan, | 759 | .channel = chan, |
@@ -787,17 +805,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
787 | if (mac80211_hwsim_addr_match(data2, hdr->addr1)) | 805 | if (mac80211_hwsim_addr_match(data2, hdr->addr1)) |
788 | ack = true; | 806 | ack = true; |
789 | 807 | ||
790 | /* set bcn timestamp relative to receiver mactime */ | 808 | rx_status.mactime = now + data2->tsf_offset; |
791 | rx_status.mactime = | ||
792 | le64_to_cpu(__mac80211_hwsim_get_tsf(data2)); | ||
793 | mgmt = (struct ieee80211_mgmt *) nskb->data; | ||
794 | if (ieee80211_is_beacon(mgmt->frame_control) || | ||
795 | ieee80211_is_probe_resp(mgmt->frame_control)) | ||
796 | mgmt->u.beacon.timestamp = cpu_to_le64( | ||
797 | rx_status.mactime + | ||
798 | (data->tsf_offset - data2->tsf_offset) + | ||
799 | 24 * 8 * 10 / txrate->bitrate); | ||
800 | |||
801 | #if 0 | 809 | #if 0 |
802 | /* | 810 | /* |
803 | * Don't enable this code by default as the OUI 00:00:00 | 811 | * Don't enable this code by default as the OUI 00:00:00 |
@@ -987,7 +995,11 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | |||
987 | static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | 995 | static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, |
988 | struct ieee80211_vif *vif) | 996 | struct ieee80211_vif *vif) |
989 | { | 997 | { |
990 | struct ieee80211_hw *hw = arg; | 998 | struct mac80211_hwsim_data *data = arg; |
999 | struct ieee80211_hw *hw = data->hw; | ||
1000 | struct ieee80211_tx_info *info; | ||
1001 | struct ieee80211_rate *txrate; | ||
1002 | struct ieee80211_mgmt *mgmt; | ||
991 | struct sk_buff *skb; | 1003 | struct sk_buff *skb; |
992 | 1004 | ||
993 | hwsim_check_magic(vif); | 1005 | hwsim_check_magic(vif); |
@@ -1000,6 +1012,15 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
1000 | skb = ieee80211_beacon_get(hw, vif); | 1012 | skb = ieee80211_beacon_get(hw, vif); |
1001 | if (skb == NULL) | 1013 | if (skb == NULL) |
1002 | return; | 1014 | return; |
1015 | info = IEEE80211_SKB_CB(skb); | ||
1016 | txrate = ieee80211_get_tx_rate(hw, info); | ||
1017 | |||
1018 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
1019 | /* fake header transmission time */ | ||
1020 | data->abs_bcn_ts = mac80211_hwsim_get_tsf_raw(); | ||
1021 | mgmt->u.beacon.timestamp = cpu_to_le64(data->abs_bcn_ts + | ||
1022 | data->tsf_offset + | ||
1023 | 24 * 8 * 10 / txrate->bitrate); | ||
1003 | 1024 | ||
1004 | mac80211_hwsim_tx_frame(hw, skb, | 1025 | mac80211_hwsim_tx_frame(hw, skb, |
1005 | rcu_dereference(vif->chanctx_conf)->def.chan); | 1026 | rcu_dereference(vif->chanctx_conf)->def.chan); |
@@ -1020,7 +1041,7 @@ mac80211_hwsim_beacon(struct hrtimer *timer) | |||
1020 | 1041 | ||
1021 | ieee80211_iterate_active_interfaces_atomic( | 1042 | ieee80211_iterate_active_interfaces_atomic( |
1022 | hw, IEEE80211_IFACE_ITER_NORMAL, | 1043 | hw, IEEE80211_IFACE_ITER_NORMAL, |
1023 | mac80211_hwsim_beacon_tx, hw); | 1044 | mac80211_hwsim_beacon_tx, data); |
1024 | 1045 | ||
1025 | /* beacon at new TBTT + beacon interval */ | 1046 | /* beacon at new TBTT + beacon interval */ |
1026 | if (data->bcn_delta) { | 1047 | if (data->bcn_delta) { |