mirror of
https://github.com/espressif/openthread.git
synced 2026-07-05 20:00:23 +00:00
Compare commits
12 Commits
v2026.07.0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b678a4f63b | |||
| 3481946bfa | |||
| 471460c610 | |||
| a4bf4f9899 | |||
| ef9c8de3cd | |||
| e4930db19d | |||
| 63f325229b | |||
| adac57a6e8 | |||
| e299ad29e4 | |||
| 1d4900609d | |||
| a56a79bcb7 | |||
| 4c44ff1edb |
@@ -107,6 +107,25 @@ jobs:
|
||||
cmake --build --preset simulation
|
||||
ctest --preset simulation
|
||||
|
||||
cmake-presets-ccm-one-shot:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
with:
|
||||
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Bootstrap
|
||||
run: |
|
||||
sudo apt-get --no-install-recommends install -y build-essential ninja-build libreadline-dev libncurses-dev
|
||||
- name: Build and test with platform CCM one-shot enabled
|
||||
run: |
|
||||
cmake --preset simulation -DOT_CRYPTO_CCM_ONE_SHOT=ON
|
||||
cmake --build --preset simulation
|
||||
ctest --preset simulation
|
||||
|
||||
cmake-version:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
|
||||
@@ -307,6 +307,7 @@ endif()
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
set(OT_CRYPTO_LIB_VALUES "MBEDTLS" "PSA" "PLATFORM")
|
||||
ot_multi_option(OT_CRYPTO_LIB OT_CRYPTO_LIB_VALUES OPENTHREAD_CONFIG_CRYPTO_LIB OPENTHREAD_CONFIG_CRYPTO_LIB_ "set Crypto backend library")
|
||||
ot_option(OT_CRYPTO_CCM_ONE_SHOT OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE "platform one-shot AES-CCM* hook")
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
set(OT_THREAD_VERSION_VALUES "1.1" "1.2" "1.3" "1.3.1" "1.4")
|
||||
|
||||
@@ -1041,7 +1041,7 @@ exit:
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t otPlatRadioGetNow(otInstance *aInstance)
|
||||
otRadioTime64 otPlatRadioGetNow(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
@@ -1109,7 +1109,7 @@ otError otPlatRadioResetCsl(otInstance *aInstance)
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, uint32_t aCslSampleTime)
|
||||
void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, otRadioTime32 aCslSampleTime)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
|
||||
@@ -345,7 +345,7 @@ typedef struct otRadioContext
|
||||
otExtAddress mExtAddress; ///< In little-endian byte order.
|
||||
uint32_t mMacFrameCounter;
|
||||
uint32_t mPrevMacFrameCounter;
|
||||
uint32_t mCslSampleTime; ///< The sample time based on the microsecond timer.
|
||||
otRadioTime32 mCslSampleTime; ///< The sample time based on the microsecond timer.
|
||||
uint16_t mCslPeriod; ///< In unit of 10 symbols.
|
||||
otShortAddress mCslShortAddress; ///< The short address of the CSL receiver's peer.
|
||||
otExtAddress mCslExtAddress; ///< The extended address of the CSL receiver's peer.
|
||||
|
||||
@@ -52,7 +52,7 @@ extern "C" {
|
||||
*
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (609)
|
||||
#define OPENTHREAD_API_VERSION (610)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -749,6 +749,51 @@ otError otPlatCryptoPbkdf2GenerateKey(const uint8_t *aPassword,
|
||||
uint16_t aKeyLen,
|
||||
uint8_t *aKey);
|
||||
|
||||
/**
|
||||
* @struct otPlatCryptoAesCcmConfig
|
||||
*
|
||||
* Holds the parameters for a one-shot AES-CCM* operation passed to `otPlatCryptoAesCcmProcessOneShot`.
|
||||
*/
|
||||
typedef struct otPlatCryptoAesCcmConfig
|
||||
{
|
||||
otCryptoKey mKey; ///< The encryption key.
|
||||
const uint8_t *mNonce; ///< Pointer to the nonce buffer (IEEE 802.15.4 CCM* format, 13 bytes).
|
||||
uint8_t mNonceLength; ///< Length of @p mNonce in bytes.
|
||||
uint8_t mTagLength; ///< Authentication tag length in bytes (even)
|
||||
uint32_t mHeaderLength; ///< Length of the additional authenticated data (header) in bytes.
|
||||
uint32_t mPlainTextLength; ///< Payload length in bytes (excluding tag).
|
||||
} otPlatCryptoAesCcmConfig;
|
||||
|
||||
/**
|
||||
* Performs in-place AES-CCM* authenticated encryption or decryption in a single call.
|
||||
*
|
||||
* For encryption (@p aEncrypt == true):
|
||||
* - Plaintext at @p aData is replaced with ciphertext in-place.
|
||||
* - The authentication tag is written to @p aData + @p aConfig->mPlainTextLength.
|
||||
*
|
||||
* For decryption (@p aEncrypt == false):
|
||||
* - Ciphertext at @p aData is replaced with plaintext in-place.
|
||||
* - The tag to verify must be at @p aData + @p aConfig->mPlainTextLength.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE`.
|
||||
*
|
||||
* Default weak mbedTLS and PSA implementations are provided.
|
||||
*
|
||||
* @param[in] aEncrypt True to encrypt and generate tag; false to decrypt and verify tag.
|
||||
* @param[in] aConfig CCM* parameters (key, nonce, lengths).
|
||||
* @param[in] aHeader Additional authenticated data (not encrypted). May be NULL if header length is 0.
|
||||
* @param[in,out] aData Payload buffer (plaintext on encrypt entry, ciphertext on decrypt entry).
|
||||
* The buffer must hold @p aConfig->mPlainTextLength + @p aConfig->mTagLength bytes.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Success.
|
||||
* @retval OT_ERROR_SECURITY Tag mismatch (decrypt only).
|
||||
* @retval OT_ERROR_FAILED Operation failed.
|
||||
*/
|
||||
otError otPlatCryptoAesCcmProcessOneShot(bool aEncrypt,
|
||||
const otPlatCryptoAesCcmConfig *aConfig,
|
||||
const uint8_t *aHeader,
|
||||
uint8_t *aData);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -183,6 +183,25 @@ struct otExtAddress
|
||||
*/
|
||||
typedef struct otExtAddress otExtAddress;
|
||||
|
||||
/**
|
||||
* Represents a 64-bit radio time in microseconds referenced to a continuous monotonic local radio clock.
|
||||
*
|
||||
* This type is returned by `otPlatRadioGetNow()` and is used as the timestamp field (`mTimestamp`) in radio frames
|
||||
* (`otRadioFrame`).
|
||||
*/
|
||||
typedef uint64_t otRadioTime64;
|
||||
|
||||
/**
|
||||
* Represents a 32-bit radio time in microseconds.
|
||||
*
|
||||
* This type holds the lower 32 bits (least significant bits) of a full 64-bit radio time (`otRadioTime64`).
|
||||
*
|
||||
* It is used in APIs such as `otPlatRadioReceiveAt()` and `otPlatRadioUpdateCslSampleTime()` and as the transmission
|
||||
* delay base time (`mTxDelayBaseTime`) in `otRadioFrame`. It is important for radio platform implementations to
|
||||
* correctly account for its roll-over.
|
||||
*/
|
||||
typedef uint32_t otRadioTime32;
|
||||
|
||||
#define OT_MAC_KEY_SIZE 16 ///< Size of the MAC Key in bytes.
|
||||
|
||||
/**
|
||||
@@ -273,7 +292,7 @@ typedef struct otRadioFrame
|
||||
*
|
||||
* This field does not affect CCA behavior which is controlled by `mCsmaCaEnabled`.
|
||||
*/
|
||||
uint32_t mTxDelayBaseTime;
|
||||
otRadioTime32 mTxDelayBaseTime;
|
||||
|
||||
/**
|
||||
* The delay time in microseconds for this transmission referenced
|
||||
@@ -381,7 +400,7 @@ typedef struct otRadioFrame
|
||||
*
|
||||
* The platform should update this field before otPlatRadioTxStarted() is fired for each transmit attempt.
|
||||
*/
|
||||
uint64_t mTimestamp;
|
||||
otRadioTime64 mTimestamp;
|
||||
} mTxInfo;
|
||||
|
||||
/**
|
||||
@@ -393,7 +412,7 @@ typedef struct otRadioFrame
|
||||
* The time of the local radio clock in microseconds when the end of
|
||||
* the SFD was present at the local antenna.
|
||||
*/
|
||||
uint64_t mTimestamp;
|
||||
otRadioTime64 mTimestamp;
|
||||
|
||||
uint32_t mAckFrameCounter; ///< ACK security frame counter (applicable when `mAckedWithSecEnhAck` is set).
|
||||
uint8_t mAckKeyId; ///< ACK security key index (applicable when `mAckedWithSecEnhAck` is set).
|
||||
@@ -765,7 +784,7 @@ void otPlatRadioSetMacFrameCounterIfLarger(otInstance *aInstance, uint32_t aMacF
|
||||
* @returns The current time in microseconds. UINT64_MAX when platform does not
|
||||
* support or radio time is not ready.
|
||||
*/
|
||||
uint64_t otPlatRadioGetNow(otInstance *aInstance);
|
||||
otRadioTime64 otPlatRadioGetNow(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Get the bus speed in bits/second between the host and the radio chip.
|
||||
@@ -894,7 +913,7 @@ otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel);
|
||||
* @retval OT_ERROR_NONE Successfully scheduled receive window.
|
||||
* @retval OT_ERROR_FAILED The receive window could not be scheduled. For example, if @p aStart is in the past.
|
||||
*/
|
||||
otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, uint32_t aStart, uint32_t aDuration);
|
||||
otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, otRadioTime32 aStart, uint32_t aDuration);
|
||||
|
||||
/**
|
||||
* The radio driver calls this function to notify OpenThread of a received frame.
|
||||
@@ -1225,7 +1244,7 @@ otError otPlatRadioResetCsl(otInstance *aInstance);
|
||||
* the time when the first symbol of the MHR of
|
||||
* the frame is expected.
|
||||
*/
|
||||
void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, uint32_t aCslSampleTime);
|
||||
void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, otRadioTime32 aCslSampleTime);
|
||||
|
||||
/**
|
||||
* Get the current estimated worst case accuracy (maximum ± deviation from the
|
||||
|
||||
@@ -196,6 +196,10 @@ build_all_features()
|
||||
|
||||
reset_source
|
||||
"$(dirname "$0")"/cmake-build simulation -DOT_BLE_TCAT=ON
|
||||
|
||||
# Build with platform CCM one-shot enabled
|
||||
reset_source
|
||||
"$(dirname "$0")"/cmake-build simulation -DOT_CRYPTO_CCM_ONE_SHOT=ON
|
||||
}
|
||||
|
||||
build_nest_common()
|
||||
|
||||
@@ -663,6 +663,8 @@ openthread_core_files = [
|
||||
"radio/radio.hpp",
|
||||
"radio/radio_callbacks.cpp",
|
||||
"radio/radio_platform.cpp",
|
||||
"radio/radio_types.cpp",
|
||||
"radio/radio_types.hpp",
|
||||
"radio/trel_interface.cpp",
|
||||
"radio/trel_interface.hpp",
|
||||
"radio/trel_link.cpp",
|
||||
@@ -857,6 +859,7 @@ openthread_radio_sources = [
|
||||
"radio/radio.cpp",
|
||||
"radio/radio_callbacks.cpp",
|
||||
"radio/radio_platform.cpp",
|
||||
"radio/radio_types.cpp",
|
||||
"thread/link_quality.cpp",
|
||||
"utils/parse_cmdline.cpp",
|
||||
"utils/power_calibration.cpp",
|
||||
|
||||
@@ -224,6 +224,7 @@ set(COMMON_SOURCES
|
||||
radio/radio.cpp
|
||||
radio/radio_callbacks.cpp
|
||||
radio/radio_platform.cpp
|
||||
radio/radio_types.cpp
|
||||
radio/trel_interface.cpp
|
||||
radio/trel_link.cpp
|
||||
radio/trel_packet.cpp
|
||||
@@ -339,6 +340,7 @@ set(RADIO_COMMON_SOURCES
|
||||
radio/radio.cpp
|
||||
radio/radio_callbacks.cpp
|
||||
radio/radio_platform.cpp
|
||||
radio/radio_types.cpp
|
||||
thread/link_quality.cpp
|
||||
utils/otns.cpp
|
||||
utils/parse_cmdline.cpp
|
||||
|
||||
@@ -49,7 +49,7 @@ otError otDnsGetNextTxtEntry(otDnsTxtEntryIterator *aIterator, otDnsTxtEntry *aE
|
||||
}
|
||||
|
||||
otError otDnsEncodeTxtData(const otDnsTxtEntry *aTxtEntries,
|
||||
uint8_t aNumTxtEntries,
|
||||
uint16_t aNumTxtEntries,
|
||||
uint8_t *aTxtData,
|
||||
uint16_t *aTxtDataLength)
|
||||
{
|
||||
|
||||
@@ -38,6 +38,19 @@
|
||||
|
||||
namespace ot {
|
||||
|
||||
uint8_t CountBitsInMask(uint32_t aMask)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
|
||||
while (aMask != 0)
|
||||
{
|
||||
aMask &= aMask - 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
uint16_t CountMatchingBits(const uint8_t *aFirst, const uint8_t *aSecond, uint16_t aMaxBitLength)
|
||||
{
|
||||
uint16_t remainingLen = aMaxBitLength;
|
||||
@@ -79,4 +92,17 @@ exit:
|
||||
return matchedLen;
|
||||
}
|
||||
|
||||
uint8_t DetermineMinBitSizeFor(uint32_t aValue)
|
||||
{
|
||||
uint8_t bitSize = 0;
|
||||
|
||||
do
|
||||
{
|
||||
bitSize++;
|
||||
aValue >>= 1;
|
||||
} while (aValue != 0);
|
||||
|
||||
return bitSize;
|
||||
}
|
||||
|
||||
} // namespace ot
|
||||
|
||||
@@ -61,28 +61,13 @@ static constexpr uint8_t kBitsPerByte = 8; ///< Number of bits in a byte.
|
||||
#define BytesForBitSize(aBitSize) static_cast<uint8_t>(((aBitSize) + (kBitsPerByte - 1)) / kBitsPerByte)
|
||||
|
||||
/**
|
||||
* Counts the number of `1` bits in the binary representation of a given unsigned int bit-mask value.
|
||||
*
|
||||
* @tparam UintType The unsigned int type (MUST be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`).
|
||||
* Counts the number of `1` bits in the binary representation of a given `uint32_t` bit-mask value.
|
||||
*
|
||||
* @param[in] aMask A bit mask.
|
||||
*
|
||||
* @returns The number of `1` bits in @p aMask.
|
||||
*/
|
||||
template <typename UintType> uint8_t CountBitsInMask(UintType aMask)
|
||||
{
|
||||
static_assert(TypeTraits::IsUint<UintType>::kValue, "UintType must be an unsigned int (8, 16, 32, or 64 bit len)");
|
||||
|
||||
uint8_t count = 0;
|
||||
|
||||
while (aMask != 0)
|
||||
{
|
||||
aMask &= aMask - 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
uint8_t CountBitsInMask(uint32_t aMask);
|
||||
|
||||
/**
|
||||
* Counts the number of consecutive matching bits between two byte arrays.
|
||||
@@ -102,6 +87,17 @@ template <typename UintType> uint8_t CountBitsInMask(UintType aMask)
|
||||
*/
|
||||
uint16_t CountMatchingBits(const uint8_t *aFirst, const uint8_t *aSecond, uint16_t aMaxBitLength);
|
||||
|
||||
/**
|
||||
* Determines the minimum number of bits required to represent a given integer value.
|
||||
*
|
||||
* @note For a value of `0`, this function returns `1`.
|
||||
*
|
||||
* @param[in] aValue The 32-bit unsigned integer value.
|
||||
*
|
||||
* @returns The minimum number of bits required to represent @p aValue.
|
||||
*/
|
||||
uint8_t DetermineMinBitSizeFor(uint32_t aValue);
|
||||
|
||||
/**
|
||||
* Sets the specified bit in a given integer to 1.
|
||||
*
|
||||
|
||||
@@ -297,6 +297,25 @@ public:
|
||||
*/
|
||||
void RemoveBytes(uint16_t aOffset, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Reads a pointer to a previously appended object in the `FrameBuilder` at a given byte offset.
|
||||
*
|
||||
* This method does not perform any bounds checking. The caller MUST ensure the object of type `ObjectType`
|
||||
* fits within the previously appended content.
|
||||
*
|
||||
* @tparam ObjectType The object type to read.
|
||||
*
|
||||
* @param[in] aOffset The byte offset where the object starts.
|
||||
*
|
||||
* @returns A pointer to the `ObjectType` at @p aOffset.
|
||||
*/
|
||||
template <typename ObjectType> ObjectType *Read(uint16_t aOffset)
|
||||
{
|
||||
static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
|
||||
|
||||
return reinterpret_cast<ObjectType *>(mBuffer + aOffset);
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t *mBuffer;
|
||||
uint16_t mLength;
|
||||
|
||||
@@ -68,6 +68,19 @@
|
||||
#define OPENTHREAD_CONFIG_CRYPTO_PLATFORM_ALLOCS_CONTEXT 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
*
|
||||
* Define to 1 to enable platform one-shot AES-CCM* acceleration.
|
||||
*
|
||||
* When enabled, `AesCcm::Engine::ProcessOneShot()` calls
|
||||
* `otPlatCryptoAesCcmProcessOneShot()` instead of the built-in
|
||||
* software CCM engine.
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
#define OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_PLATFORM
|
||||
|
||||
/**
|
||||
|
||||
@@ -409,16 +409,6 @@
|
||||
#define OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME
|
||||
*
|
||||
* Define to 1 to enable support for IEEE 802.15.4 MAC Multipurpose frame format.
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME
|
||||
#define OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME \
|
||||
(OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MAC_CSL_AUTO_SYNC_ENABLE
|
||||
*
|
||||
|
||||
@@ -702,4 +702,9 @@
|
||||
#error "OPENTHREAD_CONFIG_MLE_IP_ADDRS_TO_REGISTER is removed. All addresses are now registered."
|
||||
#endif
|
||||
|
||||
#ifdef OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME
|
||||
#error "OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME was removed and is no longer supported. " \
|
||||
"It was originally implemented as a provisional solution for the wake mechanism."
|
||||
#endif
|
||||
|
||||
#endif // OT_CORE_CONFIG_OPENTHREAD_CORE_CONFIG_CHECK_H_
|
||||
|
||||
@@ -212,13 +212,11 @@ Error AesCcm::Engine::ProcessOneShot(Operation aOperation,
|
||||
const uint8_t *aHeader,
|
||||
uint8_t *aData)
|
||||
{
|
||||
// This method performs one-shot (single-part) AES-CCM processing.
|
||||
// Currently, it is implemented by calling the multi-part
|
||||
// streaming APIs sequentially. In the future, this can be
|
||||
// optimized to directly call platform-specific one-shot hardware
|
||||
// acceleration APIs if supported by the platform.
|
||||
Error error = kErrorNone;
|
||||
|
||||
Error error = kErrorNone;
|
||||
#if OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
error = otPlatCryptoAesCcmProcessOneShot(aOperation == kEncrypt, &aConfig, aHeader, aData);
|
||||
#else
|
||||
uint8_t tag[kMaxTagLength];
|
||||
|
||||
Start(aConfig);
|
||||
@@ -236,6 +234,7 @@ Error AesCcm::Engine::ProcessOneShot(Operation aOperation,
|
||||
error = (memcmp(aData + aConfig.mPlainTextLength, tag, aConfig.mTagLength) == 0) ? kErrorNone : kErrorSecurity;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -249,7 +248,7 @@ void AesCcm::Engine::Start(const Config &aConfig)
|
||||
|
||||
OT_ASSERT(aConfig.IsValid());
|
||||
|
||||
mEcb.SetKey(aConfig.mKey);
|
||||
mEcb.SetKey(aConfig.GetKey());
|
||||
|
||||
mNonceLength = aConfig.mNonceLength;
|
||||
mTagLength = aConfig.mTagLength;
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
* @param[in] aKey A pointer to the key.
|
||||
* @param[in] aKeyLength Length of the key in bytes.
|
||||
*/
|
||||
void SetKey(const uint8_t *aKey, uint16_t aKeyLength) { mConfig.mKey.Set(aKey, aKeyLength); }
|
||||
void SetKey(const uint8_t *aKey, uint16_t aKeyLength) { mConfig.GetKey().Set(aKey, aKeyLength); }
|
||||
|
||||
/**
|
||||
* Sets the key.
|
||||
@@ -128,7 +128,7 @@ public:
|
||||
*
|
||||
* @param[in] aMacKey Key Material for AES operation.
|
||||
*/
|
||||
void SetKey(const Mac::KeyMaterial &aMacKey) { aMacKey.ConvertToCryptoKey(mConfig.mKey); }
|
||||
void SetKey(const Mac::KeyMaterial &aMacKey) { aMacKey.ConvertToCryptoKey(mConfig.GetKey()); }
|
||||
|
||||
/**
|
||||
* Sets the Nonce.
|
||||
@@ -245,16 +245,11 @@ public:
|
||||
void *aTag);
|
||||
|
||||
private:
|
||||
struct Config : public Clearable<Config>
|
||||
struct Config : public otPlatCryptoAesCcmConfig, public Clearable<Config>
|
||||
{
|
||||
bool IsValid(void) const;
|
||||
|
||||
Key mKey;
|
||||
uint8_t mNonceLength;
|
||||
uint8_t mTagLength;
|
||||
uint32_t mHeaderLength;
|
||||
uint32_t mPlainTextLength;
|
||||
const uint8_t *mNonce;
|
||||
bool IsValid(void) const;
|
||||
Key &GetKey(void) { return AsCoreType(&mKey); }
|
||||
const Key &GetKey(void) const { return AsCoreType(&mKey); }
|
||||
};
|
||||
|
||||
class Engine
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/ccm.h>
|
||||
#include <mbedtls/cmac.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/ecdsa.h>
|
||||
@@ -152,6 +153,59 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
|
||||
OT_TOOL_WEAK otError otPlatCryptoAesCcmProcessOneShot(bool aEncrypt,
|
||||
const otPlatCryptoAesCcmConfig *aConfig,
|
||||
const uint8_t *aHeader,
|
||||
uint8_t *aData)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
mbedtls_ccm_context ctx;
|
||||
int ret;
|
||||
|
||||
mbedtls_ccm_init(&ctx);
|
||||
|
||||
VerifyOrExit(aConfig != nullptr && aConfig->mNonce != nullptr && aData != nullptr, error = kErrorInvalidArgs);
|
||||
|
||||
{
|
||||
const LiteralKey key(*static_cast<const Key *>(&aConfig->mKey));
|
||||
|
||||
ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key.GetBytes(), key.GetLength() * kBitsPerByte);
|
||||
VerifyOrExit(ret == 0, error = kErrorFailed);
|
||||
|
||||
if (aEncrypt)
|
||||
{
|
||||
ret = mbedtls_ccm_encrypt_and_tag(&ctx, aConfig->mPlainTextLength, aConfig->mNonce, aConfig->mNonceLength,
|
||||
aHeader, aConfig->mHeaderLength, aData, aData,
|
||||
aData + aConfig->mPlainTextLength, aConfig->mTagLength);
|
||||
VerifyOrExit(ret == 0, error = kErrorFailed);
|
||||
}
|
||||
else
|
||||
{
|
||||
// MBEDTLS_ERR_CCM_AUTH_FAILED is the expected return on tag mismatch; map to kErrorSecurity.
|
||||
ret = mbedtls_ccm_auth_decrypt(&ctx, aConfig->mPlainTextLength, aConfig->mNonce, aConfig->mNonceLength,
|
||||
aHeader, aConfig->mHeaderLength, aData, aData,
|
||||
aData + aConfig->mPlainTextLength, aConfig->mTagLength);
|
||||
|
||||
if (ret == MBEDTLS_ERR_CCM_AUTH_FAILED)
|
||||
{
|
||||
error = kErrorSecurity;
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(ret == 0, error = kErrorFailed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_ccm_free(&ctx);
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
|
||||
// HMAC implementations
|
||||
|
||||
@@ -389,6 +389,49 @@ OT_TOOL_WEAK otError otPlatCryptoAesFree(otCryptoContext *aContext)
|
||||
return kErrorNone;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
|
||||
OT_TOOL_WEAK otError otPlatCryptoAesCcmProcessOneShot(bool aEncrypt,
|
||||
const otPlatCryptoAesCcmConfig *aConfig,
|
||||
const uint8_t *aHeader,
|
||||
uint8_t *aData)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
psa_status_t status;
|
||||
psa_algorithm_t algorithm;
|
||||
size_t outputLen = 0;
|
||||
|
||||
VerifyOrExit(aConfig != nullptr && aConfig->mNonce != nullptr && aData != nullptr, error = kErrorInvalidArgs);
|
||||
VerifyOrExit(aConfig->mKey.mKey == nullptr, error = kErrorInvalidArgs);
|
||||
|
||||
algorithm = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, aConfig->mTagLength);
|
||||
|
||||
if (aEncrypt)
|
||||
{
|
||||
// Output layout: ciphertext || tag, written in-place over the plaintext buffer.
|
||||
status = psa_aead_encrypt(aConfig->mKey.mKeyRef, algorithm, aConfig->mNonce, aConfig->mNonceLength, aHeader,
|
||||
aConfig->mHeaderLength, aData, aConfig->mPlainTextLength, aData,
|
||||
aConfig->mPlainTextLength + aConfig->mTagLength, &outputLen);
|
||||
SuccessOrExit(error = PsaToOtError(status));
|
||||
VerifyOrExit(outputLen == aConfig->mPlainTextLength + aConfig->mTagLength, error = kErrorFailed);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Input layout: ciphertext || tag contiguous at aData. Output plaintext written in-place.
|
||||
status = psa_aead_decrypt(aConfig->mKey.mKeyRef, algorithm, aConfig->mNonce, aConfig->mNonceLength, aHeader,
|
||||
aConfig->mHeaderLength, aData, aConfig->mPlainTextLength + aConfig->mTagLength, aData,
|
||||
aConfig->mPlainTextLength, &outputLen);
|
||||
error = (status == PSA_ERROR_INVALID_SIGNATURE) ? kErrorSecurity : PsaToOtError(status);
|
||||
SuccessOrExit(error);
|
||||
VerifyOrExit(outputLen == aConfig->mPlainTextLength, error = kErrorFailed);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
|
||||
OT_TOOL_WEAK otError otPlatCryptoHmacSha256Init(otCryptoContext *aContext)
|
||||
|
||||
@@ -539,36 +539,36 @@ uint32_t DataPollSender::GetDefaultPollPeriod(void) const
|
||||
|
||||
Mac::TxFrame *DataPollSender::PrepareDataRequest(Mac::TxFrames &aTxFrames)
|
||||
{
|
||||
Mac::TxFrame *frame = nullptr;
|
||||
Mac::TxFrame::Info frameInfo;
|
||||
Mac::TxFrame *frame = nullptr;
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
Mac::RadioType radio;
|
||||
|
||||
SuccessOrExit(GetPollDestinationAddress(frameInfo.mAddrs.mDestination, radio));
|
||||
SuccessOrExit(GetPollDestinationAddress(buildInfo.mAddrs.mDestination, radio));
|
||||
frame = &aTxFrames.GetTxFrame(radio);
|
||||
#else
|
||||
SuccessOrExit(GetPollDestinationAddress(frameInfo.mAddrs.mDestination));
|
||||
SuccessOrExit(GetPollDestinationAddress(buildInfo.mAddrs.mDestination));
|
||||
frame = &aTxFrames.GetTxFrame();
|
||||
#endif
|
||||
|
||||
if (frameInfo.mAddrs.mDestination.IsExtended())
|
||||
if (buildInfo.mAddrs.mDestination.IsExtended())
|
||||
{
|
||||
frameInfo.mAddrs.mSource.SetExtended(Get<Mac::Mac>().GetExtAddress());
|
||||
buildInfo.mAddrs.mSource.SetExtended(Get<Mac::Mac>().GetExtAddress());
|
||||
}
|
||||
else
|
||||
{
|
||||
frameInfo.mAddrs.mSource.SetShort(Get<Mac::Mac>().GetShortAddress());
|
||||
buildInfo.mAddrs.mSource.SetShort(Get<Mac::Mac>().GetShortAddress());
|
||||
}
|
||||
|
||||
frameInfo.mPanIds.SetBothSourceDestination(Get<Mac::Mac>().GetPanId());
|
||||
buildInfo.mPanIds.SetBothSourceDestination(Get<Mac::Mac>().GetPanId());
|
||||
|
||||
frameInfo.mType = Mac::Frame::kTypeMacCmd;
|
||||
frameInfo.mCommandId = Mac::Frame::kMacCmdDataRequest;
|
||||
frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
frameInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1;
|
||||
buildInfo.mType = Mac::Frame::kTypeMacCmd;
|
||||
buildInfo.mCommandId = Mac::Frame::kMacCmdDataRequest;
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
buildInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1;
|
||||
|
||||
Get<MessageFramer>().PrepareMacHeaders(*frame, frameInfo, nullptr);
|
||||
Get<MessageFramer>().PrepareMacHeaders(*frame, buildInfo, nullptr);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
if (frame->Has<Mac::CslIe>())
|
||||
|
||||
@@ -253,9 +253,9 @@ Error LinkRaw::SetMacKey(uint8_t aKeyIdMode,
|
||||
|
||||
VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
|
||||
|
||||
prevKey.SetFrom(aPrevKey);
|
||||
currKey.SetFrom(aCurrKey);
|
||||
nextKey.SetFrom(aNextKey);
|
||||
prevKey.SetFrom(aPrevKey, kDefaultMacKeysExportable);
|
||||
currKey.SetFrom(aCurrKey, kDefaultMacKeysExportable);
|
||||
nextKey.SetFrom(aNextKey, kDefaultMacKeysExportable);
|
||||
|
||||
mSubMac.SetMacKey(aKeyIdMode, aKeyId, prevKey, currKey, nextKey);
|
||||
|
||||
|
||||
+24
-24
@@ -705,18 +705,18 @@ void Mac::FinishOperation(void)
|
||||
|
||||
TxFrame *Mac::PrepareBeaconRequest(TxFrames &aTxFrames)
|
||||
{
|
||||
TxFrame &frame = aTxFrames.GetBroadcastTxFrame();
|
||||
TxFrame::Info frameInfo;
|
||||
TxFrame &frame = aTxFrames.GetBroadcastTxFrame();
|
||||
TxFrame::BuildInfo buildInfo;
|
||||
|
||||
frameInfo.mAddrs.mSource.SetNone();
|
||||
frameInfo.mAddrs.mDestination.SetShort(kShortAddrBroadcast);
|
||||
frameInfo.mPanIds.SetDestination(kShortAddrBroadcast);
|
||||
buildInfo.mAddrs.mSource.SetNone();
|
||||
buildInfo.mAddrs.mDestination.SetShort(kShortAddrBroadcast);
|
||||
buildInfo.mPanIds.SetDestination(kShortAddrBroadcast);
|
||||
|
||||
frameInfo.mType = Frame::kTypeMacCmd;
|
||||
frameInfo.mCommandId = Frame::kMacCmdBeaconRequest;
|
||||
frameInfo.mVersion = Frame::kVersion2003;
|
||||
buildInfo.mType = Frame::kTypeMacCmd;
|
||||
buildInfo.mCommandId = Frame::kMacCmdBeaconRequest;
|
||||
buildInfo.mVersion = Frame::kVersion2003;
|
||||
|
||||
frameInfo.PrepareHeadersIn(frame);
|
||||
buildInfo.PrepareHeadersIn(frame);
|
||||
|
||||
LogInfo("Sending Beacon Request");
|
||||
|
||||
@@ -725,9 +725,9 @@ TxFrame *Mac::PrepareBeaconRequest(TxFrames &aTxFrames)
|
||||
|
||||
TxFrame *Mac::PrepareBeacon(TxFrames &aTxFrames)
|
||||
{
|
||||
TxFrame *frame;
|
||||
TxFrame::Info frameInfo;
|
||||
Beacon *beacon = nullptr;
|
||||
TxFrame *frame;
|
||||
TxFrame::BuildInfo buildInfo;
|
||||
Beacon *beacon = nullptr;
|
||||
#if OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE
|
||||
uint8_t beaconLength;
|
||||
BeaconPayload *beaconPayload = nullptr;
|
||||
@@ -741,14 +741,14 @@ TxFrame *Mac::PrepareBeacon(TxFrames &aTxFrames)
|
||||
frame = &aTxFrames.GetBroadcastTxFrame();
|
||||
#endif
|
||||
|
||||
frameInfo.mAddrs.mSource.SetExtended(GetExtAddress());
|
||||
frameInfo.mPanIds.SetSource(mPanId);
|
||||
frameInfo.mAddrs.mDestination.SetNone();
|
||||
buildInfo.mAddrs.mSource.SetExtended(GetExtAddress());
|
||||
buildInfo.mPanIds.SetSource(mPanId);
|
||||
buildInfo.mAddrs.mDestination.SetNone();
|
||||
|
||||
frameInfo.mType = Frame::kTypeBeacon;
|
||||
frameInfo.mVersion = Frame::kVersion2003;
|
||||
buildInfo.mType = Frame::kTypeBeacon;
|
||||
buildInfo.mVersion = Frame::kVersion2003;
|
||||
|
||||
frameInfo.PrepareHeadersIn(*frame);
|
||||
buildInfo.PrepareHeadersIn(*frame);
|
||||
|
||||
beacon = reinterpret_cast<Beacon *>(frame->GetPayload());
|
||||
beacon->Init();
|
||||
@@ -2498,7 +2498,7 @@ void Mac::ProcessCsl(const RxFrame &aFrame, const Address &aSrcAddr)
|
||||
neighbor->SetCslLastHeard(TimerMilli::GetNow());
|
||||
neighbor->SetLastRxTimestamp(aFrame.GetTimestamp());
|
||||
LogDebg("Timestamp=%lu Sequence=%u CslPeriod=%u CslPhase=%u TransmitPhase=%u",
|
||||
ToUlong(static_cast<uint32_t>(aFrame.GetTimestamp())), aFrame.GetSequence(), csl->GetPeriod(),
|
||||
ToUlong(ConvertRadioTime64To32(aFrame.GetTimestamp())), aFrame.GetSequence(), csl->GetPeriod(),
|
||||
csl->GetPhase(), neighbor->GetCslPhase());
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
@@ -2622,9 +2622,9 @@ Error Mac::HandleWakeupFrame(const RxFrame &aFrame)
|
||||
const ConnectionIe *connectionIe;
|
||||
Address srcAddress;
|
||||
WakeupInfo wakeupInfo;
|
||||
uint32_t rvTimeUs;
|
||||
uint64_t rvTimestampUs;
|
||||
uint64_t radioNowUs;
|
||||
RadioTime32 rvTimeUs;
|
||||
RadioTime64 rvTimestampUs;
|
||||
RadioTime64 radioNowUs;
|
||||
|
||||
VerifyOrExit(mWakeupListenEnabled && aFrame.IsWakeupFrame());
|
||||
|
||||
@@ -2637,13 +2637,13 @@ Error Mac::HandleWakeupFrame(const RxFrame &aFrame)
|
||||
wakeupInfo.mRetryCount = connectionIe->GetRetryCount();
|
||||
VerifyOrExit(wakeupInfo.mRetryInterval > 0 && wakeupInfo.mRetryCount > 0, error = kErrorInvalidArgs);
|
||||
|
||||
radioNowUs = otPlatRadioGetNow(&GetInstance());
|
||||
radioNowUs = Get<Radio>().GetNow();
|
||||
rvTimeUs = aFrame.Find<RendezvousTimeIe>()->GetRendezvousTime() * kUsPerTenSymbols;
|
||||
rvTimestampUs = aFrame.GetTimestamp() + kRadioHeaderPhrDuration + aFrame.GetLength() * kOctetDuration + rvTimeUs;
|
||||
|
||||
if (rvTimestampUs > radioNowUs + kCslRequestAhead)
|
||||
{
|
||||
wakeupInfo.mAttachDelayMs = static_cast<uint32_t>(rvTimestampUs - radioNowUs - kCslRequestAhead);
|
||||
wakeupInfo.mAttachDelayMs = ConvertRadioTime64To32(rvTimestampUs - radioNowUs - kCslRequestAhead);
|
||||
wakeupInfo.mAttachDelayMs = wakeupInfo.mAttachDelayMs / Time::kOneMsecInUsec;
|
||||
}
|
||||
else
|
||||
|
||||
+36
-178
@@ -49,7 +49,7 @@
|
||||
namespace ot {
|
||||
namespace Mac {
|
||||
|
||||
void TxFrame::Info::PrepareHeadersIn(TxFrame &aTxFrame) const
|
||||
void TxFrame::BuildInfo::PrepareHeadersIn(TxFrame &aTxFrame) const
|
||||
{
|
||||
uint16_t fcf;
|
||||
FrameBuilder builder;
|
||||
@@ -252,21 +252,6 @@ void TxFrame::Info::PrepareHeadersIn(TxFrame &aTxFrame) const
|
||||
aTxFrame.mLength = builder.GetLength();
|
||||
}
|
||||
|
||||
void Frame::SetFrameControlField(uint16_t aFcf)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME
|
||||
if (IsShortFcf(aFcf))
|
||||
{
|
||||
OT_ASSERT((aFcf >> 8) == 0);
|
||||
mPsdu[0] = static_cast<uint8_t>(aFcf);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
LittleEndian::WriteUint16(aFcf, mPsdu);
|
||||
}
|
||||
}
|
||||
|
||||
Error Frame::ValidatePsdu(void) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
@@ -298,86 +283,22 @@ exit:
|
||||
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
bool Frame::IsWakeupFrame(void) const
|
||||
{
|
||||
const uint16_t fcf = GetFrameControlField();
|
||||
bool result = false;
|
||||
uint8_t keyIdMode;
|
||||
uint8_t firstIeIndex;
|
||||
Address srcAddress;
|
||||
const ConnectionIe *connectionIe;
|
||||
|
||||
// Wake-up frame is a Multipurpose frame without Ack Request...
|
||||
VerifyOrExit((fcf & kFcfFrameTypeMask) == kTypeMultipurpose);
|
||||
VerifyOrExit((fcf & kMpFcfAckRequest) == 0);
|
||||
|
||||
// ... with extended source address...
|
||||
SuccessOrExit(GetSrcAddr(srcAddress));
|
||||
VerifyOrExit(srcAddress.IsExtended());
|
||||
|
||||
// ... secured with Key Id Mode 2...
|
||||
SuccessOrExit(GetKeyIdMode(keyIdMode));
|
||||
VerifyOrExit(keyIdMode == kKeyIdMode2);
|
||||
|
||||
// ... that has Rendezvous Time IE and Connection IE...
|
||||
VerifyOrExit(Has<RendezvousTimeIe>());
|
||||
VerifyOrExit((connectionIe = Find<ConnectionIe>()) != nullptr);
|
||||
|
||||
// ... but no other IEs nor payload.
|
||||
firstIeIndex = FindHeaderIeIndex();
|
||||
VerifyOrExit(mPsdu + firstIeIndex + sizeof(RendezvousTimeIe) + connectionIe->GetSize() == GetFooter());
|
||||
|
||||
result = true;
|
||||
|
||||
exit:
|
||||
return result;
|
||||
// Placeholder implementation following removal of legacy Multipurpose frame format.
|
||||
return false;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
#endif
|
||||
|
||||
void Frame::SetAckRequest(bool aAckRequest)
|
||||
void Frame::UpdateFcfFlag(bool aSet, uint16_t aBitFlag)
|
||||
{
|
||||
uint16_t fcf = GetFrameControlField();
|
||||
uint16_t mask = Select<kFcfAckRequest, kMpFcfAckRequest>(fcf);
|
||||
uint16_t fcf = GetFrameControlField();
|
||||
|
||||
if (aAckRequest)
|
||||
if (aSet)
|
||||
{
|
||||
fcf |= mask;
|
||||
fcf |= aBitFlag;
|
||||
}
|
||||
else
|
||||
{
|
||||
fcf &= ~mask;
|
||||
}
|
||||
|
||||
SetFrameControlField(fcf);
|
||||
}
|
||||
|
||||
void Frame::SetFramePending(bool aFramePending)
|
||||
{
|
||||
uint16_t fcf = GetFrameControlField();
|
||||
uint16_t mask = Select<kFcfFramePending, kMpFcfFramePending>(fcf);
|
||||
|
||||
if (aFramePending)
|
||||
{
|
||||
fcf |= mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
fcf &= ~mask;
|
||||
}
|
||||
|
||||
SetFrameControlField(fcf);
|
||||
}
|
||||
|
||||
void Frame::SetIePresent(bool aIePresent)
|
||||
{
|
||||
uint16_t fcf = GetFrameControlField();
|
||||
uint16_t mask = Select<kFcfIePresent, kMpFcfIePresent>(fcf);
|
||||
|
||||
if (aIePresent)
|
||||
{
|
||||
fcf |= mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
fcf &= ~mask;
|
||||
fcf &= ~aBitFlag;
|
||||
}
|
||||
|
||||
SetFrameControlField(fcf);
|
||||
@@ -386,7 +307,7 @@ void Frame::SetIePresent(bool aIePresent)
|
||||
uint8_t Frame::SkipSequenceIndex(void) const
|
||||
{
|
||||
uint16_t fcf = GetFrameControlField();
|
||||
uint8_t index = GetFcfSize(fcf);
|
||||
uint8_t index = kFcfSize;
|
||||
|
||||
if (IsSequencePresent(fcf))
|
||||
{
|
||||
@@ -412,14 +333,7 @@ bool Frame::IsDstPanIdPresent(uint16_t aFcf)
|
||||
{
|
||||
bool present;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME
|
||||
if (IsMultipurpose(aFcf))
|
||||
{
|
||||
present = (aFcf & kMpFcfPanidPresent) != 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (IsVersion2015(aFcf))
|
||||
if (IsVersion2015(aFcf))
|
||||
{
|
||||
// Original table at `InitMacHeader()`
|
||||
//
|
||||
@@ -485,14 +399,14 @@ uint8_t Frame::GetSequence(void) const
|
||||
{
|
||||
OT_ASSERT(IsSequencePresent());
|
||||
|
||||
return GetPsdu()[GetFcfSize(GetFrameControlField())];
|
||||
return GetPsdu()[kFcfSize];
|
||||
}
|
||||
|
||||
void Frame::SetSequence(uint8_t aSequence)
|
||||
{
|
||||
OT_ASSERT(IsSequencePresent());
|
||||
|
||||
GetPsdu()[GetFcfSize(GetFrameControlField())] = aSequence;
|
||||
GetPsdu()[kFcfSize] = aSequence;
|
||||
}
|
||||
|
||||
uint8_t Frame::FindDstAddrIndex(void) const { return SkipSequenceIndex() + (IsDstPanIdPresent() ? sizeof(PanId) : 0); }
|
||||
@@ -556,15 +470,7 @@ bool Frame::IsSrcPanIdPresent(uint16_t aFcf)
|
||||
{
|
||||
bool present;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME
|
||||
if (IsMultipurpose(aFcf))
|
||||
{
|
||||
// Sources PAN ID is implicitly equal to Destination PAN ID in Multipurpose frames
|
||||
present = false;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (IsVersion2015(aFcf) && ((aFcf & (kFcfDstAddrMask | kFcfSrcAddrMask)) == (kFcfDstAddrExt | kFcfSrcAddrExt)))
|
||||
if (IsVersion2015(aFcf) && ((aFcf & (kFcfDstAddrMask | kFcfSrcAddrMask)) == (kFcfDstAddrExt | kFcfSrcAddrExt)))
|
||||
{
|
||||
// Special case for a IEEE 802.15.4-2015 frame: When both
|
||||
// addresses are extended, then the source PAN iD is not present
|
||||
@@ -1004,7 +910,7 @@ exit:
|
||||
|
||||
uint8_t Frame::CalculateAddrFieldSize(uint16_t aFcf)
|
||||
{
|
||||
uint8_t size = GetFcfSize(aFcf) + (IsSequencePresent(aFcf) ? kDsnSize : 0);
|
||||
uint8_t size = kFcfSize + (IsSequencePresent(aFcf) ? kDsnSize : 0);
|
||||
|
||||
// This static method calculates the size (number of bytes) of
|
||||
// Address header field for a given Frame Control `aFcf` value.
|
||||
@@ -1384,12 +1290,12 @@ void TxFrame::GenerateImmAck(const RxFrame &aFrame, bool aIsFramePending)
|
||||
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
|
||||
Error TxFrame::GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Info frameInfo;
|
||||
Address address;
|
||||
PanId panId;
|
||||
uint8_t securityLevel = kSecurityNone;
|
||||
uint8_t keyIdMode = kKeyIdMode0;
|
||||
Error error = kErrorNone;
|
||||
BuildInfo buildInfo;
|
||||
Address address;
|
||||
PanId panId;
|
||||
uint8_t securityLevel = kSecurityNone;
|
||||
uint8_t keyIdMode = kKeyIdMode0;
|
||||
|
||||
// Validate the received frame.
|
||||
|
||||
@@ -1406,8 +1312,8 @@ Error TxFrame::GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, con
|
||||
// Check `aRxFrame` has a valid source, which is then used as
|
||||
// ack frames destination.
|
||||
|
||||
SuccessOrExit(error = aRxFrame.GetSrcAddr(frameInfo.mAddrs.mDestination));
|
||||
VerifyOrExit(!frameInfo.mAddrs.mDestination.IsNone(), error = kErrorParse);
|
||||
SuccessOrExit(error = aRxFrame.GetSrcAddr(buildInfo.mAddrs.mDestination));
|
||||
VerifyOrExit(!buildInfo.mAddrs.mDestination.IsNone(), error = kErrorParse);
|
||||
|
||||
if (aRxFrame.GetSecurityEnabled())
|
||||
{
|
||||
@@ -1420,12 +1326,12 @@ Error TxFrame::GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, con
|
||||
if (aRxFrame.IsSrcPanIdPresent())
|
||||
{
|
||||
SuccessOrExit(error = aRxFrame.GetSrcPanId(panId));
|
||||
frameInfo.mPanIds.SetDestination(panId);
|
||||
buildInfo.mPanIds.SetDestination(panId);
|
||||
}
|
||||
else if (aRxFrame.IsDstPanIdPresent())
|
||||
{
|
||||
SuccessOrExit(error = aRxFrame.GetDstPanId(panId));
|
||||
frameInfo.mPanIds.SetDestination(panId);
|
||||
buildInfo.mPanIds.SetDestination(panId);
|
||||
}
|
||||
|
||||
// Prepare the ack frame
|
||||
@@ -1433,12 +1339,12 @@ Error TxFrame::GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, con
|
||||
mChannel = aRxFrame.mChannel;
|
||||
ClearAllBytes(mInfo.mTxInfo);
|
||||
|
||||
frameInfo.mType = kTypeAck;
|
||||
frameInfo.mVersion = kVersion2015;
|
||||
frameInfo.mSecurityLevel = static_cast<SecurityLevel>(securityLevel);
|
||||
frameInfo.mKeyIdMode = static_cast<KeyIdMode>(keyIdMode);
|
||||
buildInfo.mType = kTypeAck;
|
||||
buildInfo.mVersion = kVersion2015;
|
||||
buildInfo.mSecurityLevel = static_cast<SecurityLevel>(securityLevel);
|
||||
buildInfo.mKeyIdMode = static_cast<KeyIdMode>(keyIdMode);
|
||||
|
||||
frameInfo.PrepareHeadersIn(*this);
|
||||
buildInfo.PrepareHeadersIn(*this);
|
||||
|
||||
SetFramePending(aIsFramePending);
|
||||
SetIePresent(aIeLength != 0);
|
||||
@@ -1467,56 +1373,14 @@ exit:
|
||||
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
|
||||
Error TxFrame::GenerateWakeupFrame(PanId aPanId, const WakeupRequest &aWakeupRequest, const Address &aSource)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t fcf;
|
||||
uint8_t secCtl;
|
||||
uint8_t wakeupIdLength;
|
||||
FrameBuilder builder;
|
||||
Address dest;
|
||||
// Placeholder implementation following removal of legacy Multipurpose frame format.
|
||||
OT_UNUSED_VARIABLE(aPanId);
|
||||
OT_UNUSED_VARIABLE(aWakeupRequest);
|
||||
OT_UNUSED_VARIABLE(aSource);
|
||||
|
||||
fcf = kTypeMultipurpose | kMpFcfLongFrame | kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression |
|
||||
kMpFcfIePresent;
|
||||
|
||||
VerifyOrExit(!aSource.IsNone(), error = kErrorInvalidArgs);
|
||||
|
||||
if (aWakeupRequest.IsWakeupByExtAddress())
|
||||
{
|
||||
wakeupIdLength = 0;
|
||||
dest.SetExtended(aWakeupRequest.GetExtAddress());
|
||||
}
|
||||
else
|
||||
{
|
||||
wakeupIdLength = GetWakeupIdLength(aWakeupRequest.GetWakeupId());
|
||||
dest.SetNone();
|
||||
}
|
||||
|
||||
fcf |= DetermineFcfAddrType(dest, kMpFcfDstAddrShift);
|
||||
fcf |= DetermineFcfAddrType(aSource, kMpFcfSrcAddrShift);
|
||||
|
||||
builder.Init(mPsdu, GetMtu());
|
||||
|
||||
IgnoreError(builder.AppendUint<kLittleEndian>(fcf));
|
||||
IgnoreError(builder.AppendUint<kLittleEndian>(aPanId));
|
||||
IgnoreError(builder.AppendMacAddress(dest));
|
||||
IgnoreError(builder.AppendMacAddress(aSource));
|
||||
|
||||
secCtl = kKeyIdMode2 | kSecurityEncMic32;
|
||||
IgnoreError(builder.AppendUint8(secCtl));
|
||||
builder.AppendLength(CalculateSecurityHeaderSize(secCtl) - sizeof(secCtl));
|
||||
|
||||
builder.Append<RendezvousTimeIe>()->Init();
|
||||
|
||||
builder.Append<ConnectionIe>()->Init(wakeupIdLength);
|
||||
builder.AppendLength(wakeupIdLength);
|
||||
|
||||
builder.AppendLength(CalculateMicSize(secCtl) + GetFcsSize());
|
||||
|
||||
mLength = builder.GetLength();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
return kErrorFailed;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
|
||||
#endif
|
||||
|
||||
bool RxFrame::IsSecuredWith(KeyIdModeFlags aFlags) const
|
||||
{
|
||||
@@ -1644,12 +1508,6 @@ Frame::InfoString Frame::ToInfoString(void) const
|
||||
|
||||
break;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME
|
||||
case kTypeMultipurpose:
|
||||
string.Append("MP");
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
string.Append("%d", type);
|
||||
break;
|
||||
|
||||
+47
-110
@@ -37,12 +37,14 @@
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/const_cast.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/numeric_limits.hpp"
|
||||
#include "mac/mac_header_ie.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
#include "meshcop/network_name.hpp"
|
||||
#include "radio/radio_types.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Mac {
|
||||
@@ -229,11 +231,9 @@ public:
|
||||
/**
|
||||
* Sets the Frame Pending bit.
|
||||
*
|
||||
* @note This method must not be called on a Multipurpose frame with short Frame Control field.
|
||||
*
|
||||
* @param[in] aFramePending The Frame Pending bit.
|
||||
*/
|
||||
void SetFramePending(bool aFramePending);
|
||||
void SetFramePending(bool aFramePending) { UpdateFcfFlag(aFramePending, kFcfFramePending); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the Ack Request bit is set.
|
||||
@@ -246,17 +246,13 @@ public:
|
||||
/**
|
||||
* Sets the Ack Request bit.
|
||||
*
|
||||
* @note This method must not be called on a Multipurpose frame with short Frame Control field.
|
||||
*
|
||||
* @param[in] aAckRequest The Ack Request bit.
|
||||
*/
|
||||
void SetAckRequest(bool aAckRequest);
|
||||
void SetAckRequest(bool aAckRequest) { UpdateFcfFlag(aAckRequest, kFcfAckRequest); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the PanId Compression bit is set.
|
||||
*
|
||||
* @note This method must not be called on a Multipurpose frame, which lacks this flag.
|
||||
*
|
||||
* @retval TRUE If the PanId Compression bit is set.
|
||||
* @retval FALSE If the PanId Compression bit is not set.
|
||||
*/
|
||||
@@ -273,11 +269,9 @@ public:
|
||||
/**
|
||||
* Sets the IE Present bit.
|
||||
*
|
||||
* @note This method must not be called on a Multipurpose frame with short Frame Control field.
|
||||
*
|
||||
* @param[in] aIePresent The IE Present bit.
|
||||
*/
|
||||
void SetIePresent(bool aIePresent);
|
||||
void SetIePresent(bool aIePresent) { UpdateFcfFlag(aIePresent, kFcfIePresent); }
|
||||
|
||||
/**
|
||||
* Returns the Sequence Number value.
|
||||
@@ -697,22 +691,9 @@ public:
|
||||
*
|
||||
* @returns The Frame Control field.
|
||||
*/
|
||||
uint16_t GetFrameControlField(void) const
|
||||
{
|
||||
uint16_t fcf = mPsdu[0];
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME
|
||||
if (!IsShortFcf(fcf))
|
||||
#endif
|
||||
{
|
||||
fcf |= (mPsdu[1] << 8);
|
||||
}
|
||||
|
||||
return fcf;
|
||||
}
|
||||
uint16_t GetFrameControlField(void) const { return LittleEndian::ReadUint16(mPsdu); }
|
||||
|
||||
protected:
|
||||
static constexpr uint8_t kShortFcfSize = sizeof(uint8_t);
|
||||
static constexpr uint8_t kSecurityControlSize = sizeof(uint8_t);
|
||||
static constexpr uint8_t kFrameCounterSize = sizeof(uint32_t);
|
||||
static constexpr uint8_t kCommandIdSize = sizeof(uint8_t);
|
||||
@@ -744,25 +725,6 @@ protected:
|
||||
static constexpr uint16_t kFcfSrcAddrExt = kFcfAddrExt << kFcfSrcAddrShift;
|
||||
static constexpr uint16_t kFcfSrcAddrMask = kFcfAddrMask << kFcfSrcAddrShift;
|
||||
|
||||
// Frame Control field format for MAC Multipurpose frame
|
||||
static constexpr uint16_t kMpFcfLongFrame = 1 << 3;
|
||||
static constexpr uint16_t kMpFcfDstAddrShift = 4;
|
||||
static constexpr uint16_t kMpFcfDstAddrNone = kFcfAddrNone << kMpFcfDstAddrShift;
|
||||
static constexpr uint16_t kMpFcfDstAddrShort = kFcfAddrShort << kMpFcfDstAddrShift;
|
||||
static constexpr uint16_t kMpFcfDstAddrExt = kFcfAddrExt << kMpFcfDstAddrShift;
|
||||
static constexpr uint16_t kMpFcfDstAddrMask = kFcfAddrMask << kMpFcfDstAddrShift;
|
||||
static constexpr uint16_t kMpFcfSrcAddrShift = 6;
|
||||
static constexpr uint16_t kMpFcfSrcAddrNone = kFcfAddrNone << kMpFcfSrcAddrShift;
|
||||
static constexpr uint16_t kMpFcfSrcAddrShort = kFcfAddrShort << kMpFcfSrcAddrShift;
|
||||
static constexpr uint16_t kMpFcfSrcAddrExt = kFcfAddrExt << kMpFcfSrcAddrShift;
|
||||
static constexpr uint16_t kMpFcfSrcAddrMask = kFcfAddrMask << kMpFcfSrcAddrShift;
|
||||
static constexpr uint16_t kMpFcfPanidPresent = 1 << 8;
|
||||
static constexpr uint16_t kMpFcfSecurityEnabled = 1 << 9;
|
||||
static constexpr uint16_t kMpFcfSequenceSuppression = 1 << 10;
|
||||
static constexpr uint16_t kMpFcfFramePending = 1 << 11;
|
||||
static constexpr uint16_t kMpFcfAckRequest = 1 << 14;
|
||||
static constexpr uint16_t kMpFcfIePresent = 1 << 15;
|
||||
|
||||
static constexpr uint8_t kSecLevelMask = 7 << 0;
|
||||
static constexpr uint8_t kKeyIdModeMask = 3 << 3;
|
||||
|
||||
@@ -781,7 +743,8 @@ protected:
|
||||
static constexpr uint8_t kInvalidSize = kInvalidIndex;
|
||||
static constexpr uint8_t kMaxPsduSize = kInvalidSize - 1;
|
||||
|
||||
void SetFrameControlField(uint16_t aFcf);
|
||||
void SetFrameControlField(uint16_t aFcf) { LittleEndian::WriteUint16(aFcf, mPsdu); }
|
||||
void UpdateFcfFlag(bool aSet, uint16_t aBitFlag);
|
||||
uint8_t SkipSequenceIndex(void) const;
|
||||
uint8_t FindDstPanIdIndex(void) const;
|
||||
uint8_t FindDstAddrIndex(void) const;
|
||||
@@ -795,63 +758,23 @@ protected:
|
||||
uint8_t FindHeaderIeIndex(void) const;
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME
|
||||
static uint8_t GetFcfSize(uint16_t aFcf) { return IsShortFcf(aFcf) ? kShortFcfSize : kFcfSize; }
|
||||
#else
|
||||
// clang-format off
|
||||
static uint8_t GetFcfSize(uint16_t /* aFcf */) { return kFcfSize; }
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_MULTIPURPOSE_FRAME
|
||||
template <uint16_t kValue, uint16_t kMpValue> static uint16_t Select(uint16_t aFcf)
|
||||
{
|
||||
return IsMultipurpose(aFcf) ? kMpValue : kValue;
|
||||
}
|
||||
#else
|
||||
template <uint16_t kValue, uint16_t kMpValue> static uint16_t Select(uint16_t /* aFcf */) { return kValue; }
|
||||
#endif
|
||||
|
||||
template <uint16_t kValue, uint16_t kMpValue> static uint16_t MaskFcf(uint16_t aFcf)
|
||||
{
|
||||
return aFcf & Select<kValue, kMpValue>(aFcf);
|
||||
}
|
||||
|
||||
static uint16_t GetFcfDstAddr(uint16_t aFcf)
|
||||
{
|
||||
return MaskFcf<kFcfDstAddrMask, kMpFcfDstAddrMask>(aFcf) >> Select<kFcfDstAddrShift, kMpFcfDstAddrShift>(aFcf);
|
||||
}
|
||||
|
||||
static uint16_t GetFcfSrcAddr(uint16_t aFcf)
|
||||
{
|
||||
return MaskFcf<kFcfSrcAddrMask, kMpFcfSrcAddrMask>(aFcf) >> Select<kFcfSrcAddrShift, kMpFcfSrcAddrShift>(aFcf);
|
||||
}
|
||||
|
||||
static bool IsMultipurpose(uint16_t aFcf) { return (aFcf & kFcfFrameTypeMask) == kTypeMultipurpose; }
|
||||
static bool IsShortFcf(uint16_t aFcf)
|
||||
{
|
||||
return (aFcf & (kFcfFrameTypeMask | kMpFcfLongFrame)) == (kTypeMultipurpose | 0);
|
||||
}
|
||||
static bool IsSequencePresent(uint16_t aFcf)
|
||||
{
|
||||
return !MaskFcf<kFcfSequenceSuppression, kMpFcfSequenceSuppression>(aFcf);
|
||||
}
|
||||
static bool IsDstAddrPresent(uint16_t aFcf) { return MaskFcf<kFcfDstAddrMask, kMpFcfDstAddrMask>(aFcf); }
|
||||
static bool IsDstPanIdPresent(uint16_t aFcf);
|
||||
static bool IsSrcAddrPresent(uint16_t aFcf) { return MaskFcf<kFcfSrcAddrMask, kMpFcfSrcAddrMask>(aFcf); }
|
||||
static bool IsSrcPanIdPresent(uint16_t aFcf);
|
||||
static bool IsSecurityEnabled(uint16_t aFcf) { return MaskFcf<kFcfSecurityEnabled, kMpFcfSecurityEnabled>(aFcf); }
|
||||
static bool IsFramePending(uint16_t aFcf) { return MaskFcf<kFcfFramePending, kMpFcfFramePending>(aFcf); }
|
||||
static bool IsIePresent(uint16_t aFcf) { return MaskFcf<kFcfIePresent, kMpFcfIePresent>(aFcf); }
|
||||
static bool IsAckRequest(uint16_t aFcf) { return MaskFcf<kFcfAckRequest, kMpFcfAckRequest>(aFcf); }
|
||||
static bool IsVersion2015(uint16_t aFcf) { return (aFcf & kFcfFrameVersionMask) == kVersion2015; }
|
||||
|
||||
static uint16_t GetFcfDstAddr(uint16_t aFcf) { return ReadBits<uint16_t, kFcfDstAddrMask>(aFcf); }
|
||||
static uint16_t GetFcfSrcAddr(uint16_t aFcf) { return ReadBits<uint16_t, kFcfSrcAddrMask>(aFcf); }
|
||||
static bool IsSequencePresent(uint16_t aFcf) { return (aFcf & kFcfSequenceSuppression) == 0; }
|
||||
static bool IsDstAddrPresent(uint16_t aFcf) { return (aFcf & kFcfDstAddrMask) != 0; }
|
||||
static bool IsSrcAddrPresent(uint16_t aFcf) { return (aFcf & kFcfSrcAddrMask) != 0; }
|
||||
static bool IsSecurityEnabled(uint16_t aFcf) { return (aFcf & kFcfSecurityEnabled) != 0; }
|
||||
static bool IsFramePending(uint16_t aFcf) { return (aFcf & kFcfFramePending) != 0; }
|
||||
static bool IsIePresent(uint16_t aFcf) { return (aFcf & kFcfIePresent) != 0; }
|
||||
static bool IsAckRequest(uint16_t aFcf) { return (aFcf & kFcfAckRequest) != 0; }
|
||||
static bool IsVersion2015(uint16_t aFcf) { return (aFcf & kFcfFrameVersionMask) == kVersion2015; }
|
||||
static bool IsDstPanIdPresent(uint16_t aFcf);
|
||||
static bool IsSrcPanIdPresent(uint16_t aFcf);
|
||||
static uint16_t DetermineFcfAddrType(const Address &aAddress, uint16_t aBitShift);
|
||||
|
||||
static uint8_t CalculateAddrFieldSize(uint16_t aFcf);
|
||||
static uint8_t CalculateSecurityHeaderSize(uint8_t aSecurityControl);
|
||||
static uint8_t CalculateKeySourceSize(uint8_t aSecurityControl);
|
||||
static uint8_t CalculateMicSize(uint8_t aSecurityControl);
|
||||
static uint8_t CalculateAddrFieldSize(uint16_t aFcf);
|
||||
static uint8_t CalculateSecurityHeaderSize(uint8_t aSecurityControl);
|
||||
static uint8_t CalculateKeySourceSize(uint8_t aSecurityControl);
|
||||
static uint8_t CalculateMicSize(uint8_t aSecurityControl);
|
||||
|
||||
private:
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
@@ -945,7 +868,7 @@ public:
|
||||
*
|
||||
* @returns The timestamp in microseconds.
|
||||
*/
|
||||
const uint64_t &GetTimestamp(void) const { return mInfo.mRxInfo.mTimestamp; }
|
||||
const RadioTime64 &GetTimestamp(void) const { return mInfo.mRxInfo.mTimestamp; }
|
||||
|
||||
/**
|
||||
* Performs AES CCM on the frame which is received.
|
||||
@@ -967,22 +890,22 @@ class TxFrame : public Frame
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Represents header information.
|
||||
* Represents the information to use to build the frame.
|
||||
*/
|
||||
struct Info : public Clearable<Info>
|
||||
struct BuildInfo : public Clearable<BuildInfo>
|
||||
{
|
||||
/**
|
||||
* Initializes the `Info` by clearing all its fields (setting all bytes to zero).
|
||||
* Initializes the `BuildInfo` by clearing all its fields (setting all bytes to zero).
|
||||
*/
|
||||
Info(void) { Clear(); }
|
||||
BuildInfo(void) { Clear(); }
|
||||
|
||||
/**
|
||||
* Prepares MAC headers based on `Info` fields in a given `TxFrame`.
|
||||
* Prepares MAC headers based on `BuildInfo` fields in a given `TxFrame`.
|
||||
*
|
||||
* This method uses the `Info` structure to construct the MAC address and security headers in @p aTxFrame.
|
||||
* This method uses the `BuildInfo` structure to construct the MAC address and security headers in @p aTxFrame.
|
||||
* It determines the Frame Control Field (FCF), including setting the appropriate frame type, security level,
|
||||
* and addressing mode flags. It populates the source and destination addresses and PAN IDs within the MAC
|
||||
* header based on the information provided in the `Info` structure.
|
||||
* header based on the information provided in the `BuildInfo` structure.
|
||||
*
|
||||
* It sets the Ack Request bit in the FCF if the following criteria are met:
|
||||
* - A destination address is present
|
||||
@@ -1283,6 +1206,13 @@ public:
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
|
||||
/**
|
||||
* Gets the TX delay field for the frame.
|
||||
*
|
||||
* @returns The delay time for the TX frame in microseconds.
|
||||
*/
|
||||
uint32_t GetTxDelay(void) const { return mInfo.mTxInfo.mTxDelay; }
|
||||
|
||||
/**
|
||||
* Set TX delay field for the frame.
|
||||
*
|
||||
@@ -1290,12 +1220,19 @@ public:
|
||||
*/
|
||||
void SetTxDelay(uint32_t aTxDelay) { mInfo.mTxInfo.mTxDelay = aTxDelay; }
|
||||
|
||||
/**
|
||||
* Gets the TX delay base time field for the frame.
|
||||
*
|
||||
* @returns The delay base time for the TX frame as a `RadioTime32`.
|
||||
*/
|
||||
RadioTime32 GetTxDelayBaseTime(void) const { return mInfo.mTxInfo.mTxDelayBaseTime; }
|
||||
|
||||
/**
|
||||
* Set TX delay base time field for the frame.
|
||||
*
|
||||
* @param[in] aTxDelayBaseTime The delay base time for the TX frame.
|
||||
*/
|
||||
void SetTxDelayBaseTime(uint32_t aTxDelayBaseTime) { mInfo.mTxInfo.mTxDelayBaseTime = aTxDelayBaseTime; }
|
||||
void SetTxDelayBaseTime(RadioTime32 aTxDelayBaseTime) { mInfo.mTxInfo.mTxDelayBaseTime = aTxDelayBaseTime; }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -43,6 +43,42 @@ void HeaderIe::Init(uint8_t aId, uint8_t aLen)
|
||||
SetId(aId);
|
||||
}
|
||||
|
||||
Error HeaderIe::StartIe(FrameBuilder &aBuilder, uint8_t aId, Bookmark &aBookmark)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
HeaderIe *ie;
|
||||
|
||||
aBookmark = aBuilder.GetLength();
|
||||
|
||||
ie = aBuilder.Append<HeaderIe>();
|
||||
VerifyOrExit(ie != nullptr, error = kErrorNoBufs);
|
||||
|
||||
ie->Init(aId, 0);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error HeaderIe::EndIe(FrameBuilder &aBuilder, const Bookmark &aBookmark)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t offset = aBookmark;
|
||||
uint16_t length;
|
||||
HeaderIe *ie;
|
||||
|
||||
VerifyOrExit(offset + sizeof(HeaderIe) <= aBuilder.GetLength(), error = kErrorInvalidArgs);
|
||||
|
||||
ie = aBuilder.Read<HeaderIe>(offset);
|
||||
|
||||
length = aBuilder.GetLength() - offset - sizeof(HeaderIe);
|
||||
VerifyOrExit(length <= kMaxLength, error = kErrorInvalidArgs);
|
||||
|
||||
ie->SetLength(static_cast<uint8_t>(length));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
|
||||
Error ConnectionIe::SetWakeupId(WakeupId aWakeupId)
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/const_cast.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/frame_builder.hpp"
|
||||
#include "common/num_utils.hpp"
|
||||
#include "common/numeric_limits.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
@@ -60,6 +61,8 @@ OT_TOOL_PACKED_BEGIN
|
||||
class HeaderIe
|
||||
{
|
||||
public:
|
||||
static constexpr uint8_t kMaxLength = 127; ///< Maximum Header IE length in bytes.
|
||||
|
||||
/**
|
||||
* Returns the IE Element ID.
|
||||
*
|
||||
@@ -115,6 +118,41 @@ public:
|
||||
return (aIe.GetId() == IeType::kId) && static_cast<const IeType *>(&aIe)->IsValid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the opaque type for a bookmark used by `StartIe()/EndIe()`.
|
||||
*/
|
||||
typedef uint16_t Bookmark;
|
||||
|
||||
/**
|
||||
* Starts appending a (variable-length) `HeaderIe` in a `FrameBuilder`.
|
||||
*
|
||||
* On success, this method appends a `HeaderIe` descriptor (with length initialized to zero) to @p aBuilder and
|
||||
* saves the current byte offset as @p aBookmark. The caller can then append the IE content bytes to @p aBuilder,
|
||||
* and finally call `EndIe()` to update the IE length field automatically.
|
||||
*
|
||||
* @param[in,out] aBuilder The `FrameBuilder` instance to append to.
|
||||
* @param[in] aId The IE Element ID.
|
||||
* @param[out] aBookmark A reference to a `Bookmark` to save the start offset.
|
||||
*
|
||||
* @retval kErrorNone Successfully started the `HeaderIe`.
|
||||
* @retval kErrorNoBufs Insufficient space in @p aBuilder to append the `HeaderIe` header.
|
||||
*/
|
||||
static Error StartIe(FrameBuilder &aBuilder, uint8_t aId, Bookmark &aBookmark);
|
||||
|
||||
/**
|
||||
* Finishes appending a `HeaderIe` in a `FrameBuilder`.
|
||||
*
|
||||
* This method updates the length field of the `HeaderIe` previously started using `StartIe()`. It determines the
|
||||
* IE length based on the number of bytes appended to @p aBuilder since `StartIe()` was called.
|
||||
*
|
||||
* @param[in,out] aBuilder The `FrameBuilder` instance.
|
||||
* @param[in] aBookmark The `Bookmark` used when calling `StartIe()`.
|
||||
*
|
||||
* @retval kErrorNone Successfully finalized the `HeaderIe` length.
|
||||
* @retval kErrorInvalidArgs The @p aBookmark is invalid or the appended IE length exceeds `kMaxLength`.
|
||||
*/
|
||||
static Error EndIe(FrameBuilder &aBuilder, const Bookmark &aBookmark);
|
||||
|
||||
protected:
|
||||
void Init(uint8_t aId, uint8_t aLen);
|
||||
uint8_t *GetBytes(void) { return reinterpret_cast<uint8_t *>(this); }
|
||||
|
||||
@@ -80,6 +80,8 @@ typedef otShortAddress ShortAddress;
|
||||
|
||||
constexpr ShortAddress kShortAddrBroadcast = OT_RADIO_BROADCAST_SHORT_ADDR; ///< Broadcast Short Address.
|
||||
constexpr ShortAddress kShortAddrInvalid = OT_RADIO_INVALID_SHORT_ADDR; ///< Invalid Short Address.
|
||||
constexpr bool kDefaultMacKeysExportable =
|
||||
OPENTHREAD_CONFIG_PLATFORM_MAC_KEYS_EXPORTABLE_ENABLE; ///< Default exportability policy for MAC key refs.
|
||||
|
||||
/**
|
||||
* Represents the wake-up identifier.
|
||||
|
||||
@@ -427,32 +427,29 @@ void SubMac::StartCsmaBackoff(void)
|
||||
uint8_t backoffExponent = kCsmaMinBe + mCsmaBackoffs;
|
||||
|
||||
#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
if (mTransmitFrame.mInfo.mTxInfo.mTxDelay != 0 || mTransmitFrame.mInfo.mTxInfo.mTxDelayBaseTime != 0)
|
||||
if (mTransmitFrame.GetTxDelay() != 0 || mTransmitFrame.GetTxDelayBaseTime() != 0)
|
||||
{
|
||||
SetState(kStateCslTransmit);
|
||||
|
||||
if (ShouldHandleTransmitTargetTime())
|
||||
{
|
||||
static constexpr uint32_t kAheadTime = kCcaSampleInterval + kCslTransmitTimeAhead + kRadioHeaderShrDuration;
|
||||
Time txStartTime = Time(mTransmitFrame.mInfo.mTxInfo.mTxDelayBaseTime);
|
||||
Time radioNow = Time(static_cast<uint32_t>(Get<Radio>().GetNow()));
|
||||
|
||||
RadioTime32 radioNow = Get<Radio>().GetNowAsRadioTime32();
|
||||
RadioTime32 txStartTime = mTransmitFrame.GetTxDelayBaseTime();
|
||||
|
||||
txStartTime += (mTransmitFrame.mInfo.mTxInfo.mTxDelay - kAheadTime);
|
||||
|
||||
if (radioNow < txStartTime)
|
||||
if (IsRadioTimeStrictlyBefore(radioNow, txStartTime))
|
||||
{
|
||||
StartTimer(txStartTime - radioNow);
|
||||
ExitNow();
|
||||
}
|
||||
else // Transmit without delay
|
||||
{
|
||||
BeginTransmit();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BeginTransmit();
|
||||
|
||||
// Transmit without delay
|
||||
}
|
||||
|
||||
BeginTransmit();
|
||||
ExitNow();
|
||||
}
|
||||
#endif // !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
|
||||
+10
-10
@@ -677,7 +677,7 @@ private:
|
||||
bool mIsCslSampling : 1; // Indicates that the current time is in CSL sample window
|
||||
// for platforms not supporting `Radio::ReceiveAt()`.
|
||||
uint16_t mCslPeerShort; // The CSL peer short address.
|
||||
uint32_t mCslSampleTimeRadio; // The CSL sample time of the current period based on radio time (lower 32-bit).
|
||||
RadioTime32 mCslSampleTimeRadio; // The CSL sample time of the current period based on radio time (lower 32-bit).
|
||||
TimeMicro mCslSampleTimeLocal; // The CSL sample time of the current period based on local time.
|
||||
TimeMicro mCslLastSync; // The timestamp of the last successful CSL synchronization.
|
||||
CslAccuracy mCslParentAccuracy; // The parent's CSL accuracy (clock accuracy and uncertainty).
|
||||
@@ -685,15 +685,15 @@ private:
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
bool mIsWedSampling : 1; // Indicates that the current time is in WED's sample window
|
||||
// for platforms not supporting `Radio::ReceiveAt()`.
|
||||
bool mIsWedEnabled : 1; // Indicates if the WED is enabled.
|
||||
uint32_t mWakeupListenInterval; // The wake-up listen interval, in microseconds.
|
||||
uint32_t mWakeupListenDuration; // The wake-up listen duration, in microseconds.
|
||||
uint8_t mWakeupChannel; // The wake-up sample channel.
|
||||
TimeMicro mWedSampleTime; // The WED sample time of the current interval in local time.
|
||||
uint64_t mWedSampleTimeRadio; // The WED sample time of the current interval in radio time.
|
||||
TimerMicro mWedTimer;
|
||||
bool mIsWedSampling : 1; // Indicates that the current time is in WED's sample window
|
||||
// for platforms not supporting `Radio::ReceiveAt()`.
|
||||
bool mIsWedEnabled : 1; // Indicates if the WED is enabled.
|
||||
uint32_t mWakeupListenInterval; // The wake-up listen interval, in microseconds.
|
||||
uint32_t mWakeupListenDuration; // The wake-up listen duration, in microseconds.
|
||||
uint8_t mWakeupChannel; // The wake-up sample channel.
|
||||
TimeMicro mWedSampleTime; // The WED sample time of the current interval in local time.
|
||||
RadioTime64 mWedSampleTimeRadio; // The WED sample time of the current interval in radio time.
|
||||
TimerMicro mWedTimer;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ void SubMac::UpdateCslLastSyncTimestamp(RxFrame *aFrame, Error aError)
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_LOCAL_TIME_SYNC
|
||||
mCslLastSync = TimerMicro::GetNow();
|
||||
#else
|
||||
mCslLastSync = TimeMicro(static_cast<uint32_t>(aFrame->mInfo.mRxInfo.mTimestamp));
|
||||
mCslLastSync = TimeMicro(ConvertRadioTime64To32(aFrame->GetTimestamp()));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ void SubMac::SetCslParams(uint16_t aPeriod, uint8_t aChannel, ShortAddress aShor
|
||||
mCslTimer.Stop();
|
||||
if (mCslPeriod > 0)
|
||||
{
|
||||
mCslSampleTimeRadio = static_cast<uint32_t>(Get<Radio>().GetNow());
|
||||
mCslSampleTimeRadio = Get<Radio>().GetNowAsRadioTime32();
|
||||
mCslSampleTimeLocal = TimerMicro::GetNow();
|
||||
// Update CSL sync time whenever CSL parameters are re-initialized.
|
||||
mCslLastSync = mCslSampleTimeLocal;
|
||||
@@ -180,9 +180,9 @@ void SubMac::HandleCslReceiveAt(uint32_t aTimeAhead, uint32_t aTimeAfter)
|
||||
* x-|------------|-------------------------------------x-|------------|---------------------------------------|
|
||||
* sample sleep sample sleep
|
||||
*/
|
||||
uint32_t periodUs = mCslPeriod * kUsPerTenSymbols;
|
||||
uint32_t winStart;
|
||||
uint32_t winDuration;
|
||||
uint32_t periodUs = mCslPeriod * kUsPerTenSymbols;
|
||||
RadioTime32 winStart;
|
||||
uint32_t winDuration;
|
||||
|
||||
mCslTimer.FireAt(mCslSampleTimeLocal + periodUs - aTimeAhead - GetNextCycleDrift());
|
||||
aTimeAhead -= kCslReceiveTimeAhead;
|
||||
@@ -290,7 +290,7 @@ uint32_t SubMac::GetLocalTime(void)
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_LOCAL_TIME_SYNC
|
||||
now = TimerMicro::GetNow().GetValue();
|
||||
#else
|
||||
now = static_cast<uint32_t>(Get<Radio>().GetNow());
|
||||
now = Get<Radio>().GetNowAsRadioTime32();
|
||||
#endif
|
||||
|
||||
return now;
|
||||
@@ -321,8 +321,7 @@ void SubMac::LogReceived(RxFrame *aFrame)
|
||||
(dst.GetType() == Address::kTypeExtended && dst.GetExtended() == GetExtAddress()));
|
||||
|
||||
LogDebg("Received frame in state (SubMac %s, CSL %s), timestamp %lu", StateToString(mState),
|
||||
mIsCslSampling ? "CslSample" : "CslSleep",
|
||||
ToUlong(static_cast<uint32_t>(aFrame->mInfo.mRxInfo.mTimestamp)));
|
||||
mIsCslSampling ? "CslSample" : "CslSleep", ToUlong(ConvertRadioTime64To32(aFrame->GetTimestamp())));
|
||||
|
||||
VerifyOrExit(mState == kStateRadioSample);
|
||||
|
||||
@@ -330,7 +329,7 @@ void SubMac::LogReceived(RxFrame *aFrame)
|
||||
ahead -= kMinReceiveOnAhead + kCslReceiveTimeAhead;
|
||||
|
||||
sampleTime = mCslSampleTimeRadio - mCslPeriod * kUsPerTenSymbols;
|
||||
deviation = static_cast<uint32_t>(aFrame->mInfo.mRxInfo.mTimestamp) + kRadioHeaderPhrDuration - sampleTime;
|
||||
deviation = ConvertRadioTime64To32(aFrame->GetTimestamp()) + kRadioHeaderPhrDuration - sampleTime;
|
||||
|
||||
// This logs three values (all in microseconds):
|
||||
// - Absolute sample time in which the CSL receiver expected the MHR of the received frame.
|
||||
|
||||
@@ -96,7 +96,7 @@ void SubMac::HandleWedReceiveAt(void)
|
||||
if (mState != kStateDisabled)
|
||||
{
|
||||
IgnoreError(
|
||||
Get<Radio>().ReceiveAt(mWakeupChannel, static_cast<uint32_t>(mWedSampleTimeRadio), mWakeupListenDuration));
|
||||
Get<Radio>().ReceiveAt(mWakeupChannel, ConvertRadioTime64To32(mWedSampleTimeRadio), mWakeupListenDuration));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ Mac::TxFrame *WakeupTxScheduler::PrepareWakeupFrame(Mac::TxFrames &aTxFrames)
|
||||
|
||||
VerifyOrExit(frame->GenerateWakeupFrame(Get<Mac::Mac>().GetPanId(), mWakeupRequest, source) == kErrorNone,
|
||||
frame = nullptr);
|
||||
frame->SetTxDelayBaseTime(static_cast<uint32_t>(Get<Radio>().GetNow()));
|
||||
frame->SetTxDelayBaseTime(Get<Radio>().GetNowAsRadioTime32());
|
||||
frame->SetTxDelay(radioTxDelay);
|
||||
frame->SetCsmaCaEnabled(kWakeupFrameTxCca);
|
||||
frame->SetMaxCsmaBackoffs(0);
|
||||
|
||||
@@ -128,6 +128,8 @@ Error Radio::Transmit(Mac::TxFrame &aFrame)
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
inline uint64_t UintSafeMinus(uint64_t aLhs, uint64_t aRhs) { return aLhs > aRhs ? (aLhs - aRhs) : 0; }
|
||||
|
||||
|
||||
+20
-15
@@ -46,6 +46,7 @@
|
||||
#include "common/numeric_limits.hpp"
|
||||
#include "common/time.hpp"
|
||||
#include "mac/mac_frame.hpp"
|
||||
#include "radio/radio_types.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
@@ -523,7 +524,7 @@ public:
|
||||
* @retval kErrorNone Successfully scheduled receive window.
|
||||
* @retval kErrorFailed The receive window could not be scheduled.
|
||||
*/
|
||||
Error ReceiveAt(uint8_t aChannel, uint32_t aStart, uint32_t aDuration);
|
||||
Error ReceiveAt(uint8_t aChannel, RadioTime32 aStart, uint32_t aDuration);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
@@ -532,7 +533,7 @@ public:
|
||||
*
|
||||
* @param[in] aCslSampleTime The CSL sample time.
|
||||
*/
|
||||
void UpdateCslSampleTime(uint32_t aCslSampleTime);
|
||||
void UpdateCslSampleTime(RadioTime32 aCslSampleTime);
|
||||
|
||||
/**
|
||||
* Enables CSL sampling in radio.
|
||||
@@ -559,15 +560,21 @@ public:
|
||||
Error ResetCsl(void);
|
||||
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE || \
|
||||
OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
#if OT_CONFIG_RADIO_TIME_ENABLE
|
||||
/**
|
||||
* Get the current radio time in microseconds referenced to a continuous monotonic local radio clock (64 bits
|
||||
* width).
|
||||
*
|
||||
* @returns The current radio clock time.
|
||||
*/
|
||||
uint64_t GetNow(void);
|
||||
RadioTime64 GetNow(void);
|
||||
|
||||
/**
|
||||
* Get the current radio time in microseconds as a 32-bit value (lower 32 bits of the full radio time).
|
||||
*
|
||||
* @returns The current radio clock time as a `RadioTime32`.
|
||||
*/
|
||||
RadioTime32 GetNowAsRadioTime32(void) { return ConvertRadioTime64To32(GetNow()); }
|
||||
|
||||
/**
|
||||
* Get the current accuracy, in units of ± ppm, of the clock used for scheduling CSL operations.
|
||||
@@ -584,7 +591,7 @@ public:
|
||||
* @returns The CSL Uncertainty in units of 10 us.
|
||||
*/
|
||||
uint8_t GetCslUncertainty(void);
|
||||
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
#endif // OT_CONFIG_RADIO_TIME_ENABLE
|
||||
|
||||
/**
|
||||
* Gets the radio transmit frame buffer.
|
||||
@@ -984,7 +991,7 @@ inline Error Radio::Receive(uint8_t aChannel)
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
inline Error Radio::ReceiveAt(uint8_t aChannel, uint32_t aStart, uint32_t aDuration)
|
||||
inline Error Radio::ReceiveAt(uint8_t aChannel, RadioTime32 aStart, uint32_t aDuration)
|
||||
{
|
||||
Error error = otPlatRadioReceiveAt(GetInstancePtr(), aChannel, aStart, aDuration);
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
@@ -998,7 +1005,7 @@ inline Error Radio::ReceiveAt(uint8_t aChannel, uint32_t aStart, uint32_t aDurat
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
inline void Radio::UpdateCslSampleTime(uint32_t aCslSampleTime)
|
||||
inline void Radio::UpdateCslSampleTime(RadioTime32 aCslSampleTime)
|
||||
{
|
||||
otPlatRadioUpdateCslSampleTime(GetInstancePtr(), aCslSampleTime);
|
||||
}
|
||||
@@ -1011,9 +1018,8 @@ inline Error Radio::EnableCsl(uint32_t aCslPeriod, Mac::ShortAddress aShortAddr,
|
||||
inline Error Radio::ResetCsl(void) { return otPlatRadioResetCsl(GetInstancePtr()); }
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE || \
|
||||
OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
inline uint64_t Radio::GetNow(void) { return otPlatRadioGetNow(GetInstancePtr()); }
|
||||
#if OT_CONFIG_RADIO_TIME_ENABLE
|
||||
inline RadioTime64 Radio::GetNow(void) { return otPlatRadioGetNow(GetInstancePtr()); }
|
||||
|
||||
inline uint8_t Radio::GetCslAccuracy(void) { return otPlatRadioGetCslAccuracy(GetInstancePtr()); }
|
||||
|
||||
@@ -1112,16 +1118,15 @@ inline Error Radio::ReceiveAt(uint8_t, uint32_t, uint32_t) { return kErrorNone;
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
inline void Radio::UpdateCslSampleTime(uint32_t) {}
|
||||
inline void Radio::UpdateCslSampleTime(RadioTime32) {}
|
||||
|
||||
inline Error Radio::EnableCsl(uint32_t, Mac::ShortAddress, const Mac::ExtAddress &) { return kErrorNotImplemented; }
|
||||
|
||||
inline Error Radio::ResetCsl(void) { return kErrorNotImplemented; }
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE || \
|
||||
OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
inline uint64_t Radio::GetNow(void) { return NumericLimits<uint64_t>::kMax; }
|
||||
#if OT_CONFIG_RADIO_TIME_ENABLE
|
||||
inline RadioTime64 Radio::GetNow(void) { return NumericLimits<uint64_t>::kMax; }
|
||||
|
||||
inline uint8_t Radio::GetCslAccuracy(void) { return NumericLimits<uint8_t>::kMax; }
|
||||
|
||||
|
||||
@@ -281,7 +281,7 @@ extern "C" OT_TOOL_WEAK void otPlatRadioSetMacFrameCounterIfLarger(otInstance *a
|
||||
|
||||
extern "C" OT_TOOL_WEAK uint64_t otPlatTimeGet(void) { return UINT64_MAX; }
|
||||
|
||||
extern "C" OT_TOOL_WEAK uint64_t otPlatRadioGetNow(otInstance *aInstance)
|
||||
extern "C" OT_TOOL_WEAK otRadioTime64 otPlatRadioGetNow(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
@@ -366,10 +366,10 @@ extern "C" OT_TOOL_WEAK otError otPlatRadioGetRegion(otInstance *aInstance, uint
|
||||
return kErrorNotImplemented;
|
||||
}
|
||||
|
||||
extern "C" OT_TOOL_WEAK otError otPlatRadioReceiveAt(otInstance *aInstance,
|
||||
uint8_t aChannel,
|
||||
uint32_t aStart,
|
||||
uint32_t aDuration)
|
||||
extern "C" OT_TOOL_WEAK otError otPlatRadioReceiveAt(otInstance *aInstance,
|
||||
uint8_t aChannel,
|
||||
otRadioTime32 aStart,
|
||||
uint32_t aDuration)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aChannel);
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2026, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes implementation of OpenThread radio types.
|
||||
*/
|
||||
|
||||
#include "radio_types.hpp"
|
||||
|
||||
#include "common/time.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
bool IsRadioTimeStrictlyBefore(RadioTime32 aFirstTime, RadioTime32 aSecondTime)
|
||||
{
|
||||
Time firstTime(aFirstTime);
|
||||
Time secondTime(aSecondTime);
|
||||
|
||||
return (firstTime < secondTime);
|
||||
}
|
||||
|
||||
} // namespace ot
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2026, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for OpenThread radio types.
|
||||
*/
|
||||
|
||||
#ifndef OT_CORE_RADIO_RADIO_TYPES_HPP_
|
||||
#define OT_CORE_RADIO_RADIO_TYPES_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <openthread/platform/radio.h>
|
||||
|
||||
namespace ot {
|
||||
|
||||
#ifdef OT_CONFIG_RADIO_TIME_ENABLE
|
||||
#error "OT_CONFIG_RADIO_TIME_ENABLE MUST NOT be defined directly. It is derived from other configs"
|
||||
#endif
|
||||
|
||||
#define OT_CONFIG_RADIO_TIME_ENABLE \
|
||||
(OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE || \
|
||||
OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE || OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || \
|
||||
OPENTHREAD_CONFIG_TIME_SYNC_ENABLE)
|
||||
|
||||
/**
|
||||
* Represents a 64-bit radio time in microseconds referenced to a continuous monotonic local radio clock.
|
||||
*/
|
||||
typedef otRadioTime64 RadioTime64;
|
||||
|
||||
/**
|
||||
* Represents a 32-bit radio time in microseconds (holds the lower 32 bits of a `RadioTime64`).
|
||||
*/
|
||||
typedef otRadioTime32 RadioTime32;
|
||||
|
||||
/**
|
||||
* Converts a 64-bit radio time to a 32-bit radio time.
|
||||
*
|
||||
* @param[in] aRadioTime64 The 64-bit radio time to convert.
|
||||
*
|
||||
* @returns The converted 32-bit radio time (lower 32 bits of @p aRadioTime64).
|
||||
*/
|
||||
inline RadioTime32 ConvertRadioTime64To32(RadioTime64 aRadioTime64) { return static_cast<RadioTime32>(aRadioTime64); }
|
||||
|
||||
/**
|
||||
* Indicates whether a given 32-bit radio time is strictly before another 32-bit radio time.
|
||||
*
|
||||
* This function correctly accounts for 32-bit microsecond counter roll-over.
|
||||
*
|
||||
* @param[in] aFirstTime The first 32-bit radio time to compare.
|
||||
* @param[in] aSecondTime The second 32-bit radio time to compare.
|
||||
*
|
||||
* @retval TRUE @p aFirstTime is strictly before @p aSecondTime.
|
||||
* @retval FALSE @p aFirstTime is not strictly before @p aSecondTime.
|
||||
*/
|
||||
bool IsRadioTimeStrictlyBefore(RadioTime32 aFirstTime, RadioTime32 aSecondTime);
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // OT_CORE_RADIO_RADIO_TYPES_HPP_
|
||||
@@ -135,12 +135,12 @@ uint32_t CslTxScheduler::GetNextCslTransmissionDelay(const CslNeighbor &aCslNeig
|
||||
uint32_t &aDelayFromLastRx,
|
||||
uint32_t aAheadUs) const
|
||||
{
|
||||
uint64_t radioNow = Get<Radio>().GetNow();
|
||||
uint32_t periodInUs = aCslNeighbor.GetCslPeriod() * kUsPerTenSymbols;
|
||||
// See CslTxScheduler::NeighborInfo::mCslPhase
|
||||
|
||||
/* see CslTxScheduler::NeighborInfo::mCslPhase */
|
||||
uint64_t firstTxWindow = aCslNeighbor.GetLastRxTimestamp() + aCslNeighbor.GetCslPhase() * kUsPerTenSymbols;
|
||||
uint64_t nextTxWindow = radioNow - (radioNow % periodInUs) + (firstTxWindow % periodInUs);
|
||||
RadioTime64 radioNow = Get<Radio>().GetNow();
|
||||
uint32_t periodInUs = aCslNeighbor.GetCslPeriod() * kUsPerTenSymbols;
|
||||
RadioTime64 firstTxWindow = aCslNeighbor.GetLastRxTimestamp() + aCslNeighbor.GetCslPhase() * kUsPerTenSymbols;
|
||||
RadioTime64 nextTxWindow = radioNow - (radioNow % periodInUs) + (firstTxWindow % periodInUs);
|
||||
|
||||
while (nextTxWindow < radioNow + aAheadUs)
|
||||
{
|
||||
@@ -222,8 +222,7 @@ Mac::TxFrame *CslTxScheduler::HandleFrameRequest(Mac::TxFrames &aTxFrames)
|
||||
VerifyOrExit(delay <= mCslFrameRequestAheadUs + kFramePreparationGuardInterval, frame = nullptr);
|
||||
|
||||
frame->SetTxDelay(txDelay);
|
||||
frame->SetTxDelayBaseTime(
|
||||
static_cast<uint32_t>(mCslTxNeighbor->GetLastRxTimestamp())); // Only LSB part of the time is required.
|
||||
frame->SetTxDelayBaseTime(ConvertRadioTime64To32(mCslTxNeighbor->GetLastRxTimestamp()));
|
||||
frame->SetCsmaCaEnabled(true);
|
||||
|
||||
exit:
|
||||
|
||||
@@ -95,8 +95,8 @@ public:
|
||||
TimeMilli GetCslLastHeard(void) const { return mCslLastHeard; }
|
||||
void SetCslLastHeard(TimeMilli aCslLastHeard) { mCslLastHeard = aCslLastHeard; }
|
||||
|
||||
uint64_t GetLastRxTimestamp(void) const { return mLastRxTimestamp; }
|
||||
void SetLastRxTimestamp(uint64_t aLastRxTimestamp) { mLastRxTimestamp = aLastRxTimestamp; }
|
||||
RadioTime64 GetLastRxTimestamp(void) const { return mLastRxTimestamp; }
|
||||
void SetLastRxTimestamp(RadioTime64 aLastRxTimestamp) { mLastRxTimestamp = aLastRxTimestamp; }
|
||||
|
||||
private:
|
||||
uint8_t mCslTxAttempts : 7; ///< Number of CSL triggered tx attempts.
|
||||
|
||||
@@ -344,13 +344,13 @@ void KeyManager::UpdateKeyMaterial(void)
|
||||
Mac::KeyMaterial prevKey;
|
||||
Mac::KeyMaterial nextKey;
|
||||
|
||||
curKey.SetFrom(hashKeys.GetMacKey(), kExportableMacKeys);
|
||||
curKey.SetFrom(hashKeys.GetMacKey(), Mac::kDefaultMacKeysExportable);
|
||||
|
||||
ComputeKeys(mKeySequence - 1, hashKeys);
|
||||
prevKey.SetFrom(hashKeys.GetMacKey(), kExportableMacKeys);
|
||||
prevKey.SetFrom(hashKeys.GetMacKey(), Mac::kDefaultMacKeysExportable);
|
||||
|
||||
ComputeKeys(mKeySequence + 1, hashKeys);
|
||||
nextKey.SetFrom(hashKeys.GetMacKey(), kExportableMacKeys);
|
||||
nextKey.SetFrom(hashKeys.GetMacKey(), Mac::kDefaultMacKeysExportable);
|
||||
|
||||
Get<Mac::SubMac>().SetMacKey(Mac::Frame::kKeyIdMode1, (mKeySequence & 0x7f) + 1, prevKey, curKey, nextKey);
|
||||
}
|
||||
|
||||
@@ -571,7 +571,6 @@ public:
|
||||
private:
|
||||
static constexpr uint16_t kDefaultKeySwitchGuardTime = 624; // ~ 93% of 672 (default key rotation time)
|
||||
static constexpr uint32_t kKeySwitchGuardTimePercentage = 93; // Percentage of key rotation time.
|
||||
static constexpr bool kExportableMacKeys = OPENTHREAD_CONFIG_PLATFORM_MAC_KEYS_EXPORTABLE_ENABLE;
|
||||
|
||||
static_assert(kDefaultKeySwitchGuardTime ==
|
||||
SecurityPolicy::kDefaultKeyRotationTime * kKeySwitchGuardTimePercentage / 100,
|
||||
|
||||
@@ -970,6 +970,7 @@ Error Lowpan::DecompressUdpHeader(Message &aMessage, FrameData &aFrameData, uint
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(aDatagramLength >= aMessage.GetOffset() + sizeof(Ip6::UdpHeader), error = kErrorParse);
|
||||
udpHeader.SetLength(aDatagramLength - aMessage.GetOffset());
|
||||
}
|
||||
|
||||
@@ -1035,6 +1036,7 @@ Error Lowpan::Decompress(Message &aMessage,
|
||||
|
||||
if (aDatagramLength)
|
||||
{
|
||||
VerifyOrExit(aDatagramLength >= currentOffset + sizeof(Ip6::Header), error = kErrorParse);
|
||||
ip6PayloadLength = BigEndian::HostSwap16(aDatagramLength - currentOffset - sizeof(Ip6::Header));
|
||||
}
|
||||
else
|
||||
|
||||
@@ -53,11 +53,13 @@ void MessageFramer::DetermineMacSourceAddress(const Ip6::Address &aIp6Addr, Mac:
|
||||
}
|
||||
}
|
||||
|
||||
void MessageFramer::PrepareMacHeaders(Mac::TxFrame &aTxFrame, Mac::TxFrame::Info &aTxFrameInfo, const Message *aMessage)
|
||||
void MessageFramer::PrepareMacHeaders(Mac::TxFrame &aTxFrame,
|
||||
Mac::TxFrame::BuildInfo &aBuildInfo,
|
||||
const Message *aMessage)
|
||||
{
|
||||
const Neighbor *neighbor;
|
||||
|
||||
aTxFrameInfo.mVersion = Mac::Frame::kVersion2006;
|
||||
aBuildInfo.mVersion = Mac::Frame::kVersion2006;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
|
||||
@@ -67,7 +69,7 @@ void MessageFramer::PrepareMacHeaders(Mac::TxFrame &aTxFrame, Mac::TxFrame::Info
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Determine frame version and Header IE entries
|
||||
|
||||
neighbor = Get<NeighborTable>().FindNeighbor(aTxFrameInfo.mAddrs.mDestination);
|
||||
neighbor = Get<NeighborTable>().FindNeighbor(aBuildInfo.mAddrs.mDestination);
|
||||
|
||||
if (neighbor == nullptr)
|
||||
{
|
||||
@@ -75,20 +77,20 @@ void MessageFramer::PrepareMacHeaders(Mac::TxFrame &aTxFrame, Mac::TxFrame::Info
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
else if (Get<Mac::Mac>().IsCslEnabled())
|
||||
{
|
||||
aTxFrameInfo.mAppendCslIe = true;
|
||||
aTxFrameInfo.mVersion = Mac::Frame::kVersion2015;
|
||||
aBuildInfo.mAppendCslIe = true;
|
||||
aBuildInfo.mVersion = Mac::Frame::kVersion2015;
|
||||
}
|
||||
#endif
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
else if ((Get<ChildTable>().Contains(*neighbor) && static_cast<const Child *>(neighbor)->IsCslSynchronized()))
|
||||
{
|
||||
aTxFrameInfo.mVersion = Mac::Frame::kVersion2015;
|
||||
aBuildInfo.mVersion = Mac::Frame::kVersion2015;
|
||||
}
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
|
||||
else if (neighbor->IsEnhAckProbingActive())
|
||||
{
|
||||
aTxFrameInfo.mVersion = Mac::Frame::kVersion2015;
|
||||
aBuildInfo.mVersion = Mac::Frame::kVersion2015;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -98,19 +100,19 @@ void MessageFramer::PrepareMacHeaders(Mac::TxFrame &aTxFrame, Mac::TxFrame::Info
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
if ((aMessage != nullptr) && aMessage->IsTimeSync())
|
||||
{
|
||||
aTxFrameInfo.mAppendTimeIe = true;
|
||||
aTxFrameInfo.mVersion = Mac::Frame::kVersion2015;
|
||||
aBuildInfo.mAppendTimeIe = true;
|
||||
aBuildInfo.mVersion = Mac::Frame::kVersion2015;
|
||||
}
|
||||
#endif
|
||||
|
||||
aTxFrameInfo.mEmptyPayload = (aMessage == nullptr) || (aMessage->GetLength() == 0);
|
||||
aBuildInfo.mEmptyPayload = (aMessage == nullptr) || (aMessage->GetLength() == 0);
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Prepare MAC headers
|
||||
|
||||
aTxFrameInfo.PrepareHeadersIn(aTxFrame);
|
||||
aBuildInfo.PrepareHeadersIn(aTxFrame);
|
||||
|
||||
OT_UNUSED_VARIABLE(aMessage);
|
||||
OT_UNUSED_VARIABLE(neighbor);
|
||||
@@ -118,23 +120,23 @@ void MessageFramer::PrepareMacHeaders(Mac::TxFrame &aTxFrame, Mac::TxFrame::Info
|
||||
|
||||
void MessageFramer::PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address &aMacDest, bool aAckRequest)
|
||||
{
|
||||
Mac::TxFrame::Info frameInfo;
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
|
||||
frameInfo.mAddrs.mSource.SetShort(Get<Mac::Mac>().GetShortAddress());
|
||||
buildInfo.mAddrs.mSource.SetShort(Get<Mac::Mac>().GetShortAddress());
|
||||
|
||||
if (frameInfo.mAddrs.mSource.IsShortAddrInvalid() || aMacDest.IsExtended())
|
||||
if (buildInfo.mAddrs.mSource.IsShortAddrInvalid() || aMacDest.IsExtended())
|
||||
{
|
||||
frameInfo.mAddrs.mSource.SetExtended(Get<Mac::Mac>().GetExtAddress());
|
||||
buildInfo.mAddrs.mSource.SetExtended(Get<Mac::Mac>().GetExtAddress());
|
||||
}
|
||||
|
||||
frameInfo.mAddrs.mDestination = aMacDest;
|
||||
frameInfo.mPanIds.SetBothSourceDestination(Get<Mac::Mac>().GetPanId());
|
||||
buildInfo.mAddrs.mDestination = aMacDest;
|
||||
buildInfo.mPanIds.SetBothSourceDestination(Get<Mac::Mac>().GetPanId());
|
||||
|
||||
frameInfo.mType = Mac::Frame::kTypeData;
|
||||
frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
frameInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1;
|
||||
buildInfo.mType = Mac::Frame::kTypeData;
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
buildInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1;
|
||||
|
||||
PrepareMacHeaders(aFrame, frameInfo, nullptr);
|
||||
PrepareMacHeaders(aFrame, buildInfo, nullptr);
|
||||
|
||||
aFrame.SetAckRequest(aAckRequest);
|
||||
aFrame.SetPayloadLength(0);
|
||||
@@ -148,34 +150,34 @@ uint16_t MessageFramer::PrepareFrame(Mac::TxFrame &aFrame,
|
||||
uint16_t aMeshDest,
|
||||
bool aAddFragHeader)
|
||||
{
|
||||
Mac::TxFrame::Info frameInfo;
|
||||
uint16_t payloadLength;
|
||||
uint16_t origMsgOffset;
|
||||
uint16_t nextOffset;
|
||||
FrameBuilder frameBuilder;
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
uint16_t payloadLength;
|
||||
uint16_t origMsgOffset;
|
||||
uint16_t nextOffset;
|
||||
FrameBuilder frameBuilder;
|
||||
|
||||
start:
|
||||
frameInfo.Clear();
|
||||
buildInfo.Clear();
|
||||
|
||||
if (aMessage.IsLinkSecurityEnabled())
|
||||
{
|
||||
frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
|
||||
if (aMessage.GetSubType() == Message::kSubTypeJoinerEntrust)
|
||||
{
|
||||
frameInfo.mKeyIdMode = Mac::Frame::kKeyIdMode0;
|
||||
buildInfo.mKeyIdMode = Mac::Frame::kKeyIdMode0;
|
||||
}
|
||||
else if (aMessage.IsMleCommand(Mle::kCommandAnnounce))
|
||||
{
|
||||
frameInfo.mKeyIdMode = Mac::Frame::kKeyIdMode2;
|
||||
buildInfo.mKeyIdMode = Mac::Frame::kKeyIdMode2;
|
||||
}
|
||||
else
|
||||
{
|
||||
frameInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1;
|
||||
buildInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1;
|
||||
}
|
||||
}
|
||||
|
||||
frameInfo.mPanIds.SetBothSourceDestination(Get<Mac::Mac>().GetPanId());
|
||||
buildInfo.mPanIds.SetBothSourceDestination(Get<Mac::Mac>().GetPanId());
|
||||
|
||||
if (aMessage.IsSubTypeMle())
|
||||
{
|
||||
@@ -184,12 +186,12 @@ start:
|
||||
case Mle::kCommandAnnounce:
|
||||
aFrame.SetChannel(aMessage.GetChannel());
|
||||
aFrame.SetRxChannelAfterTxDone(Get<Mac::Mac>().GetPanChannel());
|
||||
frameInfo.mPanIds.SetDestination(Mac::kPanIdBroadcast);
|
||||
buildInfo.mPanIds.SetDestination(Mac::kPanIdBroadcast);
|
||||
break;
|
||||
|
||||
case Mle::kCommandDiscoveryRequest:
|
||||
case Mle::kCommandDiscoveryResponse:
|
||||
frameInfo.mPanIds.SetDestination(aMessage.GetPanId());
|
||||
buildInfo.mPanIds.SetDestination(aMessage.GetPanId());
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -197,10 +199,10 @@ start:
|
||||
}
|
||||
}
|
||||
|
||||
frameInfo.mType = Mac::Frame::kTypeData;
|
||||
frameInfo.mAddrs = aMacAddrs;
|
||||
buildInfo.mType = Mac::Frame::kTypeData;
|
||||
buildInfo.mAddrs = aMacAddrs;
|
||||
|
||||
PrepareMacHeaders(aFrame, frameInfo, &aMessage);
|
||||
PrepareMacHeaders(aFrame, buildInfo, &aMessage);
|
||||
|
||||
frameBuilder.Init(aFrame.GetPayload(), aFrame.GetMaxPayloadLength());
|
||||
|
||||
@@ -350,15 +352,15 @@ start:
|
||||
|
||||
uint16_t MessageFramer::PrepareMeshFrame(Mac::TxFrame &aFrame, Message &aMessage, const Mac::Addresses &aMacAddrs)
|
||||
{
|
||||
Mac::TxFrame::Info frameInfo;
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
|
||||
frameInfo.mType = Mac::Frame::kTypeData;
|
||||
frameInfo.mAddrs = aMacAddrs;
|
||||
frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
frameInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1;
|
||||
frameInfo.mPanIds.SetBothSourceDestination(Get<Mac::Mac>().GetPanId());
|
||||
buildInfo.mType = Mac::Frame::kTypeData;
|
||||
buildInfo.mAddrs = aMacAddrs;
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
buildInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1;
|
||||
buildInfo.mPanIds.SetBothSourceDestination(Get<Mac::Mac>().GetPanId());
|
||||
|
||||
PrepareMacHeaders(aFrame, frameInfo, &aMessage);
|
||||
PrepareMacHeaders(aFrame, buildInfo, &aMessage);
|
||||
|
||||
// write payload
|
||||
OT_ASSERT(aMessage.GetLength() <= aFrame.GetMaxPayloadLength());
|
||||
|
||||
@@ -131,7 +131,7 @@ private:
|
||||
// (requiring one hop) and one as additional guard increment.
|
||||
static constexpr uint8_t kMeshHeaderHopsLeft = Mle::kMaxRouteCost + 3;
|
||||
|
||||
void PrepareMacHeaders(Mac::TxFrame &aTxFrame, Mac::TxFrame::Info &aTxFrameInfo, const Message *aMessage);
|
||||
void PrepareMacHeaders(Mac::TxFrame &aTxFrame, Mac::TxFrame::BuildInfo &aBuildInfo, const Message *aMessage);
|
||||
|
||||
uint16_t mFragTag;
|
||||
};
|
||||
|
||||
@@ -1627,15 +1627,15 @@ otError RadioSpinel::Transmit(otRadioFrame &aFrame)
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
if (mTransmitFrame->mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0)
|
||||
{
|
||||
uint64_t netRadioTime = otPlatRadioGetNow(mInstance);
|
||||
uint64_t netSyncTime;
|
||||
uint8_t *timeIe = mTransmitFrame->mPsdu + mTransmitFrame->mInfo.mTxInfo.mIeInfo->mTimeIeOffset;
|
||||
otRadioTime64 netRadioTime = otPlatRadioGetNow(mInstance);
|
||||
otRadioTime64 netSyncTime;
|
||||
uint8_t *timeIe = mTransmitFrame->mPsdu + mTransmitFrame->mInfo.mTxInfo.mIeInfo->mTimeIeOffset;
|
||||
|
||||
if (netRadioTime == UINT64_MAX)
|
||||
{
|
||||
// If we can't get the radio time, get the platform time
|
||||
netSyncTime = static_cast<uint64_t>(static_cast<int64_t>(otPlatTimeGet()) +
|
||||
mTransmitFrame->mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset);
|
||||
netSyncTime = static_cast<otRadioTime64>(static_cast<int64_t>(otPlatTimeGet()) +
|
||||
mTransmitFrame->mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1644,16 +1644,16 @@ otError RadioSpinel::Transmit(otRadioFrame &aFrame)
|
||||
// If supported, add a delay and transmit the network time at a precise moment
|
||||
#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
transmitDelay = kTxWaitUs / 10;
|
||||
mTransmitFrame->mInfo.mTxInfo.mTxDelayBaseTime = static_cast<uint32_t>(netRadioTime);
|
||||
mTransmitFrame->mInfo.mTxInfo.mTxDelayBaseTime = static_cast<otRadioTime32>(netRadioTime);
|
||||
mTransmitFrame->mInfo.mTxInfo.mTxDelay = transmitDelay;
|
||||
#endif
|
||||
netSyncTime = static_cast<uint64_t>(static_cast<int64_t>(netRadioTime) + transmitDelay +
|
||||
mTransmitFrame->mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset);
|
||||
netSyncTime = static_cast<otRadioTime64>(static_cast<int64_t>(netRadioTime) + transmitDelay +
|
||||
mTransmitFrame->mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset);
|
||||
}
|
||||
|
||||
*(timeIe++) = mTransmitFrame->mInfo.mTxInfo.mIeInfo->mTimeSyncSeq;
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(uint64_t); i++)
|
||||
for (uint8_t i = 0; i < sizeof(otRadioTime64); i++)
|
||||
{
|
||||
*(timeIe++) = static_cast<uint8_t>(netSyncTime & 0xff);
|
||||
netSyncTime = netSyncTime >> 8;
|
||||
|
||||
@@ -1709,8 +1709,8 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_RX_AT>(void)
|
||||
SuccessOrExit(error = mDecoder.ReadUint8(channel));
|
||||
|
||||
{
|
||||
uint64_t now = otPlatRadioGetNow(mInstance);
|
||||
uint32_t start;
|
||||
otRadioTime64 now = otPlatRadioGetNow(mInstance);
|
||||
uint32_t start;
|
||||
|
||||
VerifyOrExit(when > now && (when - now) < UINT32_MAX, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
|
||||
@@ -978,7 +978,7 @@ void otPlatRadioSetMacFrameCounterIfLarger(otInstance *aInstance, uint32_t aMacF
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
}
|
||||
|
||||
uint64_t otPlatRadioGetNow(otInstance *aInstance)
|
||||
otRadioTime64 otPlatRadioGetNow(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return GetRadioSpinel().GetNow();
|
||||
@@ -1097,7 +1097,7 @@ otError otPlatRadioConfigureEnhAckProbing(otInstance *aInstance,
|
||||
}
|
||||
#endif
|
||||
|
||||
otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, uint32_t aStart, uint32_t aDuration)
|
||||
otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, otRadioTime32 aStart, uint32_t aDuration)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aChannel);
|
||||
|
||||
@@ -385,7 +385,7 @@ otError otPlatRadioSleep(otInstance *) { return OT_ERROR_NONE; }
|
||||
|
||||
otError otPlatRadioReceive(otInstance *, uint8_t aChannel) { return FakePlatform::CurrentPlatform().Receive(aChannel); }
|
||||
|
||||
otError otPlatRadioReceiveAt(otInstance *, uint8_t aChannel, uint32_t aStart, uint32_t aDuration)
|
||||
otError otPlatRadioReceiveAt(otInstance *, uint8_t aChannel, otRadioTime32 aStart, uint32_t aDuration)
|
||||
{
|
||||
return FakePlatform::CurrentPlatform().ReceiveAt(aChannel, aStart, aDuration);
|
||||
}
|
||||
|
||||
@@ -66,17 +66,17 @@ TEST(RadioSpinelTransmit, shouldPassDesiredTxPowerToRadioPlatform)
|
||||
txFrame.mPsdu = frameBuffer;
|
||||
|
||||
{
|
||||
Mac::TxFrame::Info frameInfo;
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
|
||||
frameInfo.mType = Mac::Frame::kTypeData;
|
||||
frameInfo.mVersion = Mac::Frame::kVersion2006;
|
||||
frameInfo.mAddrs.mSource.SetShort(kSrcAddr);
|
||||
frameInfo.mAddrs.mDestination.SetExtended(kDstAddr);
|
||||
frameInfo.mPanIds.SetSource(kSrcPanId);
|
||||
frameInfo.mPanIds.SetDestination(kDstPanId);
|
||||
frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
buildInfo.mType = Mac::Frame::kTypeData;
|
||||
buildInfo.mVersion = Mac::Frame::kVersion2006;
|
||||
buildInfo.mAddrs.mSource.SetShort(kSrcAddr);
|
||||
buildInfo.mAddrs.mDestination.SetExtended(kDstAddr);
|
||||
buildInfo.mPanIds.SetSource(kSrcPanId);
|
||||
buildInfo.mPanIds.SetDestination(kDstPanId);
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
|
||||
frameInfo.PrepareHeadersIn(txFrame);
|
||||
buildInfo.PrepareHeadersIn(txFrame);
|
||||
}
|
||||
|
||||
txFrame.mInfo.mTxInfo.mTxPower = kTxPower;
|
||||
@@ -110,17 +110,17 @@ TEST(RadioSpinelTransmit, shouldCauseSwitchingToRxChannelAfterTxDone)
|
||||
txFrame.mPsdu = frameBuffer;
|
||||
|
||||
{
|
||||
Mac::TxFrame::Info frameInfo;
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
|
||||
frameInfo.mType = Mac::Frame::kTypeData;
|
||||
frameInfo.mVersion = Mac::Frame::kVersion2006;
|
||||
frameInfo.mAddrs.mSource.SetShort(kSrcAddr);
|
||||
frameInfo.mAddrs.mDestination.SetExtended(kDstAddr);
|
||||
frameInfo.mPanIds.SetSource(kSrcPanId);
|
||||
frameInfo.mPanIds.SetDestination(kDstPanId);
|
||||
frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
buildInfo.mType = Mac::Frame::kTypeData;
|
||||
buildInfo.mVersion = Mac::Frame::kVersion2006;
|
||||
buildInfo.mAddrs.mSource.SetShort(kSrcAddr);
|
||||
buildInfo.mAddrs.mDestination.SetExtended(kDstAddr);
|
||||
buildInfo.mPanIds.SetSource(kSrcPanId);
|
||||
buildInfo.mPanIds.SetDestination(kDstPanId);
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
|
||||
frameInfo.PrepareHeadersIn(txFrame);
|
||||
buildInfo.PrepareHeadersIn(txFrame);
|
||||
}
|
||||
|
||||
txFrame.mInfo.mTxInfo.mTxPower = kTxPower;
|
||||
@@ -156,17 +156,17 @@ TEST(RadioSpinelTransmit, shouldSkipCsmaCaWhenDisabled)
|
||||
txFrame.mPsdu = frameBuffer;
|
||||
|
||||
{
|
||||
Mac::TxFrame::Info frameInfo;
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
|
||||
frameInfo.mType = Mac::Frame::kTypeData;
|
||||
frameInfo.mVersion = Mac::Frame::kVersion2006;
|
||||
frameInfo.mAddrs.mSource.SetShort(kSrcAddr);
|
||||
frameInfo.mAddrs.mDestination.SetExtended(kDstAddr);
|
||||
frameInfo.mPanIds.SetSource(kSrcPanId);
|
||||
frameInfo.mPanIds.SetDestination(kDstPanId);
|
||||
frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
buildInfo.mType = Mac::Frame::kTypeData;
|
||||
buildInfo.mVersion = Mac::Frame::kVersion2006;
|
||||
buildInfo.mAddrs.mSource.SetShort(kSrcAddr);
|
||||
buildInfo.mAddrs.mDestination.SetExtended(kDstAddr);
|
||||
buildInfo.mPanIds.SetSource(kSrcPanId);
|
||||
buildInfo.mPanIds.SetDestination(kDstPanId);
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
|
||||
frameInfo.PrepareHeadersIn(txFrame);
|
||||
buildInfo.PrepareHeadersIn(txFrame);
|
||||
}
|
||||
|
||||
txFrame.mInfo.mTxInfo.mCsmaCaEnabled = false;
|
||||
@@ -212,17 +212,17 @@ TEST(RadioSpinelTransmit, shouldPerformCsmaCaWhenEnabled)
|
||||
txFrame.mPsdu = frameBuffer;
|
||||
|
||||
{
|
||||
Mac::TxFrame::Info frameInfo;
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
|
||||
frameInfo.mType = Mac::Frame::kTypeData;
|
||||
frameInfo.mVersion = Mac::Frame::kVersion2006;
|
||||
frameInfo.mAddrs.mSource.SetShort(kSrcAddr);
|
||||
frameInfo.mAddrs.mDestination.SetExtended(kDstAddr);
|
||||
frameInfo.mPanIds.SetSource(kSrcPanId);
|
||||
frameInfo.mPanIds.SetDestination(kDstPanId);
|
||||
frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
buildInfo.mType = Mac::Frame::kTypeData;
|
||||
buildInfo.mVersion = Mac::Frame::kVersion2006;
|
||||
buildInfo.mAddrs.mSource.SetShort(kSrcAddr);
|
||||
buildInfo.mAddrs.mDestination.SetExtended(kDstAddr);
|
||||
buildInfo.mPanIds.SetSource(kSrcPanId);
|
||||
buildInfo.mPanIds.SetDestination(kDstPanId);
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
|
||||
frameInfo.PrepareHeadersIn(txFrame);
|
||||
buildInfo.PrepareHeadersIn(txFrame);
|
||||
}
|
||||
|
||||
txFrame.mInfo.mTxInfo.mCsmaCaEnabled = true;
|
||||
@@ -262,17 +262,17 @@ TEST(RadioSpinelTransmit, shouldNotCauseSwitchingToRxAfterTxDoneIfNotRxOnWhenIdl
|
||||
txFrame.mPsdu = frameBuffer;
|
||||
|
||||
{
|
||||
Mac::TxFrame::Info frameInfo;
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
|
||||
frameInfo.mType = Mac::Frame::kTypeData;
|
||||
frameInfo.mVersion = Mac::Frame::kVersion2006;
|
||||
frameInfo.mAddrs.mSource.SetShort(kSrcAddr);
|
||||
frameInfo.mAddrs.mDestination.SetExtended(kDstAddr);
|
||||
frameInfo.mPanIds.SetSource(kSrcPanId);
|
||||
frameInfo.mPanIds.SetDestination(kDstPanId);
|
||||
frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
buildInfo.mType = Mac::Frame::kTypeData;
|
||||
buildInfo.mVersion = Mac::Frame::kVersion2006;
|
||||
buildInfo.mAddrs.mSource.SetShort(kSrcAddr);
|
||||
buildInfo.mAddrs.mDestination.SetExtended(kDstAddr);
|
||||
buildInfo.mPanIds.SetSource(kSrcPanId);
|
||||
buildInfo.mPanIds.SetDestination(kDstPanId);
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
|
||||
frameInfo.PrepareHeadersIn(txFrame);
|
||||
buildInfo.PrepareHeadersIn(txFrame);
|
||||
}
|
||||
|
||||
txFrame.mInfo.mTxInfo.mTxPower = kTxPower;
|
||||
@@ -338,17 +338,17 @@ TEST(RadioSpinelTransmit, shouldSkipCsmaBackoffWhenCsmaCaIsEnabledAndMaxBackoffs
|
||||
txFrame.mPsdu = frameBuffer;
|
||||
|
||||
{
|
||||
Mac::TxFrame::Info frameInfo;
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
|
||||
frameInfo.mType = Mac::Frame::kTypeData;
|
||||
frameInfo.mVersion = Mac::Frame::kVersion2006;
|
||||
frameInfo.mAddrs.mSource.SetShort(kSrcAddr);
|
||||
frameInfo.mAddrs.mDestination.SetExtended(kDstAddr);
|
||||
frameInfo.mPanIds.SetSource(kSrcPanId);
|
||||
frameInfo.mPanIds.SetDestination(kDstPanId);
|
||||
frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
buildInfo.mType = Mac::Frame::kTypeData;
|
||||
buildInfo.mVersion = Mac::Frame::kVersion2006;
|
||||
buildInfo.mAddrs.mSource.SetShort(kSrcAddr);
|
||||
buildInfo.mAddrs.mDestination.SetExtended(kDstAddr);
|
||||
buildInfo.mPanIds.SetSource(kSrcPanId);
|
||||
buildInfo.mPanIds.SetDestination(kDstPanId);
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
|
||||
frameInfo.PrepareHeadersIn(txFrame);
|
||||
buildInfo.PrepareHeadersIn(txFrame);
|
||||
}
|
||||
|
||||
txFrame.mInfo.mTxInfo.mCsmaCaEnabled = true;
|
||||
|
||||
@@ -156,7 +156,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
uint64_t otPlatRadioGetNow(otInstance *aInstance)
|
||||
otRadioTime64 otPlatRadioGetNow(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
@@ -332,7 +332,7 @@ otError otPlatRadioResetCsl(otInstance *aInstance)
|
||||
return kErrorNone;
|
||||
}
|
||||
|
||||
void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, uint32_t aCslSampleTime)
|
||||
void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, otRadioTime32 aCslSampleTime)
|
||||
{
|
||||
AsNode(aInstance).mRadio.mRadioContext.mCslSampleTime = aCslSampleTime;
|
||||
}
|
||||
|
||||
@@ -1,237 +0,0 @@
|
||||
#!/usr/bin/expect -f
|
||||
|
||||
#
|
||||
# Copyright (c) 2025, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
source "tests/scripts/expect/_common.exp"
|
||||
source "tests/scripts/expect/_multinode.exp"
|
||||
|
||||
set WL1 1
|
||||
set WL2 2
|
||||
set WC1 3
|
||||
set WC2 4
|
||||
set WL1_EXT_ADDRESS "deadbeefcafe0001"
|
||||
set WL2_EXT_ADDRESS "deadbeefcafe0002"
|
||||
set WC1_EXT_ADDRESS "deadbeefcafe0003"
|
||||
set WC2_EXT_ADDRESS "deadbeefcafe0004"
|
||||
|
||||
|
||||
send_user "\n\n>>> Setup WL1\n"
|
||||
spawn_node $WL1
|
||||
|
||||
setup_default_network
|
||||
|
||||
send "mode rdn\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "extaddr $WL1_EXT_ADDRESS\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "wakeup channel 11\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "routerupgradethreshold 0\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "ifconfig up\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "thread start\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "wakeup listen enable\n"
|
||||
expect_line "Done"
|
||||
|
||||
set wl1_link_local_addr [get_ipaddr linklocal]
|
||||
|
||||
|
||||
send_user "\n\n>>> Setup WL2\n"
|
||||
spawn_node $WL2
|
||||
|
||||
setup_default_network
|
||||
|
||||
send "mode rdn\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "extaddr $WL2_EXT_ADDRESS\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "wakeup channel 11\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "routerupgradethreshold 0\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "ifconfig up\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "thread start\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "wakeup listen enable\n"
|
||||
expect_line "Done"
|
||||
|
||||
set wl2_link_local_addr [get_ipaddr linklocal]
|
||||
|
||||
|
||||
send_user "\n\n>>> Setup WC1\n"
|
||||
spawn_node $WC1
|
||||
setup_default_network
|
||||
|
||||
send "mode rdn\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "extaddr $WC1_EXT_ADDRESS\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "wakeup channel 11\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "routerupgradethreshold 0\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "ifconfig up\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "thread start\n"
|
||||
expect_line "Done"
|
||||
|
||||
set wc1_link_local_addr [get_ipaddr linklocal]
|
||||
|
||||
|
||||
send_user "\n\n>>> Setup WC2\n"
|
||||
spawn_node $WC2
|
||||
setup_default_network
|
||||
|
||||
send "mode rdn\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "extaddr $WC2_EXT_ADDRESS\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "wakeup channel 11\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "routerupgradethreshold 0\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "ifconfig up\n"
|
||||
expect_line "Done"
|
||||
|
||||
send "thread start\n"
|
||||
expect_line "Done"
|
||||
|
||||
set wc2_link_local_addr [get_ipaddr linklocal]
|
||||
|
||||
|
||||
send_user "\n\n>>> WC1 establishes a P2P link with WL1\n"
|
||||
switch_node $WC1
|
||||
send "p2p link extaddr $WL1_EXT_ADDRESS\n"
|
||||
expect_line "Done"
|
||||
|
||||
send_user "\n\n>>> WC1 pings WL1\n"
|
||||
send "ping $wl1_link_local_addr 20 5\n"
|
||||
for {set i 1} {$i <= 5} {incr i} {
|
||||
expect "28 bytes from $wl1_link_local_addr: icmp_seq=$i"
|
||||
}
|
||||
|
||||
sleep 1
|
||||
|
||||
|
||||
send_user "\n\n>>> WC1 establishes a P2P link with WL2\n"
|
||||
send "p2p link extaddr $WL2_EXT_ADDRESS\n"
|
||||
expect_line "Done"
|
||||
|
||||
sleep 1
|
||||
|
||||
send_user "\n\n>>> WC1 pings WL2\n"
|
||||
send "ping $wl2_link_local_addr 20 5\n"
|
||||
for {set i 6} {$i <= 10} {incr i} {
|
||||
expect "28 bytes from $wl2_link_local_addr: icmp_seq=$i"
|
||||
}
|
||||
|
||||
|
||||
send_user "\n\n>>> WC2 establishes a P2P link with WL1\n"
|
||||
switch_node $WC2
|
||||
send "p2p link extaddr $WL1_EXT_ADDRESS\n"
|
||||
expect_line "Done"
|
||||
|
||||
sleep 1
|
||||
|
||||
send_user "\n\n>>> WC2 pings WL1\n"
|
||||
send "ping $wl1_link_local_addr 20 5\n"
|
||||
for {set i 1} {$i <= 5} {incr i} {
|
||||
expect "28 bytes from $wl1_link_local_addr: icmp_seq=$i"
|
||||
}
|
||||
|
||||
|
||||
send_user "\n\n>>> WL1 pings WC1\n"
|
||||
switch_node $WL1
|
||||
|
||||
send "ping $wc1_link_local_addr 20 5\n"
|
||||
for {set i 1} {$i <= 5} {incr i} {
|
||||
expect "28 bytes from $wc1_link_local_addr: icmp_seq=$i"
|
||||
}
|
||||
|
||||
|
||||
send_user "\n\n>>> WL1 pings WC2\n"
|
||||
send "ping $wc2_link_local_addr 20 5\n"
|
||||
for {set i 6} {$i <= 10} {incr i} {
|
||||
expect "28 bytes from $wc2_link_local_addr: icmp_seq=$i"
|
||||
}
|
||||
|
||||
|
||||
send_user "\n\n>>> WL2 pings WC1\n"
|
||||
switch_node $WL2
|
||||
|
||||
send "ping $wc1_link_local_addr 20 5\n"
|
||||
for {set i 1} {$i <= 5} {incr i} {
|
||||
expect "28 bytes from $wc1_link_local_addr: icmp_seq=$i"
|
||||
}
|
||||
|
||||
|
||||
send_user "\n\n>>> WC1 tears down the P2P link with WL1\n"
|
||||
switch_node $WC1
|
||||
send "p2p unlink $WL1_EXT_ADDRESS\n"
|
||||
expect_line "Done"
|
||||
|
||||
|
||||
send_user "\n\n>>> WC2 tears down the P2P link with WL1\n"
|
||||
switch_node $WC2
|
||||
send "p2p unlink $WL1_EXT_ADDRESS\n"
|
||||
expect_line "Done"
|
||||
|
||||
|
||||
send_user "\n\n>>> WL2 tears down the P2P link with WC1\n"
|
||||
switch_node $WL2
|
||||
send "p2p unlink $WC1_EXT_ADDRESS\n"
|
||||
expect_line "Done"
|
||||
|
||||
sleep 1
|
||||
|
||||
dispose_all
|
||||
@@ -339,6 +339,115 @@ void TestAesCcmMessageProcessing(void)
|
||||
printf("\nTestAesCcmMessageProcessing PASSED\n\n");
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
|
||||
/**
|
||||
* Verifies `otPlatCryptoAesCcmProcessOneShot` directly and via `AesCcm::Process`,
|
||||
* using IEEE 802.15.4-2006 Annex C Section C.2.3
|
||||
* (MAC command frame: 29-byte header, 1-byte payload, 8-byte MIC).
|
||||
*/
|
||||
void TestPlatformCcmSinglePart(void)
|
||||
{
|
||||
static const uint8_t kKey[] = {
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
};
|
||||
|
||||
static const uint8_t kNonce[] = {
|
||||
0xAC, 0xDE, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x06,
|
||||
};
|
||||
|
||||
static constexpr uint32_t kHeaderLength = 29;
|
||||
static constexpr uint32_t kPayloadLength = 1;
|
||||
static constexpr uint8_t kTagLength = 8;
|
||||
static constexpr uint32_t kFrameLength = kHeaderLength + kPayloadLength + kTagLength;
|
||||
|
||||
static const uint8_t kPlainFrame[kHeaderLength + kPayloadLength] = {
|
||||
0x2B, 0xDC, 0x84, 0x21, 0x43, 0x02, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC, 0xFF, 0xFF,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x06, 0x05, 0x00, 0x00, 0x00, 0x01, 0xCE,
|
||||
};
|
||||
|
||||
static const uint8_t kEncryptedFrame[kFrameLength] = {
|
||||
0x2B, 0xDC, 0x84, 0x21, 0x43, 0x02, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC,
|
||||
0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x06, 0x05, 0x00,
|
||||
0x00, 0x00, 0x01, 0xD8, 0x4F, 0xDE, 0x52, 0x90, 0x61, 0xF9, 0xC6, 0xF1,
|
||||
};
|
||||
|
||||
otInstance *instance = testInitInstance();
|
||||
uint8_t frame[kFrameLength];
|
||||
otPlatCryptoAesCcmConfig config;
|
||||
|
||||
printf("TestPlatformCcmSinglePart\n");
|
||||
|
||||
VerifyOrQuit(instance != nullptr);
|
||||
|
||||
config.mKey.mKey = kKey;
|
||||
config.mKey.mKeyLength = sizeof(kKey);
|
||||
config.mKey.mKeyRef = 0;
|
||||
config.mNonce = kNonce;
|
||||
config.mNonceLength = sizeof(kNonce);
|
||||
config.mTagLength = kTagLength;
|
||||
config.mHeaderLength = kHeaderLength;
|
||||
config.mPlainTextLength = kPayloadLength;
|
||||
|
||||
// Direct encrypt/decrypt round-trip through the platform hook.
|
||||
memcpy(frame, kPlainFrame, sizeof(kPlainFrame));
|
||||
memset(frame + kHeaderLength + kPayloadLength, 0, kTagLength);
|
||||
SuccessOrQuit(otPlatCryptoAesCcmProcessOneShot(true, &config, frame, frame + kHeaderLength));
|
||||
DumpBuffer("encrypted", frame, sizeof(frame));
|
||||
VerifyOrQuit(memcmp(frame, kEncryptedFrame, kFrameLength) == 0);
|
||||
|
||||
SuccessOrQuit(otPlatCryptoAesCcmProcessOneShot(false, &config, frame, frame + kHeaderLength));
|
||||
DumpBuffer("decrypted", frame, kHeaderLength + kPayloadLength);
|
||||
VerifyOrQuit(memcmp(frame, kPlainFrame, kHeaderLength + kPayloadLength) == 0);
|
||||
|
||||
// Tag corruption must be rejected.
|
||||
memcpy(frame, kPlainFrame, sizeof(kPlainFrame));
|
||||
memset(frame + kHeaderLength + kPayloadLength, 0, kTagLength);
|
||||
SuccessOrQuit(otPlatCryptoAesCcmProcessOneShot(true, &config, frame, frame + kHeaderLength));
|
||||
frame[kHeaderLength + kPayloadLength] ^= 0xFF;
|
||||
VerifyOrQuit(otPlatCryptoAesCcmProcessOneShot(false, &config, frame, frame + kHeaderLength) == kErrorSecurity);
|
||||
|
||||
memcpy(frame, kPlainFrame, sizeof(kPlainFrame));
|
||||
memset(frame + kHeaderLength + kPayloadLength, 0, kTagLength);
|
||||
SuccessOrQuit(otPlatCryptoAesCcmProcessOneShot(true, &config, frame, frame + kHeaderLength));
|
||||
frame[kFrameLength - 1] ^= 0x01;
|
||||
VerifyOrQuit(otPlatCryptoAesCcmProcessOneShot(false, &config, frame, frame + kHeaderLength) == kErrorSecurity);
|
||||
|
||||
// AesCcm::Process must produce the same result as the direct platform call.
|
||||
{
|
||||
uint8_t directResult[kFrameLength];
|
||||
uint8_t aesCcmResult[kFrameLength];
|
||||
Crypto::AesCcm aesCcm;
|
||||
|
||||
memcpy(directResult, kPlainFrame, sizeof(kPlainFrame));
|
||||
memset(directResult + kHeaderLength + kPayloadLength, 0, kTagLength);
|
||||
SuccessOrQuit(otPlatCryptoAesCcmProcessOneShot(true, &config, directResult, directResult + kHeaderLength));
|
||||
|
||||
memcpy(aesCcmResult, kPlainFrame, sizeof(kPlainFrame));
|
||||
memset(aesCcmResult + kHeaderLength + kPayloadLength, 0, kTagLength);
|
||||
aesCcm.SetKey(kKey, sizeof(kKey));
|
||||
aesCcm.SetNonce(kNonce, sizeof(kNonce));
|
||||
aesCcm.SetAuthData(aesCcmResult, kHeaderLength);
|
||||
aesCcm.SetTagLength(kTagLength);
|
||||
SuccessOrQuit(aesCcm.Process(Crypto::AesCcm::kEncrypt, aesCcmResult + kHeaderLength, kPayloadLength));
|
||||
VerifyOrQuit(memcmp(directResult, aesCcmResult, kFrameLength) == 0);
|
||||
VerifyOrQuit(memcmp(aesCcmResult, kEncryptedFrame, kFrameLength) == 0);
|
||||
|
||||
aesCcm.SetKey(kKey, sizeof(kKey));
|
||||
aesCcm.SetNonce(kNonce, sizeof(kNonce));
|
||||
aesCcm.SetAuthData(aesCcmResult, kHeaderLength);
|
||||
aesCcm.SetTagLength(kTagLength);
|
||||
SuccessOrQuit(aesCcm.Process(Crypto::AesCcm::kDecrypt, aesCcmResult + kHeaderLength, kPayloadLength));
|
||||
VerifyOrQuit(memcmp(aesCcmResult, kPlainFrame, kHeaderLength + kPayloadLength) == 0);
|
||||
}
|
||||
|
||||
testFreeInstance(instance);
|
||||
|
||||
printf("\nTestPlatformCcmSinglePart PASSED\n\n");
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
@@ -346,6 +455,9 @@ int main(void)
|
||||
ot::TestMacBeaconFrame();
|
||||
ot::TestMacCommandFrame();
|
||||
ot::TestAesCcmMessageProcessing();
|
||||
#if OPENTHREAD_CONFIG_CRYPTO_PLATFORM_CCM_ONE_SHOT_ENABLE
|
||||
ot::TestPlatformCcmSinglePart();
|
||||
#endif
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -37,23 +37,28 @@ namespace ot {
|
||||
|
||||
void TestCountBitsInMask(void)
|
||||
{
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(0) == 0);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(1) == 1);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(2) == 1);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(3) == 2);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(4) == 1);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(7) == 3);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(11) == 3);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(15) == 4);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(0x11) == 2);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(0xef) == 7);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(0xff) == 8);
|
||||
VerifyOrQuit(CountBitsInMask(0) == 0);
|
||||
VerifyOrQuit(CountBitsInMask(1) == 1);
|
||||
VerifyOrQuit(CountBitsInMask(2) == 1);
|
||||
VerifyOrQuit(CountBitsInMask(3) == 2);
|
||||
VerifyOrQuit(CountBitsInMask(4) == 1);
|
||||
VerifyOrQuit(CountBitsInMask(7) == 3);
|
||||
VerifyOrQuit(CountBitsInMask(11) == 3);
|
||||
VerifyOrQuit(CountBitsInMask(15) == 4);
|
||||
VerifyOrQuit(CountBitsInMask(0x11) == 2);
|
||||
VerifyOrQuit(CountBitsInMask(0xef) == 7);
|
||||
VerifyOrQuit(CountBitsInMask(0xff) == 8);
|
||||
|
||||
VerifyOrQuit(CountBitsInMask<uint16_t>(0) == 0);
|
||||
VerifyOrQuit(CountBitsInMask<uint16_t>(0xff00) == 8);
|
||||
VerifyOrQuit(CountBitsInMask<uint16_t>(0xff) == 8);
|
||||
VerifyOrQuit(CountBitsInMask<uint16_t>(0xaa55) == 8);
|
||||
VerifyOrQuit(CountBitsInMask<uint16_t>(0xffff) == 16);
|
||||
VerifyOrQuit(CountBitsInMask(0xff00) == 8);
|
||||
VerifyOrQuit(CountBitsInMask(0xaa55) == 8);
|
||||
VerifyOrQuit(CountBitsInMask(0xffff) == 16);
|
||||
|
||||
VerifyOrQuit(CountBitsInMask(0x10000) == 1);
|
||||
VerifyOrQuit(CountBitsInMask(0xff0055) == 12);
|
||||
VerifyOrQuit(CountBitsInMask(0xaa0055) == 8);
|
||||
VerifyOrQuit(CountBitsInMask(0xaa007700) == 10);
|
||||
VerifyOrQuit(CountBitsInMask(0xffff0000) == 16);
|
||||
VerifyOrQuit(CountBitsInMask(0xffffffff) == 32);
|
||||
|
||||
printf("TestCountBitsInMask() passed\n");
|
||||
}
|
||||
@@ -130,6 +135,47 @@ void TestCountMatchingBitsExamples(void)
|
||||
printf("TestCountMatchingBitsExamples() passed\n");
|
||||
}
|
||||
|
||||
void TestDetermineMinBitSize(void)
|
||||
{
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(0) == 1);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(1) == 1);
|
||||
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(2) == 2);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(3) == 2);
|
||||
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(4) == 3);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(6) == 3);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(7) == 3);
|
||||
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(8) == 4);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(11) == 4);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(15) == 4);
|
||||
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(16) == 5);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(30) == 5);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(32) == 6);
|
||||
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(127) == 7);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(128) == 8);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(255) == 8);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(256) == 9);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(500) == 9);
|
||||
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(1000) == 10);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(1023) == 10);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(1024) == 11);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(2000) == 11);
|
||||
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(0xffff) == 16);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(0x10000) == 17);
|
||||
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(0x7fffffff) == 31);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(0x80000000) == 32);
|
||||
VerifyOrQuit(DetermineMinBitSizeFor(0xffffffff) == 32);
|
||||
|
||||
printf("TestDetermineMinBitSize() passed\n");
|
||||
}
|
||||
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
@@ -137,6 +183,7 @@ int main(void)
|
||||
ot::TestCountBitsInMask();
|
||||
ot::TestCountMatchingBitsAllCombinations();
|
||||
ot::TestCountMatchingBitsExamples();
|
||||
ot::TestDetermineMinBitSize();
|
||||
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
|
||||
+113
-316
@@ -290,43 +290,43 @@ void TestMacHeader(void)
|
||||
uint8_t psdu[OT_RADIO_FRAME_MAX_SIZE];
|
||||
uint8_t offset;
|
||||
|
||||
Mac::TxFrame frame;
|
||||
Mac::TxFrame::Info frameInfo;
|
||||
Mac::Address address;
|
||||
Mac::PanId panId;
|
||||
Mac::TxFrame frame;
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
Mac::Address address;
|
||||
Mac::PanId panId;
|
||||
|
||||
frame.mPsdu = psdu;
|
||||
frame.mLength = 0;
|
||||
frame.mRadioType = 0;
|
||||
|
||||
VerifyOrQuit(frameInfo.mAddrs.mSource.IsNone());
|
||||
VerifyOrQuit(frameInfo.mAddrs.mDestination.IsNone());
|
||||
VerifyOrQuit(!frameInfo.mPanIds.IsSourcePresent());
|
||||
VerifyOrQuit(!frameInfo.mPanIds.IsDestinationPresent());
|
||||
VerifyOrQuit(buildInfo.mAddrs.mSource.IsNone());
|
||||
VerifyOrQuit(buildInfo.mAddrs.mDestination.IsNone());
|
||||
VerifyOrQuit(!buildInfo.mPanIds.IsSourcePresent());
|
||||
VerifyOrQuit(!buildInfo.mPanIds.IsDestinationPresent());
|
||||
|
||||
switch (testCase.mSrcAddrType)
|
||||
{
|
||||
case kNoneAddr:
|
||||
frameInfo.mAddrs.mSource.SetNone();
|
||||
buildInfo.mAddrs.mSource.SetNone();
|
||||
break;
|
||||
case kShrtAddr:
|
||||
frameInfo.mAddrs.mSource.SetShort(kShortAddr1);
|
||||
buildInfo.mAddrs.mSource.SetShort(kShortAddr1);
|
||||
break;
|
||||
case kExtdAddr:
|
||||
frameInfo.mAddrs.mSource.SetExtended(extAddr1);
|
||||
buildInfo.mAddrs.mSource.SetExtended(extAddr1);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (testCase.mDstAddrType)
|
||||
{
|
||||
case kNoneAddr:
|
||||
frameInfo.mAddrs.mDestination.SetNone();
|
||||
buildInfo.mAddrs.mDestination.SetNone();
|
||||
break;
|
||||
case kShrtAddr:
|
||||
frameInfo.mAddrs.mDestination.SetShort(kShortAddr2);
|
||||
buildInfo.mAddrs.mDestination.SetShort(kShortAddr2);
|
||||
break;
|
||||
case kExtdAddr:
|
||||
frameInfo.mAddrs.mDestination.SetExtended(extAddr2);
|
||||
buildInfo.mAddrs.mDestination.SetExtended(extAddr2);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -335,10 +335,10 @@ void TestMacHeader(void)
|
||||
case kNoPanId:
|
||||
break;
|
||||
case kUsePanId1:
|
||||
frameInfo.mPanIds.SetSource(kPanId1);
|
||||
buildInfo.mPanIds.SetSource(kPanId1);
|
||||
break;
|
||||
case kUsePanId2:
|
||||
frameInfo.mPanIds.SetSource(kPanId2);
|
||||
buildInfo.mPanIds.SetSource(kPanId2);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -347,20 +347,20 @@ void TestMacHeader(void)
|
||||
case kNoPanId:
|
||||
break;
|
||||
case kUsePanId1:
|
||||
frameInfo.mPanIds.SetDestination(kPanId1);
|
||||
buildInfo.mPanIds.SetDestination(kPanId1);
|
||||
break;
|
||||
case kUsePanId2:
|
||||
frameInfo.mPanIds.SetDestination(kPanId2);
|
||||
buildInfo.mPanIds.SetDestination(kPanId2);
|
||||
break;
|
||||
}
|
||||
|
||||
frameInfo.mType = Mac::Frame::kTypeData;
|
||||
frameInfo.mVersion = testCase.mVersion;
|
||||
frameInfo.mSecurityLevel = testCase.mSecurity;
|
||||
frameInfo.mKeyIdMode = testCase.mKeyIdMode;
|
||||
frameInfo.mSuppressSequence = testCase.mSuppressSequence;
|
||||
buildInfo.mType = Mac::Frame::kTypeData;
|
||||
buildInfo.mVersion = testCase.mVersion;
|
||||
buildInfo.mSecurityLevel = testCase.mSecurity;
|
||||
buildInfo.mKeyIdMode = testCase.mKeyIdMode;
|
||||
buildInfo.mSuppressSequence = testCase.mSuppressSequence;
|
||||
|
||||
frameInfo.PrepareHeadersIn(frame);
|
||||
buildInfo.PrepareHeadersIn(frame);
|
||||
|
||||
VerifyOrQuit(frame.GetHeaderLength() == testCase.mHeaderLength);
|
||||
VerifyOrQuit(frame.GetFooterLength() == testCase.mFooterLength);
|
||||
@@ -376,25 +376,25 @@ void TestMacHeader(void)
|
||||
|
||||
VerifyOrQuit(frame.IsSrcAddrPresent() == (testCase.mSrcAddrType != kNoneAddr));
|
||||
SuccessOrQuit(frame.GetSrcAddr(address));
|
||||
VerifyOrQuit(CompareAddresses(address, frameInfo.mAddrs.mSource));
|
||||
VerifyOrQuit(CompareAddresses(address, buildInfo.mAddrs.mSource));
|
||||
VerifyOrQuit(frame.IsDstAddrPresent() == (testCase.mDstAddrType != kNoneAddr));
|
||||
SuccessOrQuit(frame.GetDstAddr(address));
|
||||
VerifyOrQuit(CompareAddresses(address, frameInfo.mAddrs.mDestination));
|
||||
VerifyOrQuit(CompareAddresses(address, buildInfo.mAddrs.mDestination));
|
||||
|
||||
VerifyOrQuit(frame.IsDstPanIdPresent() == (testCase.mDstPanIdMode != kNoPanId));
|
||||
|
||||
if (frame.IsDstPanIdPresent())
|
||||
{
|
||||
SuccessOrQuit(frame.GetDstPanId(panId));
|
||||
VerifyOrQuit(panId == frameInfo.mPanIds.GetDestination());
|
||||
VerifyOrQuit(frameInfo.mPanIds.IsDestinationPresent());
|
||||
VerifyOrQuit(panId == buildInfo.mPanIds.GetDestination());
|
||||
VerifyOrQuit(buildInfo.mPanIds.IsDestinationPresent());
|
||||
}
|
||||
|
||||
if (frame.IsSrcPanIdPresent())
|
||||
{
|
||||
SuccessOrQuit(frame.GetSrcPanId(panId));
|
||||
VerifyOrQuit(panId == frameInfo.mPanIds.GetSource());
|
||||
VerifyOrQuit(frameInfo.mPanIds.IsSourcePresent());
|
||||
VerifyOrQuit(panId == buildInfo.mPanIds.GetSource());
|
||||
VerifyOrQuit(buildInfo.mPanIds.IsSourcePresent());
|
||||
}
|
||||
|
||||
if (frame.GetSecurityEnabled())
|
||||
@@ -470,6 +470,88 @@ void VerifyChannelMaskContent(const Mac::ChannelMask &aMask, uint8_t *aChannels,
|
||||
VerifyOrQuit(aLength == aMask.GetNumberOfChannels());
|
||||
}
|
||||
|
||||
void TestMacHeaderIeStartEnd(void)
|
||||
{
|
||||
using HeaderIe = Mac::HeaderIe;
|
||||
|
||||
static const uint8_t kIeId1 = 0x0a;
|
||||
static const uint8_t kIeId2 = 0x0b;
|
||||
static const uint8_t kIeId3 = 0x0c;
|
||||
static const uint8_t kContent[] = {0x11, 0x22, 0x33, 0x44, 0x55};
|
||||
|
||||
uint8_t buffer[256];
|
||||
FrameBuilder builder;
|
||||
uint16_t offset;
|
||||
HeaderIe::Bookmark bookmark;
|
||||
HeaderIe *ie;
|
||||
uint8_t largeContent[128];
|
||||
|
||||
printf("TestMacHeaderIeStartEnd\n");
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Normal use: Append an IE (5 bytes content)
|
||||
|
||||
builder.Init(buffer, sizeof(buffer));
|
||||
SuccessOrQuit(HeaderIe::StartIe(builder, kIeId1, bookmark));
|
||||
VerifyOrQuit(builder.GetLength() == sizeof(HeaderIe));
|
||||
|
||||
SuccessOrQuit(builder.AppendBytes(kContent, sizeof(kContent)));
|
||||
SuccessOrQuit(HeaderIe::EndIe(builder, bookmark));
|
||||
|
||||
VerifyOrQuit(builder.GetLength() == sizeof(HeaderIe) + sizeof(kContent));
|
||||
|
||||
ie = reinterpret_cast<HeaderIe *>(buffer);
|
||||
VerifyOrQuit(ie->GetId() == kIeId1);
|
||||
VerifyOrQuit(ie->GetLength() == sizeof(kContent));
|
||||
VerifyOrQuit(ie->GetSize() == sizeof(HeaderIe) + sizeof(kContent));
|
||||
VerifyOrQuit(memcmp(ie->GetContent(), kContent, sizeof(kContent)) == 0);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Normal use: Append a new IE with empty payload (0-length IE)
|
||||
|
||||
offset = builder.GetLength();
|
||||
SuccessOrQuit(HeaderIe::StartIe(builder, kIeId2, bookmark));
|
||||
SuccessOrQuit(HeaderIe::EndIe(builder, bookmark));
|
||||
|
||||
// First IE should remain untouched
|
||||
ie = reinterpret_cast<HeaderIe *>(buffer);
|
||||
VerifyOrQuit(ie->GetId() == kIeId1);
|
||||
VerifyOrQuit(ie->GetLength() == sizeof(kContent));
|
||||
VerifyOrQuit(ie->GetSize() == sizeof(HeaderIe) + sizeof(kContent));
|
||||
VerifyOrQuit(memcmp(ie->GetContent(), kContent, sizeof(kContent)) == 0);
|
||||
|
||||
// Second IE with empty content
|
||||
ie = builder.Read<HeaderIe>(offset);
|
||||
VerifyOrQuit(ie->GetId() == kIeId2);
|
||||
VerifyOrQuit(ie->GetLength() == 0);
|
||||
VerifyOrQuit(ie->GetSize() == sizeof(HeaderIe));
|
||||
|
||||
VerifyOrQuit(builder.GetLength() == 2 * sizeof(HeaderIe) + sizeof(kContent));
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Maximum allowed IE length (127 bytes)
|
||||
|
||||
memset(largeContent, 0xaa, sizeof(largeContent));
|
||||
|
||||
builder.Init(buffer, sizeof(buffer));
|
||||
SuccessOrQuit(HeaderIe::StartIe(builder, kIeId3, bookmark));
|
||||
SuccessOrQuit(builder.AppendBytes(largeContent, HeaderIe::kMaxLength));
|
||||
SuccessOrQuit(HeaderIe::EndIe(builder, bookmark));
|
||||
|
||||
ie = builder.Read<HeaderIe>(0);
|
||||
VerifyOrQuit(ie->GetId() == kIeId3);
|
||||
VerifyOrQuit(ie->GetLength() == HeaderIe::kMaxLength);
|
||||
VerifyOrQuit(builder.GetLength() == ie->GetSize());
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Exceeding maximum length (128 bytes > 127)
|
||||
|
||||
builder.Init(buffer, sizeof(buffer));
|
||||
SuccessOrQuit(HeaderIe::StartIe(builder, kIeId3, bookmark));
|
||||
SuccessOrQuit(builder.AppendBytes(largeContent, HeaderIe::kMaxLength + 1));
|
||||
VerifyOrQuit(HeaderIe::EndIe(builder, bookmark) == kErrorInvalidArgs);
|
||||
}
|
||||
|
||||
void TestMacChannelMask(void)
|
||||
{
|
||||
uint8_t allChannels[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26};
|
||||
@@ -782,301 +864,16 @@ void TestMacFrameAckGeneration(void)
|
||||
#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
|
||||
constexpr uint16_t kMpFcfLongFrame = 1 << 3;
|
||||
constexpr uint16_t kMpFcfDstAddrShift = 4;
|
||||
constexpr uint16_t kMpFcfDstAddrNone = 0 << kMpFcfDstAddrShift;
|
||||
constexpr uint16_t kMpFcfDstAddrExt = 3 << kMpFcfDstAddrShift;
|
||||
constexpr uint16_t kMpFcfSrcAddrShift = 6;
|
||||
constexpr uint16_t kMpFcfSrcAddrShort = 2 << kMpFcfSrcAddrShift;
|
||||
constexpr uint16_t kMpFcfSrcAddrExt = 3 << kMpFcfSrcAddrShift;
|
||||
constexpr uint16_t kMpFcfPanidPresent = 1 << 8;
|
||||
constexpr uint16_t kMpFcfSecurityEnabled = 1 << 9;
|
||||
constexpr uint16_t kMpFcfSequenceSuppression = 1 << 10;
|
||||
constexpr uint16_t kMpFcfAckRequest = 1 << 14;
|
||||
constexpr uint16_t kMpFcfIePresent = 1 << 15;
|
||||
|
||||
void TestMacWakeupFrameGeneration(void)
|
||||
{
|
||||
constexpr static Mac::WakeupId kWakeupId = 0x1020;
|
||||
constexpr static uint8_t kSrcExtaddr[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
|
||||
constexpr static uint8_t kDstExtaddr[] = {0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87};
|
||||
constexpr static uint8_t kKeySource[] = {0, 0, 0, 0x1c};
|
||||
|
||||
constexpr static uint8_t kWakeupPsdu[] = {
|
||||
// Frame Control
|
||||
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
|
||||
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
|
||||
// PAN ID
|
||||
0xce, 0xfa,
|
||||
// Destination Address
|
||||
0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0,
|
||||
// Source Address
|
||||
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
|
||||
// Security Header
|
||||
Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x1c, 0x1d,
|
||||
// Rendezvous Time IE
|
||||
0x82, 0x0e, 0xcd, 0xab,
|
||||
// Connection IE
|
||||
0x05, 0x00, 0x9b, 0xb8, 0xea, 0x01, 0x1c};
|
||||
|
||||
constexpr static uint8_t kWakeupPsdu2[] = {
|
||||
// Frame Control
|
||||
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrNone | kMpFcfSrcAddrExt,
|
||||
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
|
||||
// PAN ID
|
||||
0xce, 0xfa,
|
||||
// No Destination Address
|
||||
// Source Address
|
||||
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
|
||||
// Security Header
|
||||
Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x1c, 0x1d,
|
||||
// Rendezvous Time IE
|
||||
0x82, 0x0e, 0xcd, 0xab,
|
||||
// Connection IE
|
||||
0x07, 0x00, 0x9b, 0xb8, 0xea, 0x01, 0x1c, 0x20, 0x10};
|
||||
|
||||
uint8_t psdu[OT_RADIO_FRAME_MAX_SIZE];
|
||||
Mac::Address src;
|
||||
Mac::Address dst;
|
||||
Mac::Address addr;
|
||||
Mac::WakeupId wakeupId;
|
||||
Mac::WakeupRequest wakeupRequest;
|
||||
Mac::TxFrame txFrame;
|
||||
Mac::Frame rxFrame;
|
||||
Mac::ConnectionIe *connectionIe;
|
||||
|
||||
printf("TestMacWakeupFrameGeneration\n");
|
||||
|
||||
src.SetExtended(kSrcExtaddr);
|
||||
dst.SetExtended(kDstExtaddr);
|
||||
wakeupRequest.SetExtAddress(dst.GetExtended());
|
||||
txFrame.mPsdu = psdu;
|
||||
txFrame.mLength = 0;
|
||||
txFrame.mRadioType = 0;
|
||||
|
||||
SuccessOrQuit(txFrame.GenerateWakeupFrame(0xface, wakeupRequest, src));
|
||||
|
||||
// Validate that the frame satisfies the wake-up frame definition
|
||||
VerifyOrQuit(txFrame.GetType() == Mac::Frame::kTypeMultipurpose);
|
||||
VerifyOrQuit(!txFrame.GetAckRequest());
|
||||
VerifyOrQuit(txFrame.Has<Mac::RendezvousTimeIe>());
|
||||
VerifyOrQuit(txFrame.Has<Mac::ConnectionIe>());
|
||||
VerifyOrQuit(txFrame.GetPayloadLength() == 0);
|
||||
SuccessOrQuit(txFrame.GetSrcAddr(addr));
|
||||
VerifyOrQuit(CompareAddresses(src, addr));
|
||||
SuccessOrQuit(txFrame.GetDstAddr(addr));
|
||||
VerifyOrQuit(CompareAddresses(dst, addr));
|
||||
|
||||
// Initialize remaining fields and check if the frame has the expected contents
|
||||
txFrame.SetFrameCounter(0xfcfcfcfc);
|
||||
txFrame.SetKeySource(kKeySource);
|
||||
txFrame.SetKeyId(0x1d);
|
||||
txFrame.Find<Mac::RendezvousTimeIe>()->SetRendezvousTime(0xabcd);
|
||||
connectionIe = txFrame.Find<Mac::ConnectionIe>();
|
||||
connectionIe->SetRetryInterval(1);
|
||||
connectionIe->SetRetryCount(12);
|
||||
VerifyOrQuit(connectionIe->SetWakeupId(kWakeupId) == kErrorParse);
|
||||
|
||||
VerifyOrQuit(txFrame.Find<Mac::RendezvousTimeIe>()->GetRendezvousTime() == 0xabcd);
|
||||
VerifyOrQuit(connectionIe->GetRetryInterval() == 1);
|
||||
VerifyOrQuit(connectionIe->GetRetryCount() == 12);
|
||||
VerifyOrQuit(connectionIe->GetWakeupId(wakeupId) == kErrorParse);
|
||||
VerifyOrQuit(txFrame.GetLength() == sizeof(kWakeupPsdu) + txFrame.GetFooterLength());
|
||||
VerifyOrQuit(memcmp(psdu, kWakeupPsdu, sizeof(kWakeupPsdu)) == 0);
|
||||
|
||||
// Initialize RX Frame with the same PSDU and check if it's recognized as wake-up frame
|
||||
rxFrame.mPsdu = psdu;
|
||||
rxFrame.mLength = txFrame.GetLength();
|
||||
rxFrame.mRadioType = 0;
|
||||
|
||||
SuccessOrQuit(rxFrame.ValidatePsdu());
|
||||
VerifyOrQuit(rxFrame.IsWakeupFrame());
|
||||
|
||||
// Validate the wake-up frame using the wake-up identifier.
|
||||
src.SetExtended(kSrcExtaddr);
|
||||
wakeupRequest.SetWakeupId(kWakeupId);
|
||||
txFrame.mPsdu = psdu;
|
||||
txFrame.mLength = 0;
|
||||
txFrame.mRadioType = 0;
|
||||
|
||||
SuccessOrQuit(txFrame.GenerateWakeupFrame(0xface, wakeupRequest, src));
|
||||
|
||||
// Validate that the frame satisfies the wake-up frame definition
|
||||
VerifyOrQuit(txFrame.GetType() == Mac::Frame::kTypeMultipurpose);
|
||||
VerifyOrQuit(!txFrame.GetAckRequest());
|
||||
VerifyOrQuit(txFrame.Has<Mac::RendezvousTimeIe>());
|
||||
VerifyOrQuit(txFrame.Has<Mac::ConnectionIe>());
|
||||
VerifyOrQuit(txFrame.GetPayloadLength() == 0);
|
||||
SuccessOrQuit(txFrame.GetSrcAddr(addr));
|
||||
VerifyOrQuit(CompareAddresses(src, addr));
|
||||
SuccessOrQuit(txFrame.GetDstAddr(addr));
|
||||
VerifyOrQuit(addr.IsNone());
|
||||
|
||||
// Initialize remaining fields and check if the frame has the expected contents
|
||||
txFrame.SetFrameCounter(0xfcfcfcfc);
|
||||
txFrame.SetKeySource(kKeySource);
|
||||
txFrame.SetKeyId(0x1d);
|
||||
txFrame.Find<Mac::RendezvousTimeIe>()->SetRendezvousTime(0xabcd);
|
||||
connectionIe = txFrame.Find<Mac::ConnectionIe>();
|
||||
connectionIe->SetRetryInterval(1);
|
||||
connectionIe->SetRetryCount(12);
|
||||
SuccessOrQuit(connectionIe->SetWakeupId(kWakeupId));
|
||||
|
||||
VerifyOrQuit(txFrame.Find<Mac::RendezvousTimeIe>()->GetRendezvousTime() == 0xabcd);
|
||||
VerifyOrQuit(connectionIe->GetRetryInterval() == 1);
|
||||
VerifyOrQuit(connectionIe->GetRetryCount() == 12);
|
||||
SuccessOrQuit(connectionIe->GetWakeupId(wakeupId));
|
||||
VerifyOrQuit(wakeupId == kWakeupId);
|
||||
VerifyOrQuit(wakeupRequest.GetWakeupId() == kWakeupId);
|
||||
VerifyOrQuit(txFrame.GetLength() == sizeof(kWakeupPsdu2) + txFrame.GetFooterLength());
|
||||
VerifyOrQuit(memcmp(psdu, kWakeupPsdu2, sizeof(kWakeupPsdu2)) == 0);
|
||||
|
||||
// Initialize RX Frame with the same PSDU and check if it's recognized as wake-up frame
|
||||
rxFrame.mPsdu = psdu;
|
||||
rxFrame.mLength = txFrame.GetLength();
|
||||
rxFrame.mRadioType = 0;
|
||||
|
||||
SuccessOrQuit(rxFrame.ValidatePsdu());
|
||||
VerifyOrQuit(rxFrame.IsWakeupFrame());
|
||||
}
|
||||
|
||||
void TestMacWakeupFrameDetectionNegative(void)
|
||||
{
|
||||
struct TestCase
|
||||
{
|
||||
uint8_t *mPsdu;
|
||||
uint8_t mLength;
|
||||
};
|
||||
|
||||
uint8_t ackRequestedPsdu[] = {
|
||||
// Frame Control
|
||||
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
|
||||
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfAckRequest | kMpFcfIePresent) >>
|
||||
8,
|
||||
// PAN ID
|
||||
0xCE, 0xFA,
|
||||
// Destination Address
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
// Source Address
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
// Security Header
|
||||
Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x1C, 0x1D,
|
||||
// Rendezvous Time IE
|
||||
0x82, 0x0E, 0xCD, 0xAB,
|
||||
// Connection IE
|
||||
0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x01, 0x1C,
|
||||
// Footer
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t shortAddressPsdu[] = {
|
||||
// Frame Control
|
||||
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrShort,
|
||||
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
|
||||
// PAN ID
|
||||
0xCE, 0xFA,
|
||||
// Destination Address
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
// Source Address
|
||||
0x55, 0x55,
|
||||
// Security Header
|
||||
Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x1C, 0x1D,
|
||||
// Rendezvous Time IE
|
||||
0x82, 0x0E, 0xCD, 0xAB,
|
||||
// Connection IE
|
||||
0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x01, 0x1C,
|
||||
// Footer
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t noRendezvousIePsdu[] = {
|
||||
// Frame Control
|
||||
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
|
||||
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
|
||||
// PAN ID
|
||||
0xCE, 0xFA,
|
||||
// Destination Address
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
// Source Address
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
// Security Header
|
||||
Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x1C, 0x1D,
|
||||
// Connection IE
|
||||
0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x01, 0x1C,
|
||||
// Footer
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t noConnectionIePsdu[] = {
|
||||
// Frame Control
|
||||
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
|
||||
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
|
||||
// PAN ID
|
||||
0xCE, 0xFA,
|
||||
// Destination Address
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
// Source Address
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
// Security Header
|
||||
Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x1C, 0x1D,
|
||||
// Rendezvous Time IE
|
||||
0x82, 0x0E, 0xCD, 0xAB,
|
||||
// Connection IE
|
||||
0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x02, 0x1C,
|
||||
// Footer
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t keyIdMode1Psdu[] = {
|
||||
// Frame Control
|
||||
Mac::Frame::kTypeMultipurpose | kMpFcfLongFrame | kMpFcfDstAddrExt | kMpFcfSrcAddrExt,
|
||||
(kMpFcfPanidPresent | kMpFcfSecurityEnabled | kMpFcfSequenceSuppression | kMpFcfIePresent) >> 8,
|
||||
// PAN ID
|
||||
0xCE, 0xFA,
|
||||
// Destination Address
|
||||
0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
|
||||
// Source Address
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
// Security Header
|
||||
Mac::Frame::kKeyIdMode1 | Mac::Frame::kSecurityEncMic32, 0xFC, 0xFC, 0xFC, 0xFC, 0x1D,
|
||||
// Rendezvous Time IE
|
||||
0x82, 0x0E, 0xCD, 0xAB,
|
||||
// Connection IE
|
||||
0x05, 0x00, 0x9B, 0xB8, 0xEA, 0x01, 0x1C,
|
||||
// Footer
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
const TestCase testCases[] = {
|
||||
{ackRequestedPsdu, sizeof(ackRequestedPsdu)}, {shortAddressPsdu, sizeof(shortAddressPsdu)},
|
||||
{noRendezvousIePsdu, sizeof(noRendezvousIePsdu)}, {noConnectionIePsdu, sizeof(noConnectionIePsdu)},
|
||||
{keyIdMode1Psdu, sizeof(keyIdMode1Psdu)},
|
||||
};
|
||||
|
||||
Mac::Frame rxFrame;
|
||||
|
||||
printf("TestMacWakeupFrameDetectionNegative\n");
|
||||
|
||||
for (const TestCase &testCase : testCases)
|
||||
{
|
||||
rxFrame.mPsdu = testCase.mPsdu;
|
||||
rxFrame.mLength = testCase.mLength;
|
||||
rxFrame.mRadioType = 0;
|
||||
|
||||
SuccessOrQuit(rxFrame.ValidatePsdu());
|
||||
VerifyOrQuit(!rxFrame.IsWakeupFrame());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ot::TestMacAddress();
|
||||
ot::TestMacHeader();
|
||||
ot::TestMacHeaderIeStartEnd();
|
||||
ot::TestMacChannelMask();
|
||||
ot::TestMacFrameApi();
|
||||
ot::TestMacFrameAckGeneration();
|
||||
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
|
||||
ot::TestMacWakeupFrameGeneration();
|
||||
ot::TestMacWakeupFrameDetectionNegative();
|
||||
#endif
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -457,7 +457,7 @@ OT_TOOL_WEAK otError otPlatRadioEnableCsl(otInstance *, uint32_t, otShortAddress
|
||||
|
||||
OT_TOOL_WEAK otError otPlatRadioResetCsl(otInstance *) { return OT_ERROR_NONE; }
|
||||
|
||||
OT_TOOL_WEAK void otPlatRadioUpdateCslSampleTime(otInstance *, uint32_t) {}
|
||||
OT_TOOL_WEAK void otPlatRadioUpdateCslSampleTime(otInstance *, otRadioTime32) {}
|
||||
|
||||
OT_TOOL_WEAK uint8_t otPlatRadioGetCslAccuracy(otInstance *)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user