lrwpan: Fixes PHY not going to TRX_OFF after CSMA-CA failure (RxOnWhenIdel(false))

This commit is contained in:
Alberto Gallegos
2022-05-30 01:47:29 +00:00
committed by Alberto Gallegos Ramonet
parent 6db83e54bf
commit 1eabe61b56
6 changed files with 311 additions and 0 deletions

View File

@@ -31,6 +31,8 @@ Changes from ns-3.36 to ns-3.37
### Changed behavior
* Lr-wpan: **LrWpanPhy** now change to TRX_OFF after a CSMA-CA failure when the RxOnWhenIdle flag is set to false in the **LrWpanMac**.
Changes from ns-3.36 to ns-3.36.1
---------------------------------

View File

@@ -23,6 +23,7 @@ Release 3-dev
- (wifi) Fix setting of stations' max supported channel width
- (wifi) Fix setting TX power for HE TB PPDUs in case AP requested using the max TX power
- (wifi) #521 - UL OFDMA support
- (lr-wpan) #536 - Fixes PHY not going to TRX_OFF after CSMA-CA failure (RxOnWhenIdle(false))
Release 3.36.1
--------------

View File

@@ -47,4 +47,5 @@ build_lib(
test/lr-wpan-spectrum-value-helper-test.cc
test/lr-wpan-ifs-test.cc
test/lr-wpan-slotted-csmaca-test.cc
test/lr-wpan-mac-test.cc
)

View File

@@ -126,6 +126,7 @@ void
LrWpanCsmaCa::SetMacMinBE (uint8_t macMinBE)
{
NS_LOG_FUNCTION (this << macMinBE);
NS_ASSERT_MSG (macMinBE <= m_macMaxBE,"MacMinBE ("<<macMinBE<<") should be <= MacMaxBE ("<<m_macMaxBE<<")");
m_macMinBE = macMinBE;
}
@@ -140,6 +141,7 @@ void
LrWpanCsmaCa::SetMacMaxBE (uint8_t macMaxBE)
{
NS_LOG_FUNCTION (this << macMaxBE);
NS_ASSERT_MSG (macMaxBE >= 3 && macMaxBE <= 8, "MacMaxBE ("<<macMaxBE<<") should be >= 3 and <= 8");
m_macMaxBE = macMaxBE;
}
@@ -154,6 +156,7 @@ void
LrWpanCsmaCa::SetMacMaxCSMABackoffs (uint8_t macMaxCSMABackoffs)
{
NS_LOG_FUNCTION (this << macMaxCSMABackoffs);
NS_ASSERT_MSG (macMaxCSMABackoffs <= 5, "MacMaxCSMABackoffs should be <= 5");
m_macMaxCSMABackoffs = macMaxCSMABackoffs;
}

View File

@@ -1777,11 +1777,27 @@ LrWpanMac::SetLrWpanMacState (LrWpanMacState macState)
// remove the copy of the packet that was just sent
RemoveFirstTxQElement ();
ChangeMacState (MAC_IDLE);
if (m_macRxOnWhenIdle)
{
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_RX_ON);
}
else
{
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_TRX_OFF);
}
}
else if (m_lrWpanMacState == MAC_CSMA && macState == MAC_CSMA_DEFERRED)
{
ChangeMacState (MAC_IDLE);
m_txPkt = 0;
if (m_macRxOnWhenIdle)
{
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_RX_ON);
}
else
{
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_TRX_OFF);
}
NS_LOG_DEBUG ("****** PACKET DEFERRED to the next superframe *****");
}
}

View File

@@ -0,0 +1,288 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2022 Tokushima University, Japan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
*/
#include <ns3/log.h>
#include <ns3/core-module.h>
#include <ns3/lr-wpan-module.h>
#include <ns3/propagation-loss-model.h>
#include <ns3/propagation-delay-model.h>
#include <ns3/simulator.h>
#include <ns3/single-model-spectrum-channel.h>
#include <ns3/constant-position-mobility-model.h>
#include <ns3/packet.h>
#include <iostream>
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("lr-wpan-mac-test");
/**
* \ingroup lr-wpan-test
* \ingroup tests
*
* \brief Test PHY going to TRX_OFF after CSMA failure (MAC->RxOnWhenIdle(false))
*/
class TestRxOffWhenIdleAfterCsmaFailure : public TestCase
{
public:
TestRxOffWhenIdleAfterCsmaFailure ();
virtual ~TestRxOffWhenIdleAfterCsmaFailure ();
private:
/**
* Function called when a Data indication is invoked
* \param params MCPS data indication parameters
* \param p packet
*/
void DataIndication (McpsDataIndicationParams params, Ptr<Packet> p);
/**
* Function called when a Data confirm is invoked (After Tx Attempt)
* \param params MCPS data confirm parameters
*/
void DataConfirm (McpsDataConfirmParams params);
/**
* Function called when a the PHY state changes in Dev0 [00:01]
* \param context context
* \param now time at which the function is called
* \param oldState old PHY state
* \param newState new PHY state
*/
void StateChangeNotificationDev0 (std::string context, Time now, LrWpanPhyEnumeration oldState, LrWpanPhyEnumeration newState);
/**
* Function called when a the PHY state changes in Dev2 [00:03]
* \param context context
* \param now time at which the function is called
* \param oldState old PHY state
* \param newState new PHY state
*/
void StateChangeNotificationDev2 (std::string context, Time now, LrWpanPhyEnumeration oldState, LrWpanPhyEnumeration newState);
virtual void DoRun (void);
LrWpanPhyEnumeration m_dev0State; //!< Stores the PHY state of device 0 [00:01]
};
TestRxOffWhenIdleAfterCsmaFailure::TestRxOffWhenIdleAfterCsmaFailure ()
: TestCase ("Test PHY going to TRX_OFF state after CSMA failure")
{}
TestRxOffWhenIdleAfterCsmaFailure::~TestRxOffWhenIdleAfterCsmaFailure ()
{}
void
TestRxOffWhenIdleAfterCsmaFailure::DataIndication (McpsDataIndicationParams params, Ptr<Packet> p)
{
NS_LOG_DEBUG ("Received packet of size " << p->GetSize ());
}
void
TestRxOffWhenIdleAfterCsmaFailure::DataConfirm (McpsDataConfirmParams params)
{
if (params.m_status == LrWpanMcpsDataConfirmStatus::IEEE_802_15_4_SUCCESS)
{
NS_LOG_DEBUG ("LrWpanMcpsDataConfirmStatus = Success");
}
else if (params.m_status == LrWpanMcpsDataConfirmStatus::IEEE_802_15_4_CHANNEL_ACCESS_FAILURE)
{
NS_LOG_DEBUG ("LrWpanMcpsDataConfirmStatus = Channel Access Failure");
}
}
void
TestRxOffWhenIdleAfterCsmaFailure::StateChangeNotificationDev0 (std::string context, Time now, LrWpanPhyEnumeration oldState, LrWpanPhyEnumeration newState)
{
NS_LOG_DEBUG (Simulator::Now ().As (Time::S) << context << "PHY state change at " << now.As (Time::S)
<< " from " << LrWpanHelper::LrWpanPhyEnumerationPrinter (oldState)
<< " to " << LrWpanHelper::LrWpanPhyEnumerationPrinter (newState));
m_dev0State = newState;
}
void
TestRxOffWhenIdleAfterCsmaFailure::StateChangeNotificationDev2 (std::string context, Time now, LrWpanPhyEnumeration oldState, LrWpanPhyEnumeration newState)
{
NS_LOG_DEBUG (Simulator::Now ().As (Time::S) << context << "PHY state change at " << now.As (Time::S)
<< " from " << LrWpanHelper::LrWpanPhyEnumerationPrinter (oldState)
<< " to " << LrWpanHelper::LrWpanPhyEnumerationPrinter (newState));
}
void
TestRxOffWhenIdleAfterCsmaFailure::DoRun ()
{
// [00:01] [00:02] [00:03]
// Node 0------>Node1<------Node2 (interferer)
//
// Test Setup:
//
// Start the test with a transmission from node 3 to node 1,
// soon after, node 0 will attempt to transmit a packet to node 1 as well but
// it will fail because node 2 is still transmitting.
//
// The test confirms that the PHY in node 0 goes to TRX_OFF
// after its CSMA failure because its MAC has been previously
// set with flag RxOnWhenIdle (false). To ensure that node 0 CSMA
// do not attempt to do multiple backoffs delays in its CSMA,
// macMinBE and MacMaxCSMABackoffs has been set to 0.
LogComponentEnableAll (LOG_PREFIX_TIME);
LogComponentEnableAll (LOG_PREFIX_FUNC);
LogComponentEnable ("LrWpanMac", LOG_LEVEL_DEBUG);
LogComponentEnable ("LrWpanCsmaCa", LOG_LEVEL_DEBUG);
// Create 3 nodes, and a NetDevice for each one
Ptr<Node> n0 = CreateObject <Node> ();
Ptr<Node> n1 = CreateObject <Node> ();
Ptr<Node> interferenceNode = CreateObject <Node> ();
Ptr<LrWpanNetDevice> dev0 = CreateObject<LrWpanNetDevice> ();
Ptr<LrWpanNetDevice> dev1 = CreateObject<LrWpanNetDevice> ();
Ptr<LrWpanNetDevice> dev2 = CreateObject<LrWpanNetDevice> ();
dev0->SetAddress (Mac16Address ("00:01"));
dev1->SetAddress (Mac16Address ("00:02"));
dev2->SetAddress (Mac16Address ("00:03"));
// Each device must be attached to the same channel
Ptr<SingleModelSpectrumChannel> channel = CreateObject<SingleModelSpectrumChannel> ();
Ptr<LogDistancePropagationLossModel> propModel = CreateObject<LogDistancePropagationLossModel> ();
Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
channel->AddPropagationLossModel (propModel);
channel->SetPropagationDelayModel (delayModel);
dev0->SetChannel (channel);
dev1->SetChannel (channel);
dev2->SetChannel (channel);
// To complete configuration, a LrWpanNetDevice must be added to a node
n0->AddDevice (dev0);
n1->AddDevice (dev1);
interferenceNode->AddDevice (dev2);
// Trace state changes in the phy
dev0->GetPhy ()->TraceConnect ("TrxState", std::string ("[address 00:01]"),
MakeCallback (&TestRxOffWhenIdleAfterCsmaFailure::StateChangeNotificationDev0,this));
dev2->GetPhy ()->TraceConnect ("TrxState", std::string ("[address 00:03]"),
MakeCallback (&TestRxOffWhenIdleAfterCsmaFailure::StateChangeNotificationDev2,this));
Ptr<ConstantPositionMobilityModel> sender0Mobility = CreateObject<ConstantPositionMobilityModel> ();
sender0Mobility->SetPosition (Vector (0,0,0));
dev0->GetPhy ()->SetMobility (sender0Mobility);
Ptr<ConstantPositionMobilityModel> sender1Mobility = CreateObject<ConstantPositionMobilityModel> ();
sender1Mobility->SetPosition (Vector (0,1,0));
dev1->GetPhy ()->SetMobility (sender1Mobility);
Ptr<ConstantPositionMobilityModel> sender3Mobility = CreateObject<ConstantPositionMobilityModel> ();
sender3Mobility->SetPosition (Vector (0,2,0));
dev2->GetPhy ()->SetMobility (sender3Mobility);
McpsDataConfirmCallback cb0;
cb0 = MakeCallback (&TestRxOffWhenIdleAfterCsmaFailure::DataConfirm,this);
dev0->GetMac ()->SetMcpsDataConfirmCallback (cb0);
McpsDataIndicationCallback cb1;
cb1 = MakeCallback (&TestRxOffWhenIdleAfterCsmaFailure::DataIndication,this);
dev0->GetMac ()->SetMcpsDataIndicationCallback (cb1);
McpsDataConfirmCallback cb2;
cb2 = MakeCallback (&TestRxOffWhenIdleAfterCsmaFailure::DataConfirm,this);
dev1->GetMac ()->SetMcpsDataConfirmCallback (cb2);
McpsDataIndicationCallback cb3;
cb3 = MakeCallback (&TestRxOffWhenIdleAfterCsmaFailure::DataIndication,this);
dev1->GetMac ()->SetMcpsDataIndicationCallback (cb3);
dev0->GetMac ()->SetRxOnWhenIdle (false);
dev1->GetMac ()->SetRxOnWhenIdle (false);
// set CSMA min beacon exponent (BE) to 0 to make all backoff delays == to 0 secs.
dev0->GetCsmaCa ()->SetMacMinBE (0);
dev2->GetCsmaCa ()->SetMacMinBE (0);
// Only try once to do a backoff period before giving up.
dev0->GetCsmaCa ()->SetMacMaxCSMABackoffs (0);
dev2->GetCsmaCa ()->SetMacMaxCSMABackoffs (0);
// The below should trigger two callbacks when end-to-end data is working
// 1) DataConfirm callback is called
// 2) DataIndication callback is called with value of 50
Ptr<Packet> p0 = Create<Packet> (50); // 50 bytes of dummy data
McpsDataRequestParams params;
params.m_dstPanId = 0;
params.m_srcAddrMode = SHORT_ADDR;
params.m_dstAddrMode = SHORT_ADDR;
params.m_dstAddr = Mac16Address ("00:02");
params.m_msduHandle = 0;
// Send the packet that will be rejected due to channel access failure
Simulator::ScheduleWithContext (1, Seconds (0.00033),
&LrWpanMac::McpsDataRequest,
dev0->GetMac (), params, p0);
// Send interference packet
Ptr<Packet> p2 = Create<Packet> (60); // 60 bytes of dummy data
params.m_dstAddr = Mac16Address ("00:02");
Simulator::ScheduleWithContext (2, Seconds (0.0),
&LrWpanMac::McpsDataRequest,
dev2->GetMac (), params, p2);
Simulator::Run ();
NS_TEST_EXPECT_MSG_EQ (m_dev0State, LrWpanPhyEnumeration::IEEE_802_15_4_PHY_TRX_OFF,
"Error, dev0 [00:01] PHY should be in TRX_OFF after CSMA failure");
Simulator::Destroy ();
}
/**
* \ingroup lr-wpan-test
* \ingroup tests
*
* \brief LrWpan MAC TestSuite
*/
class LrWpanMacTestSuite : public TestSuite
{
public:
LrWpanMacTestSuite ();
};
LrWpanMacTestSuite::LrWpanMacTestSuite ()
: TestSuite ("lr-wpan-mac-test", UNIT)
{
AddTestCase (new TestRxOffWhenIdleAfterCsmaFailure, TestCase::QUICK);
}
static LrWpanMacTestSuite g_lrWpanMacTestSuite; //!< Static variable for test initialization