From d486f26151dbcddd7d059b0143585f7de51a6aad Mon Sep 17 00:00:00 2001 From: Tommaso Pecorella Date: Sun, 6 Apr 2014 23:01:10 +0200 Subject: [PATCH] Preliminary Collision tests --- src/lr-wpan/model/lr-wpan-csmaca.cc | 40 ++-- src/lr-wpan/model/lr-wpan-csmaca.h | 26 +-- src/lr-wpan/model/lr-wpan-mac.cc | 14 +- src/lr-wpan/test/lr-wpan-collision-test.cc | 222 +++++++++++++++++++++ src/lr-wpan/wscript | 1 + 5 files changed, 263 insertions(+), 40 deletions(-) create mode 100644 src/lr-wpan/test/lr-wpan-collision-test.cc diff --git a/src/lr-wpan/model/lr-wpan-csmaca.cc b/src/lr-wpan/model/lr-wpan-csmaca.cc index 626ebc2cd..d5b651e0e 100644 --- a/src/lr-wpan/model/lr-wpan-csmaca.cc +++ b/src/lr-wpan/model/lr-wpan-csmaca.cc @@ -91,84 +91,84 @@ LrWpanCsmaCa::GetMac (void) const } void -LrWpanCsmaCa::setSlottedCsmaCa (void) +LrWpanCsmaCa::SetSlottedCsmaCa (void) { NS_LOG_FUNCTION (this); m_isSlotted = true; } void -LrWpanCsmaCa::setUnSlottedCsmaCa (void) +LrWpanCsmaCa::SetUnSlottedCsmaCa (void) { NS_LOG_FUNCTION (this); m_isSlotted = false; } bool -LrWpanCsmaCa::isSlottedCsmaCa (void) const +LrWpanCsmaCa::IsSlottedCsmaCa (void) const { NS_LOG_FUNCTION (this); return (m_isSlotted); } bool -LrWpanCsmaCa::isUnSlottedCsmaCa (void) const +LrWpanCsmaCa::IsUnSlottedCsmaCa (void) const { NS_LOG_FUNCTION (this); return (!m_isSlotted); } void -LrWpanCsmaCa::setMacMinBE (uint8_t macMinBE) +LrWpanCsmaCa::SetMacMinBE (uint8_t macMinBE) { NS_LOG_FUNCTION (this << macMinBE); m_macMinBE = macMinBE; } uint8_t -LrWpanCsmaCa::getMacMinBE (void) const +LrWpanCsmaCa::GetMacMinBE (void) const { NS_LOG_FUNCTION (this); return m_macMinBE; } void -LrWpanCsmaCa::setMacMaxBE (uint8_t macMaxBE) +LrWpanCsmaCa::SetMacMaxBE (uint8_t macMaxBE) { NS_LOG_FUNCTION (this << macMaxBE); m_macMinBE = macMaxBE; } uint8_t -LrWpanCsmaCa::getMacMaxBE (void) const +LrWpanCsmaCa::GetMacMaxBE (void) const { NS_LOG_FUNCTION (this); return m_macMaxBE; } void -LrWpanCsmaCa::setmacMaxCSMABackoffs (uint8_t macMaxCSMABackoffs) +LrWpanCsmaCa::SetMacMaxCSMABackoffs (uint8_t macMaxCSMABackoffs) { NS_LOG_FUNCTION (this << macMaxCSMABackoffs); m_macMaxCSMABackoffs = macMaxCSMABackoffs; } uint8_t -LrWpanCsmaCa::getmacMaxCSMABackoffs (void) const +LrWpanCsmaCa::GetMacMaxCSMABackoffs (void) const { NS_LOG_FUNCTION (this); return m_macMaxCSMABackoffs; } void -LrWpanCsmaCa::setUnitBackoffPeriod (uint64_t unitBackoffPeriod) +LrWpanCsmaCa::SetUnitBackoffPeriod (uint64_t unitBackoffPeriod) { NS_LOG_FUNCTION (this << unitBackoffPeriod); m_aUnitBackoffPeriod = unitBackoffPeriod; } uint64_t -LrWpanCsmaCa::getUnitBackoffPeriod (void) const +LrWpanCsmaCa::GetUnitBackoffPeriod (void) const { NS_LOG_FUNCTION (this); return m_aUnitBackoffPeriod; @@ -176,7 +176,7 @@ LrWpanCsmaCa::getUnitBackoffPeriod (void) const //TODO: uint64_t -LrWpanCsmaCa::getTimeToNextSlot (void) const +LrWpanCsmaCa::GetTimeToNextSlot (void) const { NS_LOG_FUNCTION (this); uint64_t diffT = 0; @@ -192,7 +192,7 @@ LrWpanCsmaCa::Start () NS_LOG_FUNCTION (this); uint64_t backoffBoundary = 0; m_NB = 0; - if (isSlottedCsmaCa ()) + if (IsSlottedCsmaCa ()) { m_CW = 2; if (m_BLE) @@ -204,7 +204,7 @@ LrWpanCsmaCa::Start () m_BE = m_macMinBE; } //TODO: for slotted, locate backoff period boundary. i.e. delay to the next slot boundary - backoffBoundary = getTimeToNextSlot (); + backoffBoundary = GetTimeToNextSlot (); m_randomBackoffEvent = Simulator::Schedule (Seconds (backoffBoundary), &LrWpanCsmaCa::RandomBackoffDelay, this); } else @@ -248,9 +248,9 @@ LrWpanCsmaCa::RandomBackoffDelay () symbolRate = (uint64_t) m_mac->GetPhy ()->GetDataOrSymbolRate (isData); //symbols per second backoffPeriod = (uint64_t)m_random.GetValue (0, upperBound); //num backoff periods - randomBackoff = MicroSeconds (backoffPeriod * getUnitBackoffPeriod () * 1000 * 1000 / symbolRate); + randomBackoff = MicroSeconds (backoffPeriod * GetUnitBackoffPeriod () * 1000 * 1000 / symbolRate); - if (isUnSlottedCsmaCa ()) + if (IsUnSlottedCsmaCa ()) { NS_LOG_LOGIC ("Unslotted: requesting CCA after backoff of " << randomBackoff.GetMicroSeconds () << " us"); m_requestCcaEvent = Simulator::Schedule (randomBackoff, &LrWpanCsmaCa::RequestCCA, this); @@ -282,7 +282,7 @@ LrWpanCsmaCa::CanProceed () if (canProceed) { // TODO: For slotted, Perform CCA on backoff period boundary i.e. delay to next slot boundary - backoffBoundary = getTimeToNextSlot (); + backoffBoundary = GetTimeToNextSlot (); m_requestCcaEvent = Simulator::Schedule (Seconds (backoffBoundary), &LrWpanCsmaCa::RequestCCA, this); } else @@ -315,7 +315,7 @@ LrWpanCsmaCa::PlmeCcaConfirm (LrWpanPhyEnumeration status) m_ccaRequestRunning = false; if (status == IEEE_802_15_4_PHY_IDLE) { - if (isSlottedCsmaCa ()) + if (IsSlottedCsmaCa ()) { m_CW--; if (m_CW == 0) @@ -345,7 +345,7 @@ LrWpanCsmaCa::PlmeCcaConfirm (LrWpanPhyEnumeration status) } else { - if (isSlottedCsmaCa ()) + if (IsSlottedCsmaCa ()) { m_CW = 2; } diff --git a/src/lr-wpan/model/lr-wpan-csmaca.h b/src/lr-wpan/model/lr-wpan-csmaca.h index 2e6e6a382..dd908322e 100644 --- a/src/lr-wpan/model/lr-wpan-csmaca.h +++ b/src/lr-wpan/model/lr-wpan-csmaca.h @@ -50,25 +50,25 @@ public: void SetMac (Ptr mac); Ptr GetMac (void) const; - void setSlottedCsmaCa (void); - void setUnSlottedCsmaCa (void); - bool isSlottedCsmaCa (void) const; - bool isUnSlottedCsmaCa (void) const; + void SetSlottedCsmaCa (void); + void SetUnSlottedCsmaCa (void); + bool IsSlottedCsmaCa (void) const; + bool IsUnSlottedCsmaCa (void) const; - void setMacMinBE (uint8_t macMinBE); - uint8_t getMacMinBE (void) const; - void setMacMaxBE (uint8_t macMaxBE); - uint8_t getMacMaxBE (void) const; - void setmacMaxCSMABackoffs (uint8_t macMaxCSMABackoffs); - uint8_t getmacMaxCSMABackoffs (void) const; + void SetMacMinBE (uint8_t macMinBE); + uint8_t GetMacMinBE (void) const; + void SetMacMaxBE (uint8_t macMaxBE); + uint8_t GetMacMaxBE (void) const; + void SetMacMaxCSMABackoffs (uint8_t macMaxCSMABackoffs); + uint8_t GetMacMaxCSMABackoffs (void) const; - void setUnitBackoffPeriod (uint64_t unitBackoffPeriod); - uint64_t getUnitBackoffPeriod (void) const; + void SetUnitBackoffPeriod (uint64_t unitBackoffPeriod); + uint64_t GetUnitBackoffPeriod (void) const; /* * Amount of time from now to the beginning of the next slot */ - uint64_t getTimeToNextSlot (void) const; + uint64_t GetTimeToNextSlot (void) const; /* * Start CSMA-CA algorithm (step 1), initialize NB, BE for both slotted and unslotted diff --git a/src/lr-wpan/model/lr-wpan-mac.cc b/src/lr-wpan/model/lr-wpan-mac.cc index 9fc1dc3b8..76b08fa22 100644 --- a/src/lr-wpan/model/lr-wpan-mac.cc +++ b/src/lr-wpan/model/lr-wpan-mac.cc @@ -302,7 +302,7 @@ LrWpanMac::McpsDataRequest (McpsDataRequestParams params, Ptr p) } //if is Slotted CSMA means its beacon enabled - if (m_csmaCa->isSlottedCsmaCa ()) + if (m_csmaCa->IsSlottedCsmaCa ()) { if (b1 == TX_OPTION_GTS) { @@ -546,14 +546,14 @@ LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr p, uint8_t lqi) || (receivedMacHdr.GetType () == LrWpanMacHeader::LRWPAN_MAC_COMMAND)) && (receivedMacHdr.GetSrcAddrMode () > 1)) { - acceptFrame = receivedMacHdr.GetSrcPanId () == m_macPanId; //TODO need to check if PAN coord + acceptFrame = receivedMacHdr.GetSrcPanId () == m_macPanId; // \todo need to check if PAN coord } if (acceptFrame) { m_macRxTrace (originalPkt); - // TODO: What should we do if we receive a frame while waiting for an ACK? - // Especially if this frame has the ACK request bit set, should we reply with an ACK, possibly missing the pending ACK? + // \todo: What should we do if we receive a frame while waiting for an ACK? + // Especially if this frame has the ACK request bit set, should we reply with an ACK, possibly missing the pending ACK? // If the received frame is a frame with the ACK request bit set, we immediately send back an ACK. // If we are currently waiting for a pending ACK, we assume the ACK was lost and trigger a retransmission after sending the ACK. @@ -572,8 +572,8 @@ LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr p, uint8_t lqi) } else if (m_lrWpanMacState == MAC_CSMA) { - // TODO: If we receive a packet while doing CSMA/CA, should we drop the packet because of channel busy, - // or should we restart CSMA/CA for the packet after sending the ACK? + // \todo: If we receive a packet while doing CSMA/CA, should we drop the packet because of channel busy, + // or should we restart CSMA/CA for the packet after sending the ACK? // Currently we simply restart CSMA/CA after sending the ACK. m_csmaCa->Cancel (); } @@ -968,7 +968,7 @@ LrWpanMac::ChangeMacState (LrWpanMacState newState) uint64_t LrWpanMac::GetMacAckWaitDuration (void) const { - return m_csmaCa->getUnitBackoffPeriod () + m_phy->aTurnaroundTime + m_phy->GetPhySHRDuration () + return m_csmaCa->GetUnitBackoffPeriod () + m_phy->aTurnaroundTime + m_phy->GetPhySHRDuration () + ceil (6 * m_phy->GetPhySymbolsPerOctet ()); } diff --git a/src/lr-wpan/test/lr-wpan-collision-test.cc b/src/lr-wpan/test/lr-wpan-collision-test.cc new file mode 100644 index 000000000..5aca57469 --- /dev/null +++ b/src/lr-wpan/test/lr-wpan-collision-test.cc @@ -0,0 +1,222 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2014 Universita' di Firenze, Italy + * + * 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: Tommaso Pecorella + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +NS_LOG_COMPONENT_DEFINE ("lr-wpan-collision-test"); + +using namespace ns3; + +// This is an example TestCase. +class LrWpanCollisionTestCase : public TestCase +{ +public: + LrWpanCollisionTestCase (); + virtual ~LrWpanCollisionTestCase (); + + void DataIndication (McpsDataIndicationParams params, Ptr p); +private: + virtual void DoRun (void); + + uint8_t m_rxPackets; +}; + +LrWpanCollisionTestCase::LrWpanCollisionTestCase () + : TestCase ("Test the 802.15.4 collision handling") +{ + m_rxPackets = 0; +} + +LrWpanCollisionTestCase::~LrWpanCollisionTestCase () +{ +} + +void LrWpanCollisionTestCase::DataIndication (McpsDataIndicationParams params, Ptr p) +{ + m_rxPackets ++; +} + + +void +LrWpanCollisionTestCase::DoRun (void) +{ + + // Create 3 nodes, and a NetDevice for each one + Ptr n0 = CreateObject (); + Ptr n1 = CreateObject (); + Ptr n2 = CreateObject (); + + Ptr dev0 = CreateObject (); + Ptr dev1 = CreateObject (); + Ptr dev2 = CreateObject (); + + 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 channel = CreateObject (); + Ptr propModel = CreateObject (); + Ptr delayModel = CreateObject (); + 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); + n2->AddDevice (dev2); + + Ptr sender0Mobility = CreateObject (); + sender0Mobility->SetPosition (Vector (0,0,0)); + dev0->GetPhy ()->SetMobility (sender0Mobility); + n0->AggregateObject (sender0Mobility); + + Ptr sender1Mobility = CreateObject (); + // Configure position 10 m distance + sender1Mobility->SetPosition (Vector (0,10,0)); + dev1->GetPhy ()->SetMobility (sender1Mobility); + n1->AggregateObject (sender1Mobility); + + Ptr sender2Mobility = CreateObject (); + // Configure position 10 m distance + sender2Mobility->SetPosition (Vector (30,0,0)); + dev2->GetPhy ()->SetMobility (sender2Mobility); + n2->AggregateObject (sender2Mobility); + + dev0->GetMac ()->SetMcpsDataIndicationCallback (MakeCallback (&LrWpanCollisionTestCase::DataIndication, this)); + + // Disable first backoff + dev0->GetCsmaCa ()->SetMacMinBE (0); + dev1->GetCsmaCa ()->SetMacMinBE (0); + dev2->GetCsmaCa ()->SetMacMinBE (0); + + Ptr p0 = Create (50); + Ptr p1 = Create (60); + Ptr p2 = Create (120); + + McpsDataRequestParams params; + params.m_srcAddrMode = SHORT_ADDR; + params.m_dstAddrMode = SHORT_ADDR; + params.m_dstPanId = 0; + params.m_msduHandle = 0; + // params.m_txOptions = TX_OPTION_ACK; + + // First case: concurrent tx and no ACKs + m_rxPackets = 0; + params.m_dstAddr = Mac16Address ("00:02"); + Simulator::Schedule (Seconds (0.0), + &LrWpanMac::McpsDataRequest, + dev0->GetMac (), params, p0); + + params.m_dstAddr = Mac16Address ("00:01"); + Simulator::Schedule (Seconds (0.0), + &LrWpanMac::McpsDataRequest, + dev1->GetMac (), params, p1); + + Simulator::Run (); + + NS_TEST_EXPECT_MSG_EQ (m_rxPackets, 0, "Not received a packet (as expected)"); + + // Second case: concurrent tx and ACKs + m_rxPackets = 0; + params.m_txOptions = TX_OPTION_ACK; + + params.m_dstAddr = Mac16Address ("00:02"); + Simulator::Schedule (Seconds (0.0), + &LrWpanMac::McpsDataRequest, + dev0->GetMac (), params, p0); + + params.m_dstAddr = Mac16Address ("00:01"); + Simulator::Schedule (Seconds (0.0), + &LrWpanMac::McpsDataRequest, + dev1->GetMac (), params, p1); + + Simulator::Run (); + + NS_TEST_EXPECT_MSG_EQ (m_rxPackets, 1, "Received a packet (as expected)"); + + // Third case: two concurrent tx and no ACKs + m_rxPackets = 0; + params.m_txOptions = 0; + + params.m_dstAddr = Mac16Address ("00:01"); + Simulator::Schedule (Seconds (0.0), + &LrWpanMac::McpsDataRequest, + dev1->GetMac (), params, p2); + + params.m_dstAddr = Mac16Address ("00:01"); + Simulator::Schedule (Seconds (0.0), + &LrWpanMac::McpsDataRequest, + dev2->GetMac (), params, p2); + + Simulator::Run (); + + std::cout << "m_rxPackets = " << int(m_rxPackets) << std::endl; + NS_TEST_EXPECT_MSG_EQ (m_rxPackets, 0, "Received a packet (as expected)"); + + // Fourth case: two concurrent tx and ACKs + m_rxPackets = 0; + params.m_txOptions = TX_OPTION_ACK; + + params.m_dstAddr = Mac16Address ("00:01"); + Simulator::Schedule (Seconds (0.0), + &LrWpanMac::McpsDataRequest, + dev1->GetMac (), params, p0); + + params.m_dstAddr = Mac16Address ("00:01"); + Simulator::Schedule (Seconds (0.0), + &LrWpanMac::McpsDataRequest, + dev2->GetMac (), params, p1); + + Simulator::Run (); + + std::cout << "m_rxPackets = " << int(m_rxPackets) << std::endl; + NS_TEST_EXPECT_MSG_EQ (m_rxPackets, 2, "Received two packets (as expected)"); + + Simulator::Destroy (); +} + +// ============================================================================== +class LrWpanCollisionTestSuite : public TestSuite +{ +public: + LrWpanCollisionTestSuite (); +}; + +LrWpanCollisionTestSuite::LrWpanCollisionTestSuite () + : TestSuite ("lr-wpan-collision", UNIT) +{ + AddTestCase (new LrWpanCollisionTestCase, TestCase::QUICK); +} + +static LrWpanCollisionTestSuite g_lrWpanCollisionTestSuite; diff --git a/src/lr-wpan/wscript b/src/lr-wpan/wscript index 6345c6ab8..bf60150af 100644 --- a/src/lr-wpan/wscript +++ b/src/lr-wpan/wscript @@ -23,6 +23,7 @@ def build(bld): 'test/lr-wpan-packet-test.cc', 'test/lr-wpan-error-model-test.cc', 'test/lr-wpan-spectrum-value-helper-test.cc', + 'test/lr-wpan-collision-test.cc', ] headers = bld(features='ns3header')