aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Pedersen <thomas@cozybit.com>2013-01-07 17:48:07 -0500
committerJohn W. Linville <linville@tuxdriver.com>2013-01-11 14:49:58 -0500
commitb66851c3c89629e72a2eaa54d1b838fb74dad644 (patch)
treedd914ded35614222b2fde3970a35b6d191d9c2b9
parent29b7d9ad9112a95757c8030421dc3bd1b28ad8b5 (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.c57
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
415static inline u64 mac80211_hwsim_get_tsf_raw(void)
416{
417 return ktime_to_us(ktime_get_real());
418}
419
413static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data) 420static __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
420static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw, 426static 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,
987static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, 995static 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) {