diff --git a/src/wifi/model/dca-txop.cc b/src/wifi/model/dca-txop.cc index e82898778..5b4a2e15c 100644 --- a/src/wifi/model/dca-txop.cc +++ b/src/wifi/model/dca-txop.cc @@ -450,6 +450,14 @@ DcaTxop::NotifySleep (void) } } +void +DcaTxop::NotifyOff (void) +{ + NS_LOG_FUNCTION (this); + m_queue->Flush (); + m_currentPacket = 0; +} + void DcaTxop::NotifyWakeUp (void) { diff --git a/src/wifi/model/dca-txop.h b/src/wifi/model/dca-txop.h index 6e8d39fa5..4a1cdbb15 100644 --- a/src/wifi/model/dca-txop.h +++ b/src/wifi/model/dca-txop.h @@ -209,6 +209,10 @@ public: * it will be reinserted to the front of the queue. */ virtual void NotifySleep (void); + /** + * When sleep operation occurs, the queue gets cleaned up. + */ + virtual void NotifyOff (void); /** * When wake up operation occurs, channel access will be restarted. */ diff --git a/src/wifi/model/dcf-manager.cc b/src/wifi/model/dcf-manager.cc index ded68b7be..ef36f7c4f 100644 --- a/src/wifi/model/dcf-manager.cc +++ b/src/wifi/model/dcf-manager.cc @@ -72,6 +72,10 @@ public: { m_dcf->NotifySleepNow (); } + void NotifyOff (void) + { + m_dcf->NotifyOffNow (); + } void NotifyWakeup (void) { m_dcf->NotifyWakeupNow (); @@ -103,6 +107,7 @@ DcfManager::DcfManager () m_lastSwitchingDuration (MicroSeconds (0)), m_rxing (false), m_sleeping (false), + m_off (false), m_slotTimeUs (0), m_sifs (Seconds (0.0)), m_phyListener (0) @@ -292,8 +297,8 @@ void DcfManager::RequestAccess (Ptr state) { NS_LOG_FUNCTION (this << state); - //Deny access if in sleep mode - if (m_sleeping) + //Deny access if in sleep mode or off + if (m_sleeping || m_off) { return; } @@ -677,6 +682,25 @@ DcfManager::NotifySleepNow (void) } } +void +DcfManager::NotifyOffNow (void) +{ + NS_LOG_FUNCTION (this); + m_off = true; + //Cancel timeout + if (m_accessTimeout.IsRunning ()) + { + m_accessTimeout.Cancel (); + } + + //Reset backoffs + for (States::iterator i = m_states.begin (); i != m_states.end (); i++) + { + Ptr state = *i; + state->NotifyOff (); + } +} + void DcfManager::NotifyWakeupNow (void) { diff --git a/src/wifi/model/dcf-manager.h b/src/wifi/model/dcf-manager.h index 0b384fd5f..8079055f2 100644 --- a/src/wifi/model/dcf-manager.h +++ b/src/wifi/model/dcf-manager.h @@ -165,6 +165,10 @@ public: * Notify the DCF that the device has been put in sleep mode. */ void NotifySleepNow (void); + /** + * Notify the DCF that the device has been put in off mode. + */ + void NotifyOffNow (void); /** * Notify the DCF that the device has been resumed from sleep mode. */ @@ -344,6 +348,7 @@ private: Time m_lastSwitchingDuration; //!< the last switching duration time bool m_rxing; //!< flag whether it is in receiving state bool m_sleeping; //!< flag whether it is in sleeping state + bool m_off; //!< flag whether it is in off state Time m_eifsNoDifs; //!< EIFS no DIFS time EventId m_accessTimeout; //!< the access timeout ID uint32_t m_slotTimeUs; //!< the slot time in microseconds diff --git a/src/wifi/model/dcf-state.cc b/src/wifi/model/dcf-state.cc index f59b7e431..cfa1f23ff 100644 --- a/src/wifi/model/dcf-state.cc +++ b/src/wifi/model/dcf-state.cc @@ -234,6 +234,13 @@ DcfState::NotifySleep (void) m_txop->NotifySleep (); } +void +DcfState::NotifyOff (void) +{ + NS_LOG_FUNCTION (this); + m_txop->NotifyOff (); +} + void DcfState::NotifyWakeUp (void) { diff --git a/src/wifi/model/dcf-state.h b/src/wifi/model/dcf-state.h index 7a89418b1..c69b52033 100644 --- a/src/wifi/model/dcf-state.h +++ b/src/wifi/model/dcf-state.h @@ -193,6 +193,10 @@ protected: * Notify that the device has started to sleep. */ void NotifySleep (void); + /** + * Notify that the device has started to switch off. + */ + void NotifyOff (void); /** * Notify that the device has started to wake up */ diff --git a/src/wifi/model/mac-low.cc b/src/wifi/model/mac-low.cc index 7a6a075a8..cfe4d2226 100644 --- a/src/wifi/model/mac-low.cc +++ b/src/wifi/model/mac-low.cc @@ -78,6 +78,10 @@ public: { m_macLow->NotifySleepNow (); } + void NotifyOff (void) + { + m_macLow->NotifyOffNow (); + } void NotifyWakeup (void) { } @@ -632,6 +636,21 @@ MacLow::NotifySleepNow (void) m_currentDca = 0; } +void +MacLow::NotifyOffNow (void) +{ + NS_LOG_DEBUG ("Device is switched off. Cancelling MAC pending events"); + CancelAllEvents (); + if (m_navCounterResetCtsMissed.IsRunning ()) + { + m_navCounterResetCtsMissed.Cancel (); + } + m_lastNavStart = Simulator::Now (); + m_lastNavDuration = Seconds (0); + m_currentPacket = 0; + m_currentDca = 0; +} + void MacLow::ReceiveOk (Ptr packet, double rxSnr, WifiTxVector txVector, bool ampduSubframe) { diff --git a/src/wifi/model/mac-low.h b/src/wifi/model/mac-low.h index 0984c12af..368096468 100644 --- a/src/wifi/model/mac-low.h +++ b/src/wifi/model/mac-low.h @@ -319,6 +319,12 @@ public: * into sleep mode, pending MAC transmissions (RTS, CTS, DATA and ACK) are cancelled. */ void NotifySleepNow (void); + /** + * This method is typically invoked by the PhyMacLowListener to notify + * the MAC layer that the device has been put into off mode. When the device is put + * into off mode, pending MAC transmissions (RTS, CTS, DATA and ACK) are cancelled. + */ + void NotifyOffNow (void); /** * \param respHdr Add block ack response from originator (action * frame). diff --git a/src/wifi/model/wifi-phy-state-helper.cc b/src/wifi/model/wifi-phy-state-helper.cc index c266edcee..a64c9d778 100644 --- a/src/wifi/model/wifi-phy-state-helper.cc +++ b/src/wifi/model/wifi-phy-state-helper.cc @@ -58,6 +58,7 @@ WifiPhyStateHelper::GetTypeId (void) WifiPhyStateHelper::WifiPhyStateHelper () : m_rxing (false), m_sleeping (false), + m_isOff (false), m_endTx (Seconds (0)), m_endRx (Seconds (0)), m_endCcaBusy (Seconds (0)), @@ -142,6 +143,12 @@ WifiPhyStateHelper::IsStateSleep (void) const return (GetState () == WifiPhy::SLEEP); } +bool +WifiPhyStateHelper::IsStateOff (void) const +{ + return (GetState () == WifiPhy::OFF); +} + Time WifiPhyStateHelper::GetStateDuration (void) const { @@ -174,6 +181,10 @@ WifiPhyStateHelper::GetDelayUntilIdle (void) const NS_FATAL_ERROR ("Cannot determine when the device will wake up."); retval = Seconds (0); break; + case WifiPhy::OFF: + NS_FATAL_ERROR ("Cannot determine when the device will be switched on."); + retval = Seconds (0); + break; default: NS_FATAL_ERROR ("Invalid WifiPhy state."); retval = Seconds (0); @@ -192,6 +203,10 @@ WifiPhyStateHelper::GetLastRxStartTime (void) const WifiPhy::State WifiPhyStateHelper::GetState (void) const { + if (m_isOff) + { + return WifiPhy::OFF; + } if (m_sleeping) { return WifiPhy::SLEEP; @@ -288,6 +303,16 @@ WifiPhyStateHelper::NotifySleep (void) } } +void +WifiPhyStateHelper::NotifyOff (void) +{ + NS_LOG_FUNCTION (this); + for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) + { + (*i)->NotifyOff (); + } +} + void WifiPhyStateHelper::NotifyWakeup (void) { @@ -551,4 +576,46 @@ WifiPhyStateHelper::SwitchFromRxAbort (void) NS_ASSERT (!IsStateRx ()); } +void +WifiPhyStateHelper::SwitchToOff (void) +{ + NS_LOG_FUNCTION (this); + Time now = Simulator::Now (); + switch (GetState ()) + { + case WifiPhy::RX: + /* The packet which is being received as well + * as its endRx event are cancelled by the caller. + */ + m_rxing = false; + m_stateLogger (m_startRx, now - m_startRx, WifiPhy::RX); + m_endRx = now; + break; + case WifiPhy::TX: + /* The packet which is being transmitted as well + * as its endTx event are cancelled by the caller. + */ + m_stateLogger (m_startTx, now - m_startTx, WifiPhy::TX); + m_endTx = now; + break; + case WifiPhy::IDLE: + LogPreviousIdleAndCcaBusyStates (); + break; + case WifiPhy::CCA_BUSY: + { + Time ccaStart = Max (m_endRx, m_endTx); + ccaStart = Max (ccaStart, m_startCcaBusy); + ccaStart = Max (ccaStart, m_endSwitching); + m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY); + } break; + default: + NS_FATAL_ERROR ("Invalid WifiPhy state."); + break; + } + m_previousStateChangeTime = now; + m_isOff = true; + NotifyOff (); + NS_ASSERT (IsStateOff ()); +} + } //namespace ns3 diff --git a/src/wifi/model/wifi-phy-state-helper.h b/src/wifi/model/wifi-phy-state-helper.h index 0faadf8fd..fc3f547f7 100644 --- a/src/wifi/model/wifi-phy-state-helper.h +++ b/src/wifi/model/wifi-phy-state-helper.h @@ -114,6 +114,12 @@ public: * \return true if the current state is SLEEP, false otherwise */ bool IsStateSleep (void) const; + /** + * Check whether the current state is OFF. + * + * \return true if the current state is OFF, false otherwise + */ + bool IsStateOff (void) const; /** * Return the elapsed time of the current state. * @@ -189,6 +195,10 @@ public: * Abort current reception */ void SwitchFromRxAbort (void); + /** + * Switch to off mode. + */ + void SwitchToOff (void); /** * TracedCallback signature for state changes. @@ -283,6 +293,10 @@ private: * Notify all WifiPhyListener that we are going to sleep */ void NotifySleep (void); + /** + * Notify all WifiPhyListener that we are going to switch off + */ + void NotifyOff (void); /** * Notify all WifiPhyListener that we woke up */ @@ -299,6 +313,7 @@ private: bool m_rxing; ///< receiving bool m_sleeping; ///< sleeping + bool m_isOff; ///< switched off Time m_endTx; ///< end transmit Time m_endRx; ///< end receive Time m_endCcaBusy; ///< endn CCA busy diff --git a/src/wifi/model/wifi-phy.h b/src/wifi/model/wifi-phy.h index 9fbc326cd..14ac22c57 100644 --- a/src/wifi/model/wifi-phy.h +++ b/src/wifi/model/wifi-phy.h @@ -149,6 +149,10 @@ public: * Notify listeners that we went to sleep */ virtual void NotifySleep (void) = 0; + /** + * Notify listeners that we went to switch off + */ + virtual void NotifyOff (void) = 0; /** * Notify listeners that we woke up */ diff --git a/src/wifi/model/wifi-radio-energy-model.cc b/src/wifi/model/wifi-radio-energy-model.cc index f4fa356ee..aa1e372f3 100644 --- a/src/wifi/model/wifi-radio-energy-model.cc +++ b/src/wifi/model/wifi-radio-energy-model.cc @@ -555,9 +555,17 @@ WifiRadioEnergyModelPhyListener::NotifyWakeup(void) m_changeStateCallback (WifiPhy::IDLE); } -/* - * Private function state here. - */ +void +WifiRadioEnergyModelPhyListener::NotifyOff (void) +{ + NS_LOG_FUNCTION (this); + if (m_changeStateCallback.IsNull ()) + { + NS_FATAL_ERROR ("WifiRadioEnergyModelPhyListener:Change state callback not set!"); + } + m_changeStateCallback (WifiPhy::OFF); + m_switchToIdleEvent.Cancel (); +} void WifiRadioEnergyModelPhyListener::SwitchToIdle (void) diff --git a/src/wifi/model/wifi-radio-energy-model.h b/src/wifi/model/wifi-radio-energy-model.h index eee9ba7bf..9e808b5e4 100644 --- a/src/wifi/model/wifi-radio-energy-model.h +++ b/src/wifi/model/wifi-radio-energy-model.h @@ -120,6 +120,11 @@ public: */ void NotifySleep (void); + /** + * Defined in ns3::WifiPhyListener + */ + void NotifyOff (void); + /** * Defined in ns3::WifiPhyListener */ diff --git a/src/wifi/test/spectrum-wifi-phy-test.cc b/src/wifi/test/spectrum-wifi-phy-test.cc index 619f55ae6..89ac27759 100644 --- a/src/wifi/test/spectrum-wifi-phy-test.cc +++ b/src/wifi/test/spectrum-wifi-phy-test.cc @@ -230,6 +230,9 @@ public: virtual void NotifySleep (void) { } + virtual void NotifyOff (void) + { + } virtual void NotifyWakeup (void) { }