mirror of
https://github.com/espressif/openthread.git
synced 2026-08-23 10:49:51 +00:00
[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:
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user