Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: add support for radiotap timestamp field

Use the existing device timestamp from the RX status information
to add support for the new radiotap timestamp field. Currently
only 32-bit counters are supported, but we also add the radiotap
mactime where applicable. This new field allows more flexibility
in where the timestamp is taken etc. The non-timestamp data in
the field is taken from a new field in the hw struct.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>

+66
+21
include/net/ieee80211_radiotap.h
··· 190 190 * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16 191 191 * 192 192 * Contains VHT information about this frame. 193 + * 194 + * IEEE80211_RADIOTAP_TIMESTAMP u64, u16, u8, u8 variable 195 + * 196 + * Contains timestamp information for this frame. 193 197 */ 194 198 enum ieee80211_radiotap_type { 195 199 IEEE80211_RADIOTAP_TSFT = 0, ··· 218 214 IEEE80211_RADIOTAP_MCS = 19, 219 215 IEEE80211_RADIOTAP_AMPDU_STATUS = 20, 220 216 IEEE80211_RADIOTAP_VHT = 21, 217 + IEEE80211_RADIOTAP_TIMESTAMP = 22, 221 218 222 219 /* valid in every it_present bitmap, even vendor namespaces */ 223 220 IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, ··· 325 320 #define IEEE80211_RADIOTAP_CODING_LDPC_USER1 0x02 326 321 #define IEEE80211_RADIOTAP_CODING_LDPC_USER2 0x04 327 322 #define IEEE80211_RADIOTAP_CODING_LDPC_USER3 0x08 323 + 324 + /* For IEEE80211_RADIOTAP_TIMESTAMP */ 325 + #define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MASK 0x000F 326 + #define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MS 0x0000 327 + #define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US 0x0001 328 + #define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_NS 0x0003 329 + #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_MASK 0x00F0 330 + #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_BEGIN_MDPU 0x0000 331 + #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU 0x0010 332 + #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_PPDU 0x0020 333 + #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ 0x0030 334 + #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_UNKNOWN 0x00F0 335 + 336 + #define IEEE80211_RADIOTAP_TIMESTAMP_FLAG_64BIT 0x00 337 + #define IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT 0x01 338 + #define IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY 0x02 328 339 329 340 /* helpers */ 330 341 static inline int ieee80211_get_radiotap_len(unsigned char *data)
+12
include/net/mac80211.h
··· 2145 2145 * the default is _GI | _BANDWIDTH. 2146 2146 * Use the %IEEE80211_RADIOTAP_VHT_KNOWN_* values. 2147 2147 * 2148 + * @radiotap_timestamp: Information for the radiotap timestamp field; if the 2149 + * 'units_pos' member is set to a non-negative value it must be set to 2150 + * a combination of a IEEE80211_RADIOTAP_TIMESTAMP_UNIT_* and a 2151 + * IEEE80211_RADIOTAP_TIMESTAMP_SPOS_* value, and then the timestamp 2152 + * field will be added and populated from the &struct ieee80211_rx_status 2153 + * device_timestamp. If the 'accuracy' member is non-negative, it's put 2154 + * into the accuracy radiotap field and the accuracy known flag is set. 2155 + * 2148 2156 * @netdev_features: netdev features to be set in each netdev created 2149 2157 * from this HW. Note that not all features are usable with mac80211, 2150 2158 * other features will be rejected during HW registration. ··· 2196 2188 u8 offchannel_tx_hw_queue; 2197 2189 u8 radiotap_mcs_details; 2198 2190 u16 radiotap_vht_details; 2191 + struct { 2192 + int units_pos; 2193 + s16 accuracy; 2194 + } radiotap_timestamp; 2199 2195 netdev_features_t netdev_features; 2200 2196 u8 uapsd_queues; 2201 2197 u8 uapsd_max_sp_len;
+3
net/mac80211/main.c
··· 660 660 661 661 ieee80211_roc_setup(local); 662 662 663 + local->hw.radiotap_timestamp.units_pos = -1; 664 + local->hw.radiotap_timestamp.accuracy = -1; 665 + 663 666 return &local->hw; 664 667 err_free: 665 668 wiphy_free(wiphy);
+30
net/mac80211/rx.c
··· 180 180 len += 12; 181 181 } 182 182 183 + if (local->hw.radiotap_timestamp.units_pos >= 0) { 184 + len = ALIGN(len, 8); 185 + len += 12; 186 + } 187 + 183 188 if (status->chains) { 184 189 /* antenna and antenna signal fields */ 185 190 len += 2 * hweight8(status->chains); ··· 450 445 pos++; 451 446 /* partial_aid */ 452 447 pos += 2; 448 + } 449 + 450 + if (local->hw.radiotap_timestamp.units_pos >= 0) { 451 + u16 accuracy = 0; 452 + u8 flags = IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT; 453 + 454 + rthdr->it_present |= 455 + cpu_to_le32(1 << IEEE80211_RADIOTAP_TIMESTAMP); 456 + 457 + /* ensure 8 byte alignment */ 458 + while ((pos - (u8 *)rthdr) & 7) 459 + pos++; 460 + 461 + put_unaligned_le64(status->device_timestamp, pos); 462 + pos += sizeof(u64); 463 + 464 + if (local->hw.radiotap_timestamp.accuracy >= 0) { 465 + accuracy = local->hw.radiotap_timestamp.accuracy; 466 + flags |= IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY; 467 + } 468 + put_unaligned_le16(accuracy, pos); 469 + pos += sizeof(u16); 470 + 471 + *pos++ = local->hw.radiotap_timestamp.units_pos; 472 + *pos++ = flags; 453 473 } 454 474 455 475 for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) {