mirror of
https://github.com/espressif/openthread.git
synced 2026-08-02 00:57:47 +00:00
[mac] skip CSMA backoff when disabled (#10838)
This commit updates SubMac to skip CSMA backoff when TX frame disables it.
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
|
||||
#include <openthread/platform/time.h>
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
#include "instance/instance.hpp"
|
||||
|
||||
namespace ot {
|
||||
@@ -798,7 +799,7 @@ bool SubMac::ShouldHandleCsmaBackOff(void) const
|
||||
{
|
||||
bool swCsma = true;
|
||||
|
||||
VerifyOrExit(!RadioSupportsCsmaBackoff(), swCsma = false);
|
||||
VerifyOrExit(mTransmitFrame.IsCsmaCaEnabled() && !RadioSupportsCsmaBackoff(), swCsma = false);
|
||||
|
||||
#if OPENTHREAD_CONFIG_LINK_RAW_ENABLE
|
||||
VerifyOrExit(Get<LinkRaw>().IsEnabled());
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <openthread/platform/radio.h>
|
||||
|
||||
#include "common/error.hpp"
|
||||
#include "gmock/gmock.h"
|
||||
#include "mac/mac_frame.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
|
||||
@@ -40,16 +41,17 @@
|
||||
|
||||
using namespace ot;
|
||||
|
||||
using ::testing::AnyNumber;
|
||||
using ::testing::Truly;
|
||||
|
||||
class MockPlatform : public FakeCoprocessorPlatform
|
||||
{
|
||||
public:
|
||||
MOCK_METHOD(otError, Transmit, (otRadioFrame * aFrame), (override));
|
||||
};
|
||||
|
||||
TEST(RadioSpinelTransmit, shouldPassDesiredTxPowerToRadioPlatform)
|
||||
{
|
||||
class MockPlatform : public FakeCoprocessorPlatform
|
||||
{
|
||||
public:
|
||||
MOCK_METHOD(otError, Transmit, (otRadioFrame * aFrame), (override));
|
||||
};
|
||||
|
||||
MockPlatform platform;
|
||||
|
||||
constexpr Mac::PanId kSrcPanId = 0x1234;
|
||||
@@ -59,7 +61,7 @@ TEST(RadioSpinelTransmit, shouldPassDesiredTxPowerToRadioPlatform)
|
||||
constexpr int8_t kTxPower = 100;
|
||||
|
||||
uint8_t frameBuffer[OT_RADIO_FRAME_MAX_SIZE];
|
||||
Mac::TxFrame txFrame;
|
||||
Mac::TxFrame txFrame{};
|
||||
|
||||
txFrame.mPsdu = frameBuffer;
|
||||
|
||||
@@ -132,3 +134,118 @@ TEST(RadioSpinelTransmit, shouldCauseSwitchingToRxChannelAfterTxDone)
|
||||
platform.GoInMs(1000);
|
||||
EXPECT_EQ(platform.GetReceiveChannel(), 25);
|
||||
}
|
||||
|
||||
TEST(RadioSpinelTransmit, shouldSkipCsmaCaWhenDisabled)
|
||||
{
|
||||
class MockPlatform : public FakeCoprocessorPlatform
|
||||
{
|
||||
public:
|
||||
MOCK_METHOD(otError, Transmit, (otRadioFrame * aFrame), (override));
|
||||
MOCK_METHOD(otError, Receive, (uint8_t aChannel), (override));
|
||||
};
|
||||
|
||||
MockPlatform platform;
|
||||
|
||||
constexpr Mac::PanId kSrcPanId = 0x1234;
|
||||
constexpr Mac::PanId kDstPanId = 0x4321;
|
||||
constexpr uint8_t kDstAddr[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
|
||||
constexpr uint16_t kSrcAddr = 0xac00;
|
||||
constexpr int8_t kTxPower = 100;
|
||||
|
||||
uint8_t frameBuffer[OT_RADIO_FRAME_MAX_SIZE];
|
||||
Mac::TxFrame txFrame{};
|
||||
|
||||
txFrame.mPsdu = frameBuffer;
|
||||
|
||||
{
|
||||
Mac::TxFrame::Info frameInfo;
|
||||
|
||||
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;
|
||||
|
||||
frameInfo.PrepareHeadersIn(txFrame);
|
||||
}
|
||||
|
||||
txFrame.mInfo.mTxInfo.mCsmaCaEnabled = false;
|
||||
txFrame.mChannel = 11;
|
||||
|
||||
EXPECT_CALL(platform, Transmit(Truly([](otRadioFrame *aFrame) -> bool {
|
||||
Mac::Frame &frame = *static_cast<Mac::Frame *>(aFrame);
|
||||
return frame.mInfo.mTxInfo.mCsmaCaEnabled == false;
|
||||
})))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(platform, Receive).Times(AnyNumber());
|
||||
// Receive(11) will be called exactly once to prepare for TX because the fake platform doesn't support sleep-to-tx
|
||||
// capability.
|
||||
EXPECT_CALL(platform, Receive(11)).Times(1);
|
||||
|
||||
ASSERT_EQ(platform.mRadioSpinel.Enable(FakePlatform::CurrentInstance()), kErrorNone);
|
||||
ASSERT_EQ(platform.mRadioSpinel.Receive(12), kErrorNone);
|
||||
ASSERT_EQ(platform.mRadioSpinel.Transmit(txFrame), kErrorNone);
|
||||
|
||||
platform.GoInMs(1000);
|
||||
}
|
||||
|
||||
TEST(RadioSpinelTransmit, shouldPerformCsmaCaWhenEnabled)
|
||||
{
|
||||
class MockPlatform : public FakeCoprocessorPlatform
|
||||
{
|
||||
public:
|
||||
MOCK_METHOD(otError, Transmit, (otRadioFrame * aFrame), (override));
|
||||
MOCK_METHOD(otError, Receive, (uint8_t aChannel), (override));
|
||||
};
|
||||
|
||||
MockPlatform platform;
|
||||
|
||||
constexpr Mac::PanId kSrcPanId = 0x1234;
|
||||
constexpr Mac::PanId kDstPanId = 0x4321;
|
||||
constexpr uint8_t kDstAddr[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
|
||||
constexpr uint16_t kSrcAddr = 0xac00;
|
||||
constexpr int8_t kTxPower = 100;
|
||||
|
||||
uint8_t frameBuffer[OT_RADIO_FRAME_MAX_SIZE];
|
||||
Mac::TxFrame txFrame{};
|
||||
|
||||
txFrame.mPsdu = frameBuffer;
|
||||
|
||||
{
|
||||
Mac::TxFrame::Info frameInfo;
|
||||
|
||||
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;
|
||||
|
||||
frameInfo.PrepareHeadersIn(txFrame);
|
||||
}
|
||||
|
||||
txFrame.mInfo.mTxInfo.mCsmaCaEnabled = true;
|
||||
txFrame.mChannel = 11;
|
||||
|
||||
EXPECT_CALL(platform, Transmit(Truly([](otRadioFrame *aFrame) -> bool {
|
||||
Mac::Frame &frame = *static_cast<Mac::Frame *>(aFrame);
|
||||
return frame.mInfo.mTxInfo.mCsmaCaEnabled == true;
|
||||
})))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(platform, Receive).Times(AnyNumber());
|
||||
// Receive(11) will be called exactly twice:
|
||||
// 1. one time to prepare for TX because the fake platform doesn't support sleep-to-tx capability.
|
||||
// 2. one time in CSMA backoff because rx-on-when-idle is true.
|
||||
EXPECT_CALL(platform, Receive(11)).Times(2);
|
||||
|
||||
ASSERT_EQ(platform.mRadioSpinel.Enable(FakePlatform::CurrentInstance()), kErrorNone);
|
||||
ASSERT_EQ(platform.mRadioSpinel.Receive(12), kErrorNone);
|
||||
ASSERT_EQ(platform.mRadioSpinel.Transmit(txFrame), kErrorNone);
|
||||
|
||||
platform.GoInMs(1000);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user