From 8652e75b0cc578b3a9567061b4d75fac0851fd03 Mon Sep 17 00:00:00 2001 From: Alberto Gallegos Ramonet Date: Tue, 9 Jun 2020 12:05:25 +0200 Subject: [PATCH] lr-wpan: (fixes !283) Beacon collisions and timings --- src/lr-wpan/examples/lr-wpan-mlme.cc | 16 +- src/lr-wpan/model/lr-wpan-csmaca.cc | 123 +++++++----- src/lr-wpan/model/lr-wpan-csmaca.h | 10 +- src/lr-wpan/model/lr-wpan-mac.cc | 272 ++++++++++++++++----------- src/lr-wpan/model/lr-wpan-mac.h | 74 ++++---- 5 files changed, 291 insertions(+), 204 deletions(-) diff --git a/src/lr-wpan/examples/lr-wpan-mlme.cc b/src/lr-wpan/examples/lr-wpan-mlme.cc index c7ad3ca65..800e8a21a 100644 --- a/src/lr-wpan/examples/lr-wpan-mlme.cc +++ b/src/lr-wpan/examples/lr-wpan-mlme.cc @@ -75,9 +75,9 @@ static void DataIndicationCoordinator (McpsDataIndicationParams params, PtrGetPhy ()->GetDataOrSymbolRate (false); + currentTime = Simulator::Now (); + symbolRate = (uint64_t) m_mac->GetPhy ()->GetDataOrSymbolRate (false); //symbols per second if (m_coorDest) { // Take the Incoming Frame Reference - elapsedSuperframe = currentTimeSymbols - m_mac->m_beaconRxTime; + elapsedSuperframe = currentTime - m_mac->m_macBeaconRxTime; + + beaconTime = Seconds ((double) m_mac->m_rxBeaconSymbols / symbolRate); + elapsedCap = elapsedSuperframe - beaconTime; + NS_LOG_DEBUG ("Elapsed incoming CAP symbols: " << (elapsedCap.GetSeconds () * symbolRate) << " (" << elapsedCap.As (Time::S) << ")"); + NS_UNUSED (beaconTime); + NS_UNUSED (elapsedCap); } else { // Take the Outgoing Frame Reference - elapsedSuperframe = currentTimeSymbols - m_mac->m_macBeaconTxTime; + elapsedSuperframe = currentTime - m_mac->m_macBeaconTxTime; } - symbolsToBoundary = m_aUnitBackoffPeriod - std::fmod (elapsedSuperframe,m_aUnitBackoffPeriod); - nextBoundary = MicroSeconds (symbolsToBoundary * 1000 * 1000 / m_mac->GetPhy ()->GetDataOrSymbolRate (false)); + // get a close value to the the boundary in symbols + elapsedSuperframeSymbols = elapsedSuperframe.GetSeconds () * symbolRate; + symbolsToBoundary = m_aUnitBackoffPeriod - std::fmod ((double) elapsedSuperframeSymbols,m_aUnitBackoffPeriod); - NS_LOG_DEBUG ("Elapsed symbols in CAP: " << elapsedSuperframe << "(" << elapsedSuperframe / m_aUnitBackoffPeriod << " backoff periods)"); - NS_LOG_DEBUG ("Next backoff period boundary in " << symbolsToBoundary << " symbols (" - << nextBoundary.GetSeconds () << " s)"); + timeAtBoundary = Seconds ((double)(elapsedSuperframeSymbols + symbolsToBoundary) / symbolRate); + // get the exact time boundary + nextBoundary = timeAtBoundary - elapsedSuperframe; + + NS_LOG_DEBUG ("Elapsed Superframe symbols: " << elapsedSuperframeSymbols << " (" + << elapsedSuperframe.As (Time::S) << ")"); + + NS_LOG_DEBUG ("Next backoff period boundary in approx. " << nextBoundary.GetSeconds () * symbolRate << " symbols (" + << nextBoundary.As (Time::S) << ")"); return nextBoundary; @@ -279,7 +298,7 @@ LrWpanCsmaCa::RandomBackoffDelay () uint64_t upperBound = (uint64_t) pow (2, m_BE) - 1; Time randomBackoff; uint64_t symbolRate; - uint32_t backoffPeriodsLeftInCap; + Time timeLeftInCap; symbolRate = (uint64_t) m_mac->GetPhy ()->GetDataOrSymbolRate (false); //symbols per second @@ -290,32 +309,37 @@ LrWpanCsmaCa::RandomBackoffDelay () m_randomBackoffPeriodsLeft = (uint64_t)m_random->GetValue (0, upperBound + 1); } - randomBackoff = MicroSeconds (m_randomBackoffPeriodsLeft * GetUnitBackoffPeriod () * 1000 * 1000 / symbolRate); + randomBackoff = Seconds ((double) (m_randomBackoffPeriodsLeft * GetUnitBackoffPeriod ()) / symbolRate); if (IsUnSlottedCsmaCa ()) { NS_LOG_DEBUG ("Unslotted CSMA-CA: requesting CCA after backoff of " << m_randomBackoffPeriodsLeft << - " periods (" << randomBackoff.GetSeconds () << " s)"); + " periods (" << randomBackoff.As (Time::S) << ")"); m_requestCcaEvent = Simulator::Schedule (randomBackoff, &LrWpanCsmaCa::RequestCCA, this); } else { - // We must make sure there are enough backoff periods left in the CAP, otherwise we continue in + // We must make sure there is enough time left in the CAP, otherwise we continue in // the CAP of the next superframe after the transmission/reception of the beacon (and the IFS) - backoffPeriodsLeftInCap = GetBackoffPeriodsLeftInCap (); + timeLeftInCap = GetTimeLeftInCap (); - NS_LOG_DEBUG ("Slotted CSMA-CA: proceeding after backoff of " << m_randomBackoffPeriodsLeft << - " periods (" << randomBackoff.GetSeconds () << " s)"); + NS_LOG_DEBUG ("Slotted CSMA-CA: proceeding after random backoff of " << m_randomBackoffPeriodsLeft << + " periods (" << (randomBackoff.GetSeconds () * symbolRate) << " symbols or " << randomBackoff.As (Time::S) << ")"); - Time rmnCapTime = MicroSeconds (backoffPeriodsLeftInCap * GetUnitBackoffPeriod () * 1000 * 1000 / symbolRate); - NS_LOG_DEBUG ("Backoff periods left in CAP: " << backoffPeriodsLeftInCap << " (" << rmnCapTime.GetSeconds () << " s)"); - if (m_randomBackoffPeriodsLeft > backoffPeriodsLeftInCap) + + + NS_LOG_DEBUG ("Backoff periods left in CAP: " << ((timeLeftInCap.GetSeconds () * symbolRate) / m_aUnitBackoffPeriod) << " (" + << (timeLeftInCap.GetSeconds () * symbolRate) << " symbols or " + << timeLeftInCap.As (Time::S) << ")"); + + + if (randomBackoff > timeLeftInCap) { - m_randomBackoffPeriodsLeft = m_randomBackoffPeriodsLeft - backoffPeriodsLeftInCap; + uint64_t usedBackoffs = (double)(timeLeftInCap.GetSeconds () * symbolRate) / m_aUnitBackoffPeriod; + m_randomBackoffPeriodsLeft -= usedBackoffs; NS_LOG_DEBUG ("No time in CAP to complete backoff delay, deferring to the next CAP"); - - m_endCapEvent = Simulator::Schedule (rmnCapTime, &LrWpanCsmaCa::DeferCsmaTimeout, this); + m_endCapEvent = Simulator::Schedule (timeLeftInCap, &LrWpanCsmaCa::DeferCsmaTimeout, this); } else { @@ -325,35 +349,38 @@ LrWpanCsmaCa::RandomBackoffDelay () } -uint32_t -LrWpanCsmaCa::GetBackoffPeriodsLeftInCap () +Time +LrWpanCsmaCa::GetTimeLeftInCap () { - uint64_t currentTimeSymbols; - uint16_t capSymbols; - uint64_t endCapSymbols; + Time currentTime; + uint64_t capSymbols; + Time endCapTime; uint64_t activeSlot; + uint64_t symbolRate; + Time rxBeaconTime; - //At this point, the currentTime should be aligned on a backoff period boundary + // At this point, the currentTime should be aligned on a backoff period boundary + currentTime = Simulator::Now (); + symbolRate = (uint64_t) m_mac->GetPhy ()->GetDataOrSymbolRate (false); //symbols per second - currentTimeSymbols = Simulator::Now ().GetMicroSeconds () * 1000 * 1000 * - m_mac->GetPhy ()->GetDataOrSymbolRate (false); - if (m_coorDest) { // Take Incoming frame reference activeSlot = m_mac->m_incomingSuperframeDuration / 16; capSymbols = activeSlot * (m_mac->m_incomingFnlCapSlot + 1); - endCapSymbols = m_mac->m_beaconRxTime + capSymbols; + endCapTime = m_mac->m_macBeaconRxTime + + Seconds ((double) capSymbols / symbolRate); } else - { // Take Outgoing frame reference + { // Take Outgoing frame reference activeSlot = m_mac->m_superframeDuration / 16; capSymbols = activeSlot * (m_mac->m_fnlCapSlot + 1); - endCapSymbols = m_mac->m_macBeaconTxTime + capSymbols; + endCapTime = m_mac->m_macBeaconTxTime + + Seconds ((double) capSymbols / symbolRate); } - return ((endCapSymbols - currentTimeSymbols) / m_aUnitBackoffPeriod); + return (endCapTime - currentTime); } @@ -362,15 +389,16 @@ LrWpanCsmaCa::CanProceed () { NS_LOG_FUNCTION (this); - uint32_t backoffPeriodsLeftInCap; + Time timeLeftInCap; uint16_t ccaSymbols; uint32_t transactionSymbols; + Time transactionTime; uint64_t symbolRate; ccaSymbols = 0; m_randomBackoffPeriodsLeft = 0; symbolRate = (uint64_t) m_mac->GetPhy ()->GetDataOrSymbolRate (false); - backoffPeriodsLeftInCap = GetBackoffPeriodsLeftInCap (); + timeLeftInCap = GetTimeLeftInCap (); // TODO: On the 950 Mhz Band (Japanese Band) @@ -410,19 +438,20 @@ LrWpanCsmaCa::CanProceed () m_lrWpanMacTransCostCallback (transactionSymbols); } - NS_LOG_DEBUG ("Total required transaction symbols: " << transactionSymbols); + transactionTime = Seconds ((double) transactionSymbols / symbolRate); + NS_LOG_DEBUG ("Total required transaction: " << transactionSymbols << " symbols (" << transactionTime.As (Time::S) << ")"); - if (transactionSymbols > (backoffPeriodsLeftInCap * GetUnitBackoffPeriod ())) + if (transactionTime > timeLeftInCap) { NS_LOG_DEBUG ("Transaction of " << transactionSymbols << " symbols " << "cannot be completed in CAP, deferring transmission to the next CAP"); - Time waitTime = MicroSeconds (backoffPeriodsLeftInCap * GetUnitBackoffPeriod () * 1000 * 10000 / symbolRate); - NS_LOG_DEBUG ("Symbols left in CAP: " << backoffPeriodsLeftInCap * GetUnitBackoffPeriod () << - " (" << waitTime.GetSeconds () << "s)"); - m_endCapEvent = Simulator::Schedule (waitTime, &LrWpanCsmaCa::DeferCsmaTimeout, this); + NS_LOG_DEBUG ("Symbols left in CAP: " << (timeLeftInCap.GetSeconds () * symbolRate) << + " (" << timeLeftInCap.As (Time::S) << ")"); + + m_endCapEvent = Simulator::Schedule (timeLeftInCap, &LrWpanCsmaCa::DeferCsmaTimeout, this); } else { diff --git a/src/lr-wpan/model/lr-wpan-csmaca.h b/src/lr-wpan/model/lr-wpan-csmaca.h index b6ba0c481..0b4a37b7d 100644 --- a/src/lr-wpan/model/lr-wpan-csmaca.h +++ b/src/lr-wpan/model/lr-wpan-csmaca.h @@ -161,8 +161,8 @@ public: */ uint64_t GetUnitBackoffPeriod (void) const; /** - * Locates the time to the next backoff period boundary and returns the - * amount of time left (in symbols). + * Locates the time to the next backoff period boundary in the SUPERFRAME + * and returns the amount of time left to this moment. * * \return time offset to the next slot */ @@ -266,10 +266,10 @@ private: virtual void DoDispose (void); /** - * \brief Get the periods left in the CAP portion of the Outgoing or Incoming frame. - * \return num of backoff periods left in the CAP + * \brief Get the time left in the CAP portion of the Outgoing or Incoming superframe. + * \return the time left in the CAP */ - uint32_t GetBackoffPeriodsLeftInCap (); + Time GetTimeLeftInCap (); /** * The callback to inform the cost of a transaction in slotted CSMA-CA. */ diff --git a/src/lr-wpan/model/lr-wpan-mac.cc b/src/lr-wpan/model/lr-wpan-mac.cc index 772ffe57d..6407cc67d 100644 --- a/src/lr-wpan/model/lr-wpan-mac.cc +++ b/src/lr-wpan/model/lr-wpan-mac.cc @@ -190,8 +190,7 @@ LrWpanMac::LrWpanMac () } LrWpanMac::~LrWpanMac () -{ -} +{} void LrWpanMac::DoInitialize () @@ -327,55 +326,55 @@ LrWpanMac::McpsDataRequest (McpsDataRequestParams params, Ptr p) } switch (params.m_srcAddrMode) { - case NO_PANID_ADDR: - macHdr.SetSrcAddrMode (params.m_srcAddrMode); - macHdr.SetNoPanIdComp (); - break; - case ADDR_MODE_RESERVED: - NS_ABORT_MSG ("Can not set source address type to ADDR_MODE_RESERVED. Aborting."); - break; - case SHORT_ADDR: - macHdr.SetSrcAddrMode (params.m_srcAddrMode); - macHdr.SetSrcAddrFields (GetPanId (), GetShortAddress ()); - break; - case EXT_ADDR: - macHdr.SetSrcAddrMode (params.m_srcAddrMode); - macHdr.SetSrcAddrFields (GetPanId (), GetExtendedAddress ()); - break; - default: - NS_LOG_ERROR (this << " Can not send packet with incorrect Source Address mode = " << params.m_srcAddrMode); - confirmParams.m_status = IEEE_802_15_4_INVALID_ADDRESS; - if (!m_mcpsDataConfirmCallback.IsNull ()) - { - m_mcpsDataConfirmCallback (confirmParams); - } - return; + case NO_PANID_ADDR: + macHdr.SetSrcAddrMode (params.m_srcAddrMode); + macHdr.SetNoPanIdComp (); + break; + case ADDR_MODE_RESERVED: + NS_ABORT_MSG ("Can not set source address type to ADDR_MODE_RESERVED. Aborting."); + break; + case SHORT_ADDR: + macHdr.SetSrcAddrMode (params.m_srcAddrMode); + macHdr.SetSrcAddrFields (GetPanId (), GetShortAddress ()); + break; + case EXT_ADDR: + macHdr.SetSrcAddrMode (params.m_srcAddrMode); + macHdr.SetSrcAddrFields (GetPanId (), GetExtendedAddress ()); + break; + default: + NS_LOG_ERROR (this << " Can not send packet with incorrect Source Address mode = " << params.m_srcAddrMode); + confirmParams.m_status = IEEE_802_15_4_INVALID_ADDRESS; + if (!m_mcpsDataConfirmCallback.IsNull ()) + { + m_mcpsDataConfirmCallback (confirmParams); + } + return; } switch (params.m_dstAddrMode) { - case NO_PANID_ADDR: - macHdr.SetDstAddrMode (params.m_dstAddrMode); - macHdr.SetNoPanIdComp (); - break; - case ADDR_MODE_RESERVED: - NS_ABORT_MSG ("Can not set destination address type to ADDR_MODE_RESERVED. Aborting."); - break; - case SHORT_ADDR: - macHdr.SetDstAddrMode (params.m_dstAddrMode); - macHdr.SetDstAddrFields (params.m_dstPanId, params.m_dstAddr); - break; - case EXT_ADDR: - macHdr.SetDstAddrMode (params.m_dstAddrMode); - macHdr.SetDstAddrFields (params.m_dstPanId, params.m_dstExtAddr); - break; - default: - NS_LOG_ERROR (this << " Can not send packet with incorrect Destination Address mode = " << params.m_dstAddrMode); - confirmParams.m_status = IEEE_802_15_4_INVALID_ADDRESS; - if (!m_mcpsDataConfirmCallback.IsNull ()) - { - m_mcpsDataConfirmCallback (confirmParams); - } - return; + case NO_PANID_ADDR: + macHdr.SetDstAddrMode (params.m_dstAddrMode); + macHdr.SetNoPanIdComp (); + break; + case ADDR_MODE_RESERVED: + NS_ABORT_MSG ("Can not set destination address type to ADDR_MODE_RESERVED. Aborting."); + break; + case SHORT_ADDR: + macHdr.SetDstAddrMode (params.m_dstAddrMode); + macHdr.SetDstAddrFields (params.m_dstPanId, params.m_dstAddr); + break; + case EXT_ADDR: + macHdr.SetDstAddrMode (params.m_dstAddrMode); + macHdr.SetDstAddrFields (params.m_dstPanId, params.m_dstExtAddr); + break; + default: + NS_LOG_ERROR (this << " Can not send packet with incorrect Destination Address mode = " << params.m_dstAddrMode); + confirmParams.m_status = IEEE_802_15_4_INVALID_ADDRESS; + if (!m_mcpsDataConfirmCallback.IsNull ()) + { + m_mcpsDataConfirmCallback (confirmParams); + } + return; } macHdr.SetSecDisable (); @@ -582,7 +581,7 @@ LrWpanMac::MlmeStartRequest (MlmeStartRequestParams params) //TODO: change the beacon sending according to the startTime parameter (if not PAN coordinator) - m_capEvent = Simulator::ScheduleNow (&LrWpanMac::StartCAP, this, SuperframeType::OUTGOING); + m_beaconEvent = Simulator::ScheduleNow (&LrWpanMac::SendOneBeacon, this); } } } @@ -594,6 +593,7 @@ LrWpanMac::MlmeSyncRequest (MlmeSyncRequestParams params) NS_LOG_FUNCTION (this); NS_ASSERT (params.m_logCh <= 26 && m_macPanId != 0xffff); + uint64_t symbolRate = (uint64_t) m_phy->GetDataOrSymbolRate (false); //symbols per second //change phy current logical channel LrWpanPhyPibAttributes pibAttr; pibAttr.phyCurrentChannel = params.m_logCh; @@ -615,7 +615,7 @@ LrWpanMac::MlmeSyncRequest (MlmeSyncRequestParams params) m_numLostBeacons = 0; //search for a beacon for a time = incomingSuperframe symbols + 960 symbols searchSymbols = ((uint64_t) 1 << m_incomingBeaconOrder) + 1 * aBaseSuperframeDuration; - searchBeaconTime = MicroSeconds (searchSymbols * 1000 * 1000 / m_phy->GetDataOrSymbolRate (false)); + searchBeaconTime = Seconds ((double) searchSymbols / symbolRate); m_beaconTrackingOn = true; m_trackingEvent = Simulator::Schedule (searchBeaconTime, &LrWpanMac::BeaconSearchTimeout, this); } @@ -698,9 +698,10 @@ LrWpanMac::SendOneBeacon () //Set the Beacon packet to be transmitted m_txPkt = beaconPacket; - //The beacon transmission time in symbols. - m_macBeaconTxTime = Simulator::Now ().GetSeconds () * m_phy->GetDataOrSymbolRate (false); + m_outSuperframeStatus = BEACON; + + NS_LOG_DEBUG ("Outgoing superframe Active Portion (Beacon + CAP + CFP): " << m_superframeDuration << " symbols"); ChangeMacState (MAC_SENDING); m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_TX_ON); @@ -712,34 +713,41 @@ void LrWpanMac::StartCAP (SuperframeType superframeType) { uint32_t activeSlot; - uint32_t capDuration; - Time capTime; + uint64_t capDuration; + Time endCapTime; + uint64_t symbolRate; + + symbolRate = (uint64_t) m_phy->GetDataOrSymbolRate (false); //symbols per second if (superframeType == OUTGOING) { m_outSuperframeStatus = CAP; activeSlot = m_superframeDuration / 16; capDuration = activeSlot * (m_fnlCapSlot + 1); - capTime = Seconds (capDuration / m_phy->GetDataOrSymbolRate (false)); - NS_LOG_DEBUG ("Outgoing superframe CAP duration " << capDuration << " symbols (" << capTime.GetSeconds () << " s)"); + endCapTime = Seconds ((double) capDuration / symbolRate); + // Obtain the end of the CAP by adjust the time it took to send the beacon + endCapTime -= (Simulator::Now () - m_macBeaconTxTime); + + NS_LOG_DEBUG ("Outgoing superframe CAP duration " << (endCapTime.GetSeconds () * symbolRate) << " symbols (" << endCapTime.As (Time::S) << ")"); NS_LOG_DEBUG ("Active Slots duration " << activeSlot << " symbols"); - m_capEvent = Simulator::Schedule (MicroSeconds (capTime.GetMicroSeconds ()), + m_capEvent = Simulator::Schedule (endCapTime, &LrWpanMac::StartCFP, this, SuperframeType::OUTGOING); - m_beaconEvent = Simulator::ScheduleNow (&LrWpanMac::SendOneBeacon, this); } else { m_incSuperframeStatus = CAP; activeSlot = m_incomingSuperframeDuration / 16; capDuration = activeSlot * (m_incomingFnlCapSlot + 1); - capTime = Seconds (capDuration / m_phy->GetDataOrSymbolRate (false)); + endCapTime = Seconds ((double) capDuration / symbolRate); + // Obtain the end of the CAP by adjust the time it took to receive the beacon + endCapTime -= (Simulator::Now () - m_macBeaconRxTime); - NS_LOG_DEBUG ("Incoming superframe CAP duration " << capDuration << " symbols (" << capTime.GetSeconds () << " s)"); + NS_LOG_DEBUG ("Incoming superframe CAP duration " << (endCapTime.GetSeconds () * symbolRate) << " symbols (" << endCapTime.As (Time::S) << ")"); NS_LOG_DEBUG ("Active Slots duration " << activeSlot << " symbols"); - m_capEvent = Simulator::Schedule (MicroSeconds (capTime.GetMicroSeconds ()), + m_capEvent = Simulator::Schedule (endCapTime, &LrWpanMac::StartCFP, this, SuperframeType::INCOMING); } @@ -752,38 +760,41 @@ void LrWpanMac::StartCFP (SuperframeType superframeType) { uint32_t activeSlot; - uint32_t cfpDuration; - Time cfpTime; + uint64_t cfpDuration; + Time endCfpTime; + uint64_t symbolRate; + + symbolRate = (uint64_t) m_phy->GetDataOrSymbolRate (false); //symbols per second if (superframeType == INCOMING) { activeSlot = m_incomingSuperframeDuration / 16; cfpDuration = activeSlot * (15 - m_incomingFnlCapSlot); - cfpTime = Seconds (cfpDuration / m_phy->GetDataOrSymbolRate (false)); + endCfpTime = Seconds ((double) cfpDuration / symbolRate); if (cfpDuration > 0) { m_incSuperframeStatus = CFP; } - NS_LOG_DEBUG ("Incoming superframe CFP duration " << cfpDuration << " symbols (" << cfpTime.GetSeconds () << " s)"); + NS_LOG_DEBUG ("Incoming superframe CFP duration " << cfpDuration << " symbols (" << endCfpTime.As (Time::S) << ")"); - m_incCfpEvent = Simulator::Schedule (MicroSeconds (cfpTime.GetMicroSeconds ()), + m_incCfpEvent = Simulator::Schedule (endCfpTime, &LrWpanMac::StartInactivePeriod, this, SuperframeType::INCOMING); } else { activeSlot = m_superframeDuration / 16; cfpDuration = activeSlot * (15 - m_fnlCapSlot); - cfpTime = Seconds (cfpDuration / m_phy->GetDataOrSymbolRate (false)); + endCfpTime = Seconds ((double) cfpDuration / symbolRate); if (cfpDuration > 0) { m_outSuperframeStatus = CFP; } - NS_LOG_DEBUG ("Outgoing superframe CFP duration " << cfpDuration << " symbols (" << cfpTime.GetSeconds () << " s)"); + NS_LOG_DEBUG ("Outgoing superframe CFP duration " << cfpDuration << " symbols (" << endCfpTime.As (Time::S) << ")"); - m_cfpEvent = Simulator::Schedule (MicroSeconds (cfpTime.GetMicroSeconds ()), + m_cfpEvent = Simulator::Schedule (endCfpTime, &LrWpanMac::StartInactivePeriod, this, SuperframeType::OUTGOING); } @@ -794,42 +805,58 @@ LrWpanMac::StartCFP (SuperframeType superframeType) void LrWpanMac::StartInactivePeriod (SuperframeType superframeType) { - uint32_t inactiveDuration; - Time inactiveTime; + uint64_t inactiveDuration; + Time endInactiveTime; + uint64_t symbolRate; + + symbolRate = (uint64_t) m_phy->GetDataOrSymbolRate (false); //symbols per second if (superframeType == INCOMING) { inactiveDuration = m_incomingBeaconInterval - m_incomingSuperframeDuration; - inactiveTime = Seconds (inactiveDuration / m_phy->GetDataOrSymbolRate (false)); + endInactiveTime = Seconds ((double) inactiveDuration / symbolRate); if (inactiveDuration > 0) { m_incSuperframeStatus = INACTIVE; } - NS_LOG_DEBUG ("Incoming superframe Inactive duration " << inactiveDuration << " symbols (" << inactiveTime.GetSeconds () << " s)"); + NS_LOG_DEBUG ("Incoming superframe Inactive Portion duration " << inactiveDuration << " symbols (" << endInactiveTime.As (Time::S) << ")"); + m_beaconEvent = Simulator::Schedule (endInactiveTime, &LrWpanMac::AwaitBeacon, this); } else { inactiveDuration = m_beaconInterval - m_superframeDuration; - inactiveTime = Seconds (inactiveDuration / m_phy->GetDataOrSymbolRate (false)); + endInactiveTime = Seconds ((double) inactiveDuration / symbolRate); if (inactiveDuration > 0) { m_outSuperframeStatus = INACTIVE; } - NS_LOG_DEBUG ("Outgoing superframe Inactive duration " << inactiveDuration << " symbols (" << inactiveTime.GetSeconds () << " s)"); - m_capEvent = Simulator::Schedule (MicroSeconds (inactiveTime.GetMicroSeconds ()), - &LrWpanMac::StartCAP, this, SuperframeType::OUTGOING); + NS_LOG_DEBUG ("Outgoing superframe Inactive Portion duration " << inactiveDuration << " symbols (" << endInactiveTime.As (Time::S) << ")"); + m_beaconEvent = Simulator::Schedule (endInactiveTime, &LrWpanMac::SendOneBeacon, this); } } +void +LrWpanMac::AwaitBeacon (void) +{ + m_incSuperframeStatus = BEACON; + //TODO: If the device waits more than the expected time to receive the beacon (wait = 46 symbols for default beacon size) + // it should continue with the start of the incoming CAP even if it did not receive the beacon. + // At the moment, the start of the incoming CAP is only triggered if the beacon is received. + // See MLME-SyncLoss for details. + + +} void LrWpanMac::BeaconSearchTimeout (void) { + uint64_t symbolRate = (uint64_t) m_phy->GetDataOrSymbolRate (false); //symbols per second + if (m_numLostBeacons > aMaxLostBeacons) { MlmeSyncLossIndicationParams syncLossParams; @@ -849,7 +876,7 @@ LrWpanMac::BeaconSearchTimeout (void) uint64_t searchSymbols; Time searchBeaconTime; searchSymbols = ((uint64_t) 1 << m_incomingBeaconOrder) + 1 * aBaseSuperframeDuration; - searchBeaconTime = MicroSeconds (searchSymbols * 1000 * 1000 / m_phy->GetDataOrSymbolRate (false)); + searchBeaconTime = Seconds ((double) searchSymbols / symbolRate); m_trackingEvent = Simulator::Schedule (searchBeaconTime, &LrWpanMac::BeaconSearchTimeout, this); } @@ -992,7 +1019,7 @@ LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr p, uint8_t lqi) // if only srcAddr field in Data or Command frame,accept frame if srcPanId=m_macPanId Ptr originalPkt = p->Copy (); // because we will strip headers - + uint64_t symbolRate = (uint64_t) m_phy->GetDataOrSymbolRate (false); //symbols per second m_promiscSnifferTrace (originalPkt); m_macPromiscRxTrace (originalPkt); @@ -1022,31 +1049,31 @@ LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr p, uint8_t lqi) params.m_srcAddrMode = receivedMacHdr.GetSrcAddrMode (); switch (params.m_srcAddrMode) { - case SHORT_ADDR: - params.m_srcAddr = receivedMacHdr.GetShortSrcAddr (); - NS_LOG_DEBUG ("Packet from " << params.m_srcAddr); - break; - case EXT_ADDR: - params.m_srcExtAddr = receivedMacHdr.GetExtSrcAddr (); - NS_LOG_DEBUG ("Packet from " << params.m_srcExtAddr); - break; - default: - break; + case SHORT_ADDR: + params.m_srcAddr = receivedMacHdr.GetShortSrcAddr (); + NS_LOG_DEBUG ("Packet from " << params.m_srcAddr); + break; + case EXT_ADDR: + params.m_srcExtAddr = receivedMacHdr.GetExtSrcAddr (); + NS_LOG_DEBUG ("Packet from " << params.m_srcExtAddr); + break; + default: + break; } params.m_dstPanId = receivedMacHdr.GetDstPanId (); params.m_dstAddrMode = receivedMacHdr.GetDstAddrMode (); switch (params.m_dstAddrMode) { - case SHORT_ADDR: - params.m_dstAddr = receivedMacHdr.GetShortDstAddr (); - NS_LOG_DEBUG ("Packet to " << params.m_dstAddr); - break; - case EXT_ADDR: - params.m_dstExtAddr = receivedMacHdr.GetExtDstAddr (); - NS_LOG_DEBUG ("Packet to " << params.m_dstExtAddr); - break; - default: - break; + case SHORT_ADDR: + params.m_dstAddr = receivedMacHdr.GetShortDstAddr (); + NS_LOG_DEBUG ("Packet to " << params.m_dstAddr); + break; + case EXT_ADDR: + params.m_dstExtAddr = receivedMacHdr.GetExtDstAddr (); + NS_LOG_DEBUG ("Packet to " << params.m_dstExtAddr); + break; + default: + break; } if (m_macPromiscuousMode) @@ -1171,13 +1198,20 @@ LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr p, uint8_t lqi) if (receivedMacHdr.IsBeacon ()) { - NS_LOG_DEBUG ("Beacon received"); - //TODO: Handle mlme-scan.request here - // The Rx time of the beacon in symbols - m_beaconRxTime = Simulator::Now ().GetSeconds () * m_phy->GetDataOrSymbolRate (false); + // The received beacon size in symbols + // Beacon = 5 bytes Sync Header (SHR) + 1 byte PHY header (PHR) + PSDU (default 17 bytes) + m_rxBeaconSymbols = m_phy->GetPhySHRDuration () + 1 * m_phy->GetPhySymbolsPerOctet () + + (originalPkt->GetSize () * m_phy->GetPhySymbolsPerOctet ()); + // The start of Rx beacon time and start of the Incoming superframe Active Period + m_macBeaconRxTime = Simulator::Now () - Seconds (double(m_rxBeaconSymbols) / symbolRate); + + NS_LOG_DEBUG ("Beacon Received (m_macBeaconRxTime: " << m_macBeaconRxTime.As (Time::S) << ")"); + + + //TODO: Handle mlme-scan.request here // Device not associated. if (m_macPanId == 0xffff) @@ -1226,6 +1260,7 @@ LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr p, uint8_t lqi) //TODO: get Incoming frame GTS Fields here + NS_LOG_DEBUG ("Incoming superframe Active Portion (Beacon + CAP + CFP): " << m_incomingSuperframeDuration << " symbols"); //Begin CAP on the current device using info from the Incoming superframe m_incCapEvent = Simulator::ScheduleNow (&LrWpanMac::StartCAP, this,SuperframeType::INCOMING); @@ -1262,7 +1297,7 @@ LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr p, uint8_t lqi) Time searchBeaconTime; searchSymbols = ((uint64_t) 1 << m_incomingBeaconOrder) + 1 * aBaseSuperframeDuration; - searchBeaconTime = MicroSeconds (searchSymbols * 1000 * 1000 / m_phy->GetDataOrSymbolRate (false)); + searchBeaconTime = Seconds ((double) searchSymbols / symbolRate); m_trackingEvent = Simulator::Schedule (searchBeaconTime, &LrWpanMac::BeaconSearchTimeout, this); } @@ -1288,7 +1323,7 @@ LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr p, uint8_t lqi) else if (receivedMacHdr.IsAcknowledgment () && m_txPkt && m_lrWpanMacState == MAC_ACK_PENDING) { LrWpanMacHeader macHdr; - Time ifsWaitTime = MicroSeconds (GetIfsSize () * 1000 * 1000 / m_phy->GetDataOrSymbolRate (false)); + Time ifsWaitTime = Seconds ((double) GetIfsSize () / symbolRate); m_txPkt->PeekHeader (macHdr); if (receivedMacHdr.GetSeqNum () == macHdr.GetSeqNum ()) { @@ -1411,7 +1446,7 @@ LrWpanMac::AckWaitTimeout (void) void LrWpanMac::IfsWaitTimeout (void) { - NS_LOG_DEBUG ("MESSAGE SENT and IFS APPLIED"); + NS_LOG_DEBUG ("IFS Completed"); m_setMacState.Cancel (); m_setMacState = Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE); } @@ -1455,6 +1490,9 @@ LrWpanMac::PdDataConfirm (LrWpanPhyEnumeration status) LrWpanMacHeader macHdr; Time ifsWaitTime; + uint64_t symbolRate; + + symbolRate = (uint64_t) m_phy->GetDataOrSymbolRate (false); //symbols per second m_txPkt->PeekHeader (macHdr); @@ -1464,9 +1502,21 @@ LrWpanMac::PdDataConfirm (LrWpanPhyEnumeration status) { if (macHdr.IsBeacon ()) { - Time ifsWaitTime = MicroSeconds (GetIfsSize () * 1000 * 1000 / m_phy->GetDataOrSymbolRate (false)); + ifsWaitTime = Seconds ((double) GetIfsSize () / symbolRate); + + // The Tx Beacon in symbols + // Beacon = 5 bytes Sync Header (SHR) + 1 byte PHY header (PHR) + PSDU (default 17 bytes) + uint64_t beaconSymbols = m_phy->GetPhySHRDuration () + 1 * m_phy->GetPhySymbolsPerOctet () + + (m_txPkt->GetSize () * m_phy->GetPhySymbolsPerOctet ()); + + // The beacon Tx time and start of the Outgoing superframe Active Period + m_macBeaconTxTime = Simulator::Now () - Seconds (double(beaconSymbols) / symbolRate); + + m_txPkt = 0; - NS_LOG_DEBUG ("Beacon Sent"); + m_capEvent = Simulator::ScheduleNow (&LrWpanMac::StartCAP, this, SuperframeType::OUTGOING); + NS_LOG_DEBUG ("Beacon Sent (m_macBeaconTxTime: " << m_macBeaconTxTime.As (Time::S) << ")"); + MlmeStartConfirmParams mlmeConfirmParams; mlmeConfirmParams.m_status = MLMESTART_SUCCESS; if (!m_mlmeStartConfirmCallback.IsNull ()) @@ -1478,7 +1528,7 @@ LrWpanMac::PdDataConfirm (LrWpanPhyEnumeration status) { // wait for the ack or the next retransmission timeout // start retransmission timer - Time waitTime = MicroSeconds (GetMacAckWaitDuration () * 1000 * 1000 / m_phy->GetDataOrSymbolRate (false)); + Time waitTime = Seconds ((double) GetMacAckWaitDuration () / symbolRate); NS_ASSERT (m_ackWaitTimeout.IsExpired ()); m_ackWaitTimeout = Simulator::Schedule (waitTime, &LrWpanMac::AckWaitTimeout, this); m_setMacState.Cancel (); @@ -1498,7 +1548,7 @@ LrWpanMac::PdDataConfirm (LrWpanPhyEnumeration status) confirmParams.m_status = IEEE_802_15_4_SUCCESS; m_mcpsDataConfirmCallback (confirmParams); } - ifsWaitTime = MicroSeconds (GetIfsSize () * 1000 * 1000 / m_phy->GetDataOrSymbolRate (false)); + ifsWaitTime = Seconds ((double) GetIfsSize () / symbolRate); RemoveFirstTxQElement (); } } @@ -1679,7 +1729,7 @@ LrWpanMac::SetLrWpanMacState (LrWpanMacState macState) { ChangeMacState (MAC_IDLE); m_txPkt = 0; - std::cout << "THIS PACKET WAS DEFERRED! macstate " << m_lrWpanMacState << "\n"; + NS_LOG_DEBUG ("****** PACKET DEFERRED to the next superframe *****"); } } diff --git a/src/lr-wpan/model/lr-wpan-mac.h b/src/lr-wpan/model/lr-wpan-mac.h index 2f467e31c..1c6f3f401 100644 --- a/src/lr-wpan/model/lr-wpan-mac.h +++ b/src/lr-wpan/model/lr-wpan-mac.h @@ -87,6 +87,7 @@ typedef enum */ typedef enum { + BEACON, //!< The Beacon transmission or reception Period CAP, //!< Contention Access Period CFP, //!< Contention Free Period INACTIVE //!< Inactive Period or unslotted CSMA-CA @@ -236,13 +237,12 @@ struct McpsDataRequestParams { McpsDataRequestParams () : m_srcAddrMode (SHORT_ADDR), - m_dstAddrMode (SHORT_ADDR), - m_dstPanId (0), - m_dstAddr (), - m_msduHandle (0), - m_txOptions (0) - { - } + m_dstAddrMode (SHORT_ADDR), + m_dstPanId (0), + m_dstAddr (), + m_msduHandle (0), + m_txOptions (0) + {} LrWpanAddressMode m_srcAddrMode; //!< Source address mode LrWpanAddressMode m_dstAddrMode; //!< Destination address mode uint16_t m_dstPanId; //!< Destination PAN identifier @@ -289,16 +289,15 @@ struct MlmeStartRequestParams { MlmeStartRequestParams () : m_PanId (0), - m_logCh (11), - m_logChPage (0), - m_startTime (0), - m_bcnOrd (15), - m_sfrmOrd (15), - m_panCoor (false), - m_battLifeExt (false), - m_coorRealgn (false) - { - } + m_logCh (11), + m_logChPage (0), + m_startTime (0), + m_bcnOrd (15), + m_sfrmOrd (15), + m_panCoor (false), + m_battLifeExt (false), + m_coorRealgn (false) + {} uint16_t m_PanId; //!< Pan Identifier used by the device. uint8_t m_logCh; //!< Logical channel on which to start using the new superframe configuration. uint32_t m_logChPage; //!< Logical channel page on which to start using the new superframe configuration. @@ -318,9 +317,8 @@ struct MlmeSyncRequestParams { MlmeSyncRequestParams () : m_logCh (), - m_trackBcn (false) - { - } + m_trackBcn (false) + {} uint8_t m_logCh; //!< The channel number on which to attempt coordinator synchronization. bool m_trackBcn; //!< True if the mlme sync with the next beacon and attempts to track future beacons. False if mlme sync only the next beacon. }; @@ -333,11 +331,10 @@ struct MlmePollRequestParams { MlmePollRequestParams () : m_coorAddrMode (SHORT_ADDR), - m_coorPanId (0), - m_coorShortAddr (), - m_coorExtAddr () - { - } + m_coorPanId (0), + m_coorShortAddr (), + m_coorExtAddr () + {} LrWpanAddressMode m_coorAddrMode; //!< The addressing mode of the coordinator to which the pool is intended. uint16_t m_coorPanId; //!< The PAN id of the coordinator to which the poll is intended. Mac16Address m_coorShortAddr; //!< Coordintator short address. @@ -731,16 +728,18 @@ public: //MAC PIB attributes /** - * The time that the device transmitted its last beacon frame, in symbol - * periods. Only 24 bits used. - * See IEEE 802.15.4-2006, section 7.4.2, Table 86. + * The time that the device transmitted its last beacon frame. + * It also indicates the start of the Active Period in the Outgoing superframe. + * See IEEE 802.15.4-2011, section 6.4.2, Table 52. */ - uint64_t m_macBeaconTxTime; + Time m_macBeaconTxTime; /** - * The time that the device received its last beacon frame, in symbol - * periods. Only 24 bits used. + * The time that the device received its last bit of the beacon frame. + * It does not indicate the start of the Active Period in the Incoming superframe. + * Not explicitly listed by the standard but its use is implied. + * Its purpose is somehow similar to m_macBeaconTxTime */ - uint64_t m_beaconRxTime; + Time m_macBeaconRxTime; /** * The short address of the coordinator through which the device is * associated. @@ -780,6 +779,11 @@ public: * See IEEE 802.15.4-2011, section 6.4.2, Table 52. */ uint16_t m_macTransactionPersistanceTime; + /** + * The total size of the received beacon in symbols. + * Its value is used to calculate the end CAP time of the incoming superframe. + */ + uint64_t m_rxBeaconSymbols; /** * Indication of the Slot where the CAP portion of the OUTGOING Superframe ends. */ @@ -966,7 +970,6 @@ public: */ typedef void (*StateTracedCallback)(LrWpanMacState oldState, LrWpanMacState newState); - protected: // Inherited from Object. virtual void DoInitialize (void); @@ -1016,6 +1019,11 @@ private: * */ void StartInactivePeriod (SuperframeType superframeType); + /** + * Called after the end of an INCOMING superframe to start the moment a + * device waits for a new incoming beacon. + */ + void AwaitBeacon (void); /** * Called if the device is unable to locate a beacon in the time set by MLME-SYNC.request. */