[sniffer] add timestamp information to each captured radio frame (#1971)

Then sniffer devices could provide precise timestamp for each frame.

* The timestamp information is included in the metadata's PHY-specific data field of PROP_STREAM_RAW;

* nRf52840 supports microsecond accuracy timestamp;

* The other platforms support millisecond accuracy timestamp since they don't support microsecond timer for now.
This commit is contained in:
Shu Chen
2017-07-19 22:11:46 -07:00
committed by Jonathan Hui
parent 0193d6ce2e
commit 3883017fd8
12 changed files with 126 additions and 49 deletions
+7
View File
@@ -34,6 +34,7 @@
#include <openthread/config.h>
#include <openthread/openthread.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/diag.h>
#include <openthread/platform/platform.h>
#include <openthread/platform/radio.h>
@@ -433,6 +434,12 @@ void readFrame(void)
length = HWREG(RFCORE_SFR_RFDATA);
otEXPECT(IEEE802154_MIN_LENGTH <= length && length <= IEEE802154_MAX_LENGTH);
#if OPENTHREAD_ENABLE_RAW_LINK_API
// Timestamp
sReceiveFrame.mMsec = otPlatAlarmMilliGetNow();
sReceiveFrame.mUsec = 0; // Don't support microsecond timer for now.
#endif
// read psdu
for (i = 0; i < length - 2; i++)
{
+7
View File
@@ -31,6 +31,7 @@
#include <assert.h>
#include <utils/code_utils.h>
#include "cc2650_radio.h"
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/radio.h>
#include <openthread/platform/random.h> /* to seed the CSMA-CA funciton */
@@ -1776,6 +1777,12 @@ static void readFrame(void)
if (crcCorr->status.bCrcErr == 0 && (len - 2) < OT_RADIO_FRAME_MAX_SIZE)
{
#if OPENTHREAD_ENABLE_RAW_LINK_API
// Timestamp
sReceiveFrame.mMsec = otPlatAlarmMilliGetNow();
sReceiveFrame.mUsec = 0; // Don't support microsecond timer for now.
#endif
sReceiveFrame.mLength = len;
memcpy(sReceiveFrame.mPsdu, &(payload[1]), len - 2);
sReceiveFrame.mChannel = sReceiveCmd.channel;
+11
View File
@@ -31,6 +31,7 @@
* Platform abstraction for radio communication.
*/
#include <openthread/config.h>
#include <openthread/openthread.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/radio.h>
@@ -616,6 +617,11 @@ void FTDF_rcvFrameTransparent(FTDF_DataLength frameLength,
if (frameHeader.frameType != FTDF_ACKNOWLEDGEMENT_FRAME)
{
#if OPENTHREAD_ENABLE_RAW_LINK_API
// Timestamp
sReceiveFrame.mMsec = otPlatAlarmMilliGetNow();
sReceiveFrame.mUsec = 0; // Don't support microsecond timer for now.
#endif
sReceiveFrame.mChannel = sChannel;
sReceiveFrame.mLength = frameLength;
sReceiveFrame.mLqi = lqi;
@@ -626,6 +632,11 @@ void FTDF_rcvFrameTransparent(FTDF_DataLength frameLength,
}
else
{
#if OPENTHREAD_ENABLE_RAW_LINK_API
// Timestamp
sReceiveFrameAck.mMsec = otPlatAlarmMilliGetNow();
sReceiveFrameAck.mUsec = 0; // Don't support microsecond timer for now.
#endif
sReceiveFrameAck.mChannel = sChannel;
sReceiveFrameAck.mLength = frameLength;
sReceiveFrameAck.mLqi = lqi;
+7
View File
@@ -36,6 +36,7 @@
#include <openthread/types.h>
#include <openthread/config.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/platform.h>
#include <openthread/platform/radio.h>
#include <openthread/platform/diag.h>
@@ -687,6 +688,12 @@ void RAILCb_RxPacketReceived(void *aRxPacketHandle)
otLogInfoPlat(sInstance, "Received data:%d", rxPacketInfo->dataLength);
#if OPENTHREAD_ENABLE_RAW_LINK_API
// Timestamp
sReceiveFrame.mMsec = otPlatAlarmMilliGetNow();
sReceiveFrame.mUsec = 0; // Don't support microsecond timer for now.
#endif
memcpy(sReceiveFrame.mPsdu, rxPacketInfo->dataPtr + 1, rxPacketInfo->dataLength);
sReceiveFrame.mPower = rxPacketInfo->appendedInfo.rssiLatch;
sReceiveFrame.mLqi = rxPacketInfo->appendedInfo.lqi;
+8 -1
View File
@@ -35,7 +35,8 @@
#include "openthread/types.h"
#include <utils/code_utils.h>
#include "openthread/platform/radio.h"
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/radio.h>
#include "platform-emsk.h"
#include "device/device_hal/inc/dev_gpio.h"
@@ -459,6 +460,12 @@ void readFrame(void)
otEXPECT_ACTION(IEEE802154_MIN_LENGTH <= length && length <= IEEE802154_MAX_LENGTH, ;);
#if OPENTHREAD_ENABLE_RAW_LINK_API
// Timestamp
sReceiveFrame.mMsec = otPlatAlarmMilliGetNow();
sReceiveFrame.mUsec = 0; // Don't support microsecond timer for now.
#endif
/* Read PSDU */
memcpy(sReceiveFrame.mPsdu, readBuffer, length - 2);
+10 -2
View File
@@ -37,8 +37,10 @@
#include "fsl_device_registers.h"
#include "openthread-core-kw41z-config.h"
#include "fsl_xcvr.h"
#include "openthread/platform/radio.h"
#include "openthread/platform/diag.h"
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/radio.h>
#include <openthread/platform/diag.h>
#include <utils/code_utils.h>
#define DOUBLE_BUFFERING (1)
@@ -722,6 +724,12 @@ static bool rf_process_rx_frame(void)
/* Check if frame is valid */
otEXPECT_ACTION((IEEE802154_MIN_LENGTH <= temp) && (temp <= IEEE802154_MAX_LENGTH), status = false);
#if OPENTHREAD_ENABLE_RAW_LINK_API
// Timestamp
sRxFrame.mMsec = otPlatAlarmMilliGetNow();
sRxFrame.mUsec = 0; // Don't support microsecond timer for now.
#endif
sRxFrame.mLength = temp;
temp = (ZLL->LQI_AND_RSSI & ZLL_LQI_AND_RSSI_LQI_VALUE_MASK) >> ZLL_LQI_AND_RSSI_LQI_VALUE_SHIFT;
sRxFrame.mLqi = rf_lqi_adjust(temp);
+47 -46
View File
@@ -42,6 +42,7 @@
#include <openthread/platform/diag.h>
#include "platform-config.h"
#include "platform-nrf5.h"
#include "cmsis/core_cmFunc.h"
#include <drivers/clock/nrf_drv_clock.h>
@@ -123,51 +124,9 @@ static inline uint64_t TicksToTime(uint32_t aTicks)
return CEIL_DIV((US_PER_S * (uint64_t)aTicks), RTC_FREQUENCY);
}
static inline uint64_t AlarmGetCurrentTime()
{
uint32_t rtcValue1;
uint32_t rtcValue2;
uint32_t offset;
rtcValue1 = nrf_rtc_counter_get(RTC_INSTANCE);
__DMB();
offset = sTimeOffset;
__DMB();
rtcValue2 = nrf_rtc_counter_get(RTC_INSTANCE);
if ((rtcValue2 < rtcValue1) || (rtcValue1 == 0))
{
// Overflow detected. Additional condition (rtcValue1 == 0) covers situation when overflow occurred in
// interrupt state, before this function was entered. But in general, this function shall not be called
// from interrupt other than alarm interrupt.
// Wait at least 20 cycles, to ensure that if interrupt is going to be called, it will be called now.
for (uint32_t i = 0; i < 4; i++)
{
__NOP();
__NOP();
__NOP();
}
// If the event flag is still on, it means that the interrupt was not called, as we are in interrupt state.
if (nrf_rtc_event_pending(RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW))
{
HandleOverflow();
}
offset = sTimeOffset;
}
return US_PER_MS * (uint64_t)offset + TicksToTime(rtcValue2);
}
static inline uint32_t AlarmGetCurrentTimeRtcProtected(AlarmIndex aIndex)
{
uint64_t usecTime = AlarmGetCurrentTime() + 2 * US_PER_TICK;
uint64_t usecTime = nrf5AlarmGetCurrentTime() + 2 * US_PER_TICK;
uint32_t currentTime;
if (aIndex == kMsTimer)
@@ -198,7 +157,7 @@ static void HandleCompareMatch(AlarmIndex aIndex, bool aSkipCheck)
{
nrf_rtc_event_clear(RTC_INSTANCE, sChannelData[aIndex].mCompareEvent);
uint64_t usecTime = AlarmGetCurrentTime();
uint64_t usecTime = nrf5AlarmGetCurrentTime();
uint32_t now;
if (aIndex == kMsTimer)
@@ -344,9 +303,51 @@ void nrf5AlarmProcess(otInstance *aInstance)
}
}
inline uint64_t nrf5AlarmGetCurrentTime()
{
uint32_t rtcValue1;
uint32_t rtcValue2;
uint32_t offset;
rtcValue1 = nrf_rtc_counter_get(RTC_INSTANCE);
__DMB();
offset = sTimeOffset;
__DMB();
rtcValue2 = nrf_rtc_counter_get(RTC_INSTANCE);
if ((rtcValue2 < rtcValue1) || (rtcValue1 == 0))
{
// Overflow detected. Additional condition (rtcValue1 == 0) covers situation when overflow occurred in
// interrupt state, before this function was entered. But in general, this function shall not be called
// from interrupt other than alarm interrupt.
// Wait at least 20 cycles, to ensure that if interrupt is going to be called, it will be called now.
for (uint32_t i = 0; i < 4; i++)
{
__NOP();
__NOP();
__NOP();
}
// If the event flag is still on, it means that the interrupt was not called, as we are in interrupt state.
if (nrf_rtc_event_pending(RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW))
{
HandleOverflow();
}
offset = sTimeOffset;
}
return US_PER_MS * (uint64_t)offset + TicksToTime(rtcValue2);
}
uint32_t otPlatAlarmMilliGetNow(void)
{
return (uint32_t)(AlarmGetCurrentTime() / US_PER_MS);
return (uint32_t)(nrf5AlarmGetCurrentTime() / US_PER_MS);
}
void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
@@ -366,7 +367,7 @@ void otPlatAlarmMilliStop(otInstance *aInstance)
uint32_t otPlatAlarmMicroGetNow(void)
{
return (uint32_t)AlarmGetCurrentTime();
return (uint32_t)nrf5AlarmGetCurrentTime();
}
void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
@@ -77,6 +77,12 @@ void nrf5AlarmDeinit(void);
*/
void nrf5AlarmProcess(otInstance *aInstance);
/**
* Function for geting current time in mircosecond.
*
*/
uint64_t nrf5AlarmGetCurrentTime();
/**
* Initialization of Random Number Generator.
*
+8
View File
@@ -50,6 +50,8 @@
#include <openthread/platform/radio.h>
#include <openthread/platform/diag.h>
#include "platform-nrf5.h"
#include <device/nrf.h>
#include <nrf_drv_radio802154.h>
@@ -60,6 +62,7 @@
#define SHORT_ADDRESS_SIZE 2
#define EXTENDED_ADDRESS_SIZE 8
#define PENDING_BIT 0x10
#define US_PER_MS 1000ULL
enum
{
@@ -628,6 +631,11 @@ void nrf_drv_radio802154_received(uint8_t *p_data, int8_t power, int8_t lqi)
receivedFrame->mPower = power;
receivedFrame->mLqi = lqi;
receivedFrame->mChannel = nrf_drv_radio802154_channel_get();
#if OPENTHREAD_ENABLE_RAW_LINK_API
uint64_t timestamp = nrf5AlarmGetCurrentTime();
receivedFrame->mMsec = timestamp / US_PER_MS;
receivedFrame->mUsec = timestamp - receivedFrame->mMsec * US_PER_MS;
#endif
}
void nrf_drv_radio802154_transmitted(uint8_t *aAckPsdu, int8_t aPower, int8_t aLqi)
+7
View File
@@ -28,6 +28,7 @@
#include "platform-posix.h"
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/diag.h>
#include <openthread/platform/radio.h>
@@ -496,6 +497,12 @@ void radioReceive(otInstance *aInstance)
exit(EXIT_FAILURE);
}
#if OPENTHREAD_ENABLE_RAW_LINK_API
// Timestamp
sReceiveFrame.mMsec = otPlatAlarmMilliGetNow();
sReceiveFrame.mUsec = 0; // Don't support microsecond timer for now.
#endif
sReceiveFrame.mLength = (uint8_t)(rval - 1);
if (sAckWait &&
+4
View File
@@ -107,6 +107,10 @@ typedef struct otRadioFrame
bool mSecurityValid: 1; ///< Security Enabled flag is set and frame passes security checks.
bool mDidTX: 1; ///< Set to true if this frame sent from the radio. Ignored by radio driver.
bool mIsARetx: 1; ///< Set to true if this frame is a retransmission. Should be ignored by radio driver.
#if OPENTHREAD_ENABLE_RAW_LINK_API
uint32_t mMsec; ///< The timestamp when the frame was received (milliseconds).
uint16_t mUsec; ///< The timestamp when the frame was received (microseconds, the offset to mMsec).
#endif
} otRadioFrame;
/**
+4
View File
@@ -1139,6 +1139,8 @@ void NcpBase::LinkRawReceiveDone(otRadioFrame *aFrame, otError aError)
SPINEL_DATATYPE_STRUCT_S( // PHY-data
SPINEL_DATATYPE_UINT8_S // 802.15.4 channel
SPINEL_DATATYPE_UINT8_S // 802.15.4 LQI
SPINEL_DATATYPE_UINT32_S // The timestamp milliseconds
SPINEL_DATATYPE_UINT16_S // The timestamp microseconds
)
SPINEL_DATATYPE_STRUCT_S( // Vendor-data
SPINEL_DATATYPE_UINT_PACKED_S
@@ -1148,6 +1150,8 @@ void NcpBase::LinkRawReceiveDone(otRadioFrame *aFrame, otError aError)
flags, // Flags
aFrame->mChannel, // Receive channel
aFrame->mLqi, // Link quality indicator
aFrame->mMsec, // The timestamp milliseconds
aFrame->mUsec, // The timestamp microseconds, offset to mMsec
aError // Receive error
));