return result;
}
+static void mac80211_hwsim_write_tsf(struct mac80211_hwsim_data *data,
+ struct sk_buff *skb, u64 sim_time)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+ struct ieee80211_rate *txrate;
+ /* TODO: get MCS */
+ int bitrate = 100;
+
+ txrate = ieee80211_get_tx_rate(data->hw, info);
+ if (txrate)
+ bitrate = txrate->bitrate;
+
+ if (skb->len >= offsetofend(typeof(*mgmt), u.probe_resp.timestamp) &&
+ ieee80211_is_probe_resp(hdr->frame_control)) {
+ mgmt->u.probe_resp.timestamp =
+ cpu_to_le64(sim_time + data->tsf_offset +
+ 24 * 8 * 10 / bitrate);
+ } else if (skb->len >= offsetofend(typeof(*mgmt), u.beacon.timestamp) &&
+ ieee80211_is_beacon(mgmt->frame_control)) {
+ mgmt->u.beacon.timestamp = cpu_to_le64(sim_time +
+ data->tsf_offset +
+ 24 * 8 * 10 /
+ bitrate);
+ } else if (skb->len >= offsetofend(struct ieee80211_ext,
+ u.s1g_beacon.timestamp) &&
+ ieee80211_is_s1g_beacon(mgmt->frame_control)) {
+ struct ieee80211_ext *ext = (void *)mgmt;
+
+ ext->u.s1g_beacon.timestamp = cpu_to_le32(sim_time +
+ data->tsf_offset +
+ 10 * 8 * 10 /
+ bitrate);
+ }
+}
+
static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
struct sk_buff *my_skb,
int dst_portid,
struct hwsim_tx_rate tx_attempts[IEEE80211_TX_MAX_RATES];
struct hwsim_tx_rate_flag tx_attempts_flags[IEEE80211_TX_MAX_RATES];
uintptr_t cookie;
+ u64 sim_tsf;
if (data->ps != PS_DISABLED)
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
}
}
+ sim_tsf = mac80211_hwsim_get_sim_tsf();
+ mac80211_hwsim_write_tsf(data, my_skb, sim_tsf);
+
skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC);
if (skb == NULL)
goto nla_put_failure;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_rx_status rx_status;
- u64 sim_tsf;
+ u64 sim_tsf = mac80211_hwsim_get_sim_tsf();
+
+ mac80211_hwsim_write_tsf(data, skb, sim_tsf);
+
+ mac80211_hwsim_monitor_rx(hw, skb, chan);
memset(&rx_status, 0, sizeof(rx_status));
rx_status.flag |= RX_FLAG_MACTIME_START;
skb_ext_reset(skb);
nf_reset_ct(skb);
- /*
- * Get absolute mactime here so all HWs RX at the "same time", and
- * absolute TX time for beacon mactime so the timestamp matches.
- * Giving beacons a different mactime than non-beacons looks messy, but
- * it helps the Toffset be exact and a ~10us mactime discrepancy
- * probably doesn't really matter.
- */
if (ieee80211_is_beacon(hdr->frame_control) ||
- ieee80211_is_probe_resp(hdr->frame_control)) {
+ ieee80211_is_probe_resp(hdr->frame_control))
rx_status.boottime_ns = ktime_get_boottime_ns();
- sim_tsf = data->abs_bcn_ts;
- } else {
- sim_tsf = mac80211_hwsim_get_sim_tsf();
- }
/* Copy skb to all enabled radios that are on the current frequency */
spin_lock(&hwsim_radio_lock);
return;
}
- if (skb->len >= 24 + 8 &&
- ieee80211_is_probe_resp(hdr->frame_control)) {
- /* fake header transmission time */
- struct ieee80211_mgmt *mgmt;
- struct ieee80211_rate *txrate;
- /* TODO: get MCS */
- int bitrate = 100;
- u64 ts;
-
- mgmt = (struct ieee80211_mgmt *)skb->data;
- txrate = ieee80211_get_tx_rate(hw, txi);
- if (txrate)
- bitrate = txrate->bitrate;
- ts = mac80211_hwsim_get_sim_tsf();
- mgmt->u.probe_resp.timestamp =
- cpu_to_le64(ts + data->tsf_offset +
- 24 * 8 * 10 / bitrate);
- }
-
- mac80211_hwsim_monitor_rx(hw, skb, channel);
-
/* wmediumd mode check */
_portid = READ_ONCE(data->wmediumd);
ARRAY_SIZE(txi->control.rates));
}
- mac80211_hwsim_monitor_rx(hw, skb, chan);
-
if (_portid || hwsim_virtio_enabled)
return mac80211_hwsim_tx_frame_nl(hw, skb, _portid, chan);
{
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
struct ieee80211_tx_info *info;
- struct ieee80211_rate *txrate;
- struct ieee80211_mgmt *mgmt;
- /* TODO: get MCS */
- int bitrate = 100;
if (vp->skip_beacons[link_conf->link_id]) {
vp->skip_beacons[link_conf->link_id]--;
info->control.rates,
ARRAY_SIZE(info->control.rates));
- txrate = ieee80211_get_tx_rate(hw, info);
- if (txrate)
- bitrate = txrate->bitrate;
-
- mgmt = (struct ieee80211_mgmt *) skb->data;
- /* fake header transmission time */
- data->abs_bcn_ts = mac80211_hwsim_get_sim_tsf();
- if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
- struct ieee80211_ext *ext = (void *) mgmt;
-
- ext->u.s1g_beacon.timestamp = cpu_to_le32(data->abs_bcn_ts +
- data->tsf_offset +
- 10 * 8 * 10 /
- bitrate);
- } else {
- mgmt->u.beacon.timestamp = cpu_to_le64(data->abs_bcn_ts +
- data->tsf_offset +
- 24 * 8 * 10 /
- bitrate);
- }
-
mac80211_hwsim_tx_frame(hw, skb,
rcu_dereference(link_conf->chanctx_conf)->def.chan);
}
if (!found)
goto out;
+ mac80211_hwsim_monitor_rx(data2->hw, skb, data2->channel);
+
/* Tx info received because the frame was broadcasted on user space,
so we get all the necessary info: tx attempts and skb control buff */