Generate a tsf from jiffies. Prepare the path for having different tsf
offsets on the each phy. This will be useful for testing mesh
synchronization algorithms.
Signed-off-by: Javier Cardona <[email protected]>
---
v2: Added timestamp to probe responses, as suggested by Johannes
Also implement tx_last_beacon, useful for testing (new patch 1/3)
v3: Drop poorly implemented tx_last_beacon patch
TSF in microsecs, not TUs! (Johannes)
Use high-resolution timer, not jiffies (Johannes)
drivers/net/wireless/mac80211_hwsim.c | 39 +++++++++++++++++++++++++++++---
1 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index ba16f05..597f804 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -321,11 +321,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;
+ u64 rt_tsft;
u8 rt_flags;
u8 rt_rate;
__le16 rt_channel;
@@ -367,6 +371,11 @@ 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)
+{
+ return cpu_to_le64(jiffies_to_msecs(jiffies)*1000/1024 +
+ data->tsf_offset);
+}
static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
struct sk_buff *tx_skb)
@@ -391,7 +400,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 +621,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 +679,19 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
bool ack;
struct ieee80211_tx_info *txi;
u32 _pid;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct mac80211_hwsim_data *data = hw->priv;
+ __le64 *tsfpos;
+ u16 fc = le16_to_cpu(hdr->frame_control);
+ u16 fctypes = fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
+
+ if (fctypes == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP) ||
+ fctypes == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) {
+ struct ieee80211_hdr_3addr *hdr3 =
+ (struct ieee80211_hdr_3addr *) skb->data;
+ tsfpos = (__le64 *) (hdr3 + 1);
+ put_unaligned(__mac80211_hwsim_get_tsf(data), tsfpos);
+ }
mac80211_hwsim_monitor_rx(hw, skb);
@@ -685,10 +710,8 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
/* NO wmediumd detected, perfect medium simulation */
ack = mac80211_hwsim_tx_frame_no_nl(hw, skb);
- if (ack && skb->len >= 16) {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ if (ack && skb->len >= 16)
mac80211_hwsim_monitor_ack(hw, hdr->addr2);
- }
txi = IEEE80211_SKB_CB(skb);
@@ -763,9 +786,12 @@ 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_hdr_3addr *hdr;
+ __le64 *tsfpos;
hwsim_check_magic(vif);
@@ -779,6 +805,11 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
return;
info = IEEE80211_SKB_CB(skb);
+ /* add the timestamp to the beacon */
+ hdr = (struct ieee80211_hdr_3addr *) skb->data;
+ tsfpos = (__le64 *) (hdr + 1);
+ put_unaligned(__mac80211_hwsim_get_tsf(data), tsfpos);
+
mac80211_hwsim_monitor_rx(hw, skb);
/* wmediumd mode check */
--
1.7.6
On Fri, 2012-03-02 at 13:04 -0800, Javier Cardona wrote:
> Generate a tsf from jiffies. Prepare the path for having different tsf
> offsets on the each phy. This will be useful for testing mesh
> synchronization algorithms.
>
> Signed-off-by: Javier Cardona <[email protected]>
> ---
> v2: Added timestamp to probe responses, as suggested by Johannes
> Also implement tx_last_beacon, useful for testing (new patch 1/3)
> v3: Drop poorly implemented tx_last_beacon patch
> TSF in microsecs, not TUs! (Johannes)
> Use high-resolution timer, not jiffies (Johannes)
> +static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data)
> +{
> + return cpu_to_le64(jiffies_to_msecs(jiffies)*1000/1024 +
> + data->tsf_offset);
> +}
Did you forget to quilt refresh or so? :-)
johannes
On Fri, Mar 2, 2012 at 1:11 PM, Johannes Berg <[email protected]> wrote:
> On Fri, 2012-03-02 at 13:04 -0800, Javier Cardona wrote:
>
>> ?static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data)
>> ?{
>> - ? ? return cpu_to_le64(jiffies_to_msecs(jiffies)*1000/1024 +
>> - ? ? ? ? ? ? ? ? ? ? data->tsf_offset);
>> + ? ? struct timeval tv = ktime_to_timeval(ktime_get_real());
>> + ? ? u64 now = (u64) tv.tv_sec * MSEC_PER_SEC + tv.tv_usec / USEC_PER_MSEC;
>> + ? ? return cpu_to_le64(now + data->tsf_offset);
>> +}
>
> Oh.
>
> But now you're giving it in MSEC, you want USEC.
I changed tea brands this week and it shows. v4 in a few minutes.
j
--
Javier Cardona
cozybit Inc.
http://www.cozybit.com
On Fri, 2012-03-02 at 13:04 -0800, Javier Cardona wrote:
> static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data)
> {
> - return cpu_to_le64(jiffies_to_msecs(jiffies)*1000/1024 +
> - data->tsf_offset);
> + struct timeval tv = ktime_to_timeval(ktime_get_real());
> + u64 now = (u64) tv.tv_sec * MSEC_PER_SEC + tv.tv_usec / USEC_PER_MSEC;
> + return cpu_to_le64(now + data->tsf_offset);
> +}
Oh.
But now you're giving it in MSEC, you want USEC.
johannes
Signed-off-by: Javier Cardona <[email protected]>
---
drivers/net/wireless/mac80211_hwsim.c | 24 ++++++++++++++++++++++--
net/mac80211/debugfs_netdev.c | 7 ++++++-
2 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 597f804..4f41701 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"
@@ -373,8 +374,25 @@ static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb,
static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data)
{
- return cpu_to_le64(jiffies_to_msecs(jiffies)*1000/1024 +
- data->tsf_offset);
+ struct timeval tv = ktime_to_timeval(ktime_get_real());
+ u64 now = (u64) tv.tv_sec * MSEC_PER_SEC + tv.tv_usec / USEC_PER_MSEC;
+ 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 = (u64) tv.tv_sec * MSEC_PER_SEC + tv.tv_usec / USEC_PER_MSEC;
+ data->tsf_offset = tsf - now;
}
static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
@@ -1230,6 +1248,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,
};
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 510ed1d..416b906 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -537,11 +537,15 @@ static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
#ifdef CONFIG_MAC80211_MESH
+static void add_mesh_files(struct ieee80211_sub_if_data *sdata)
+{
+ DEBUGFS_ADD_MODE(tsf, 0600);
+}
+
static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
{
struct dentry *dir = debugfs_create_dir("mesh_stats",
sdata->debugfs.dir);
-
#define MESHSTATS_ADD(name)\
debugfs_create_file(#name, 0400, dir, sdata, &name##_ops);
@@ -593,6 +597,7 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
switch (sdata->vif.type) {
case NL80211_IFTYPE_MESH_POINT:
#ifdef CONFIG_MAC80211_MESH
+ add_mesh_files(sdata);
add_mesh_stats(sdata);
add_mesh_config(sdata);
#endif
--
1.7.6
On Fri, 2012-03-02 at 13:04 -0800, Javier Cardona wrote:
> @@ -667,6 +679,19 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
> bool ack;
> struct ieee80211_tx_info *txi;
> u32 _pid;
> + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
> + struct mac80211_hwsim_data *data = hw->priv;
> + __le64 *tsfpos;
> + u16 fc = le16_to_cpu(hdr->frame_control);
> + u16 fctypes = fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
> +
> + if (fctypes == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP) ||
> + fctypes == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) {
> + struct ieee80211_hdr_3addr *hdr3 =
> + (struct ieee80211_hdr_3addr *) skb->data;
> + tsfpos = (__le64 *) (hdr3 + 1);
> + put_unaligned(__mac80211_hwsim_get_tsf(data), tsfpos);
> + }
And here, you can do the same with struct ieee80211_mgmt and don't even
need the struct ieee80211_hdr * variable then.
Also, you should use ieee80211_is_beacon() and ieee80211_is_probe_req().
Sorry for the incoherent review!
johannes
Oops, just saw something else:
> struct hwsim_radiotap_hdr {
> struct ieee80211_radiotap_header hdr;
> + u64 rt_tsft;
That should be __le64
> @@ -779,6 +805,11 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
> return;
> info = IEEE80211_SKB_CB(skb);
>
> + /* add the timestamp to the beacon */
> + hdr = (struct ieee80211_hdr_3addr *) skb->data;
> + tsfpos = (__le64 *) (hdr + 1);
> + put_unaligned(__mac80211_hwsim_get_tsf(data), tsfpos);
> +
And I saw this but wondered ... maybe it should just be
struct ieee80211_mgmt *mgmt = skb->data;
mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data);
as you then also don't need the unaligned trick since the struct is
packed.
johannes
On Fri, Mar 2, 2012 at 1:43 PM, Johannes Berg <[email protected]> wrote:
> On Fri, 2012-03-02 at 13:04 -0800, Javier Cardona wrote:
>
>> @@ -667,6 +679,19 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
>> ? ? ? bool ack;
>> ? ? ? struct ieee80211_tx_info *txi;
>> ? ? ? u32 _pid;
>> + ? ? struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
>> + ? ? struct mac80211_hwsim_data *data = hw->priv;
>> + ? ? __le64 *tsfpos;
>> + ? ? u16 fc = le16_to_cpu(hdr->frame_control);
>> + ? ? u16 fctypes = fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
>> +
>> + ? ? if (fctypes == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP) ||
>> + ? ? ? ? fctypes == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) {
>> + ? ? ? ? ? ? struct ieee80211_hdr_3addr *hdr3 =
>> + ? ? ? ? ? ? ? ? ? ? (struct ieee80211_hdr_3addr *) skb->data;
>> + ? ? ? ? ? ? tsfpos = (__le64 *) (hdr3 + 1);
>> + ? ? ? ? ? ? put_unaligned(__mac80211_hwsim_get_tsf(data), tsfpos);
>> + ? ? }
>
> And here, you can do the same with struct ieee80211_mgmt and don't even
> need the struct ieee80211_hdr * variable then.
>
> Also, you should use ieee80211_is_beacon() and ieee80211_is_probe_req().
>
> Sorry for the incoherent review!
No, thank you for your patience and help. Working on v5 (how many
patch revisions can I make before somebody bans me from the list? :)
j