# HG changeset patch # User Mathieu Lacage # Date 1195487644 -3600 # Node ID b6243a53c93f1be5384bd53e29c1acce9f79f905 # Parent 40ad60ac99120a5653ffe69ae2706143aeb5d5de# Parent 3eeabad35e98a9ec6ddd56ae71eaeabcafec1be4 merge with HEAD diff -r 3eeabad35e98 -r b6243a53c93f src/devices/wifi/dca-txop.cc --- a/src/devices/wifi/dca-txop.cc Sat Nov 17 18:58:47 2007 +0100 +++ b/src/devices/wifi/dca-txop.cc Mon Nov 19 16:54:04 2007 +0100 @@ -21,84 +21,45 @@ #include "ns3/assert.h" #include "ns3/packet.h" #include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/net-device.h" +#include "ns3/node.h" #include "dca-txop.h" -#include "dcf.h" +#include "dcf-manager.h" #include "mac-parameters.h" #include "mac-low.h" #include "wifi-mac-queue.h" #include "mac-tx-middle.h" #include "wifi-phy.h" +#include "random-stream.h" NS_LOG_COMPONENT_DEFINE ("DcaTxop"); +#define MY_DEBUG(x) \ + NS_LOG_DEBUG (Simulator::Now () << " " << m_low->GetDevice ()->GetNode ()->GetId () << ":" << \ + m_low->GetDevice ()->GetIfIndex () << " " << x) + namespace ns3 { -class DcaTxop::NavListener : public ns3::MacLowNavListener { +class DcaTxop::Dcf : public DcfState +{ public: - NavListener (ns3::Dcf *dcf) - : m_dcf (dcf) {} - virtual ~NavListener () {} - virtual void NavStart (Time now, Time duration) { - m_dcf->NotifyNavStart (now, duration); - } - virtual void NavContinue (Time now, Time duration) { - m_dcf->NotifyNavContinue (now, duration); - } - virtual void NavReset (Time now, Time duration) { - m_dcf->NotifyNavReset (now, duration); - } + Dcf (DcaTxop *txop) + : m_txop (txop) + {} private: - ns3::Dcf *m_dcf; -}; -class DcaTxop::PhyListener : public ns3::WifiPhyListener { -public: - PhyListener (ns3::Dcf *dcf) - : m_dcf (dcf) {} - virtual ~PhyListener () {} - virtual void NotifyRxStart (Time duration) { - m_dcf->NotifyRxStartNow (duration); - } - virtual void NotifyRxEndOk (void) { - m_dcf->NotifyRxEndOkNow (); - } - virtual void NotifyRxEndError (void) { - m_dcf->NotifyRxEndErrorNow (); + virtual void DoNotifyAccessGranted (void) { + m_txop->NotifyAccessGranted (); } - virtual void NotifyTxStart (Time duration) { - m_dcf->NotifyTxStartNow (duration); - } - virtual void NotifyCcaBusyStart (Time duration) { - m_dcf->NotifyCcaBusyStartNow (duration); + virtual void DoNotifyInternalCollision (void) { + m_txop->NotifyInternalCollision (); } -private: - ns3::Dcf *m_dcf; -}; - - -class DcaTxop::AccessListener : public DcfAccessListener { -public: - AccessListener (DcaTxop *txop) - : DcfAccessListener (), - m_txop (txop) {} - - virtual ~AccessListener () {} - - virtual void AccessGrantedNow (void) - { - m_txop->AccessGrantedNow (); - } - virtual bool AccessNeeded (void) - { - return m_txop->AccessNeeded (); - } - virtual bool AccessingAndWillNotify (void) - { - return m_txop->AccessingAndWillNotify (); + virtual void DoNotifyCollision (void) { + m_txop->NotifyCollision (); } -private: DcaTxop *m_txop; }; @@ -133,31 +94,28 @@ DcaTxop *m_txop; }; -DcaTxop::DcaTxop (uint32_t minCw, uint32_t maxCw) - : m_accessListener (0), +DcaTxop::DcaTxop (uint32_t minCw, uint32_t maxCw, uint32_t aifsn, DcfManager *manager) + : m_manager (manager), m_hasCurrent (false), m_ssrc (0), m_slrc (0) + { m_transmissionListener = new DcaTxop::TransmissionListener (this); - m_dcf = new Dcf (minCw, maxCw); - m_accessListener = new DcaTxop::AccessListener (this); - m_dcf->RegisterAccessListener (m_accessListener); + m_dcf = new DcaTxop::Dcf (this); + m_dcf->SetCwBounds (minCw, maxCw); + m_dcf->SetAifsn (aifsn); + m_manager->Add (m_dcf); m_queue = new WifiMacQueue (); + m_rng = new RealRandomStream (); } DcaTxop::~DcaTxop () { - delete m_accessListener; delete m_transmissionListener; - delete m_navListener; - delete m_phyListener; delete m_queue; delete m_dcf; - m_accessListener = 0; m_transmissionListener = 0; - m_navListener = 0; - m_phyListener = 0; m_queue = 0; m_dcf = 0; } @@ -166,20 +124,11 @@ DcaTxop::SetLow (MacLow *low) { m_low = low; - m_navListener = new DcaTxop::NavListener (m_dcf); - m_low->RegisterNavListener (m_navListener); -} -void -DcaTxop::SetPhy (Ptr phy) -{ - m_phyListener = new DcaTxop::PhyListener (m_dcf); - phy->RegisterListener (m_phyListener); } void DcaTxop::SetParameters (MacParameters *parameters) { m_parameters = parameters; - m_dcf->SetParameters (parameters); } void DcaTxop::SetTxMiddle (MacTxMiddle *txMiddle) @@ -198,21 +147,6 @@ } void -DcaTxop::SetDifs (Time difs) -{ - m_dcf->SetDifs (difs); -} -void -DcaTxop::SetEifs (Time eifs) -{ - m_dcf->SetEifs (eifs); -} -void -DcaTxop::SetCwBounds (uint32_t min, uint32_t max) -{ - m_dcf->SetCwBounds (min, max); -} -void DcaTxop::SetMaxQueueSize (uint32_t size) { m_queue->SetMaxSize (size); @@ -227,7 +161,29 @@ DcaTxop::Queue (Packet packet, WifiMacHeader const &hdr) { m_queue->Enqueue (packet, hdr); - m_dcf->RequestAccess (); + StartAccessIfNeeded (); +} + +void +DcaTxop::RestartAccessIfNeeded (void) +{ + if ((m_hasCurrent || + !m_queue->IsEmpty ()) && + !m_dcf->IsAccessRequested ()) + { + m_manager->RequestAccess (m_dcf); + } +} + +void +DcaTxop::StartAccessIfNeeded (void) +{ + if (!m_hasCurrent && + !m_queue->IsEmpty () && + !m_dcf->IsAccessRequested ()) + { + m_manager->RequestAccess (m_dcf); + } } @@ -350,42 +306,18 @@ } bool -DcaTxop::AccessingAndWillNotify (void) -{ - if (m_hasCurrent) - { - return true; - } - else - { - return false; - } -} - -bool -DcaTxop::AccessNeeded (void) +DcaTxop::NeedsAccess (void) const { - if (!m_queue->IsEmpty () || - m_hasCurrent) - { - NS_LOG_DEBUG ("access needed here"); - return true; - } - else - { - NS_LOG_DEBUG ("no access needed here"); - return false; - } + return !m_queue->IsEmpty () || m_hasCurrent; } - -void -DcaTxop::AccessGrantedNow (void) +void +DcaTxop::NotifyAccessGranted (void) { if (!m_hasCurrent) { if (m_queue->IsEmpty ()) { - NS_LOG_DEBUG ("queue empty"); + MY_DEBUG ("queue empty"); return; } bool found; @@ -400,7 +332,7 @@ m_ssrc = 0; m_slrc = 0; m_fragmentNumber = 0; - NS_LOG_DEBUG ("dequeued size="<StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); + MY_DEBUG ("tx broadcast"); } else { @@ -431,12 +363,12 @@ Packet fragment = GetFragmentPacket (&hdr); if (IsLastFragment ()) { - NS_LOG_DEBUG ("fragmenting last fragment size="<StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); + RestartAccessIfNeeded (); +} void DcaTxop::GotCts (double snr, WifiMode txMode) { - NS_LOG_DEBUG ("got cts"); + MY_DEBUG ("got cts"); m_ssrc = 0; } void DcaTxop::MissedCts (void) { - NS_LOG_DEBUG ("missed cts"); + MY_DEBUG ("missed cts"); m_ssrc++; m_ctstimeoutTrace (m_ssrc); if (m_ssrc > Parameters ()->GetMaxSsrc ()) { // to reset the dcf. + m_hasCurrent = false; m_dcf->ResetCw (); - m_dcf->StartBackoff (); - m_hasCurrent = false; } else { m_dcf->UpdateFailedCw (); - m_dcf->StartBackoff (); } + m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); + RestartAccessIfNeeded (); } void DcaTxop::GotAck (double snr, WifiMode txMode) @@ -501,7 +445,7 @@ if (!NeedFragmentation () || IsLastFragment ()) { - NS_LOG_DEBUG ("got ack. tx done."); + MY_DEBUG ("got ack. tx done."); if (!m_txOkCallback.IsNull ()) { m_txOkCallback (m_currentHdr); @@ -512,25 +456,25 @@ */ m_hasCurrent = false; m_dcf->ResetCw (); - m_dcf->StartBackoff (); + m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); + RestartAccessIfNeeded (); } else { - NS_LOG_DEBUG ("got ack. tx not done, size="< Parameters ()->GetMaxSlrc ()) { // to reset the dcf. + m_hasCurrent = false; m_dcf->ResetCw (); - m_dcf->StartBackoff (); - m_hasCurrent = false; } else { @@ -540,14 +484,14 @@ m_txFailedCallback (m_currentHdr); } m_dcf->UpdateFailedCw (); - m_dcf->StartBackoff (); } - + m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); + RestartAccessIfNeeded (); } void DcaTxop::StartNext (void) { - NS_LOG_DEBUG ("start next packet fragment"); + MY_DEBUG ("start next packet fragment"); /* this callback is used only for fragments. */ NextFragment (); WifiMacHeader hdr; @@ -570,7 +514,7 @@ void DcaTxop::Cancel (void) { - NS_LOG_DEBUG ("transmission cancelled"); + MY_DEBUG ("transmission cancelled"); /** * This happens in only one case: in an AP, you have two DcaTxop: * - one is used exclusively for beacons and has a high priority. @@ -582,7 +526,7 @@ * queue gets a tx oportunity during this backoff, it will trigger * a call to this Cancel function. * - * Since we are already doing a backoff, so we will get access to + * Since we are already doing a backoff, we will get access to * the medium when we can, we have nothing to do here. We just * ignore the cancel event and wait until we are given again a * tx oportunity. diff -r 3eeabad35e98 -r b6243a53c93f src/devices/wifi/dca-txop.h --- a/src/devices/wifi/dca-txop.h Sat Nov 17 18:58:47 2007 +0100 +++ b/src/devices/wifi/dca-txop.h Mon Nov 19 16:54:04 2007 +0100 @@ -31,18 +31,19 @@ namespace ns3 { -class Dcf; +class DcfState; +class DcfManager; class WifiMacQueue; class MacLow; -class WifiPhy; class MacParameters; class MacTxMiddle; +class RandomStream; /** * \brief handle packet fragmentation and retransmissions. * * This class implements the packet fragmentation and - * retransmission policy. It uses the ns3::MacLow and ns3::Dcf + * retransmission policy. It uses the ns3::MacLow and ns3::DcfManager * helper classes to respectively send packets and decide when * to send them. Packets are stored in a ns3::WifiMacQueue until * they can be sent. @@ -65,17 +66,19 @@ typedef Callback TxFailed; /** - * \param minCw forwarded to ns3::Dcf constructor - * \param maxCw forwarded to ns3::Dcf constructor + * \param minCw forwarded to ns3::DcfState constructor + * \param maxCw forwarded to ns3::DcfState constructor + * \param aifsn forwarded to ns3::DcfState constructor + * \param manager the manager which will be responsible + * for controlling access to this DcaTxop. * * Initialized from \valueref{WifiMaxSsrc}, \valueref{WifiMaxSlrc}, * \valueref{WifiRtsCtsThreshold}, and, \valueref{WifiFragmentationThreshold}. */ - DcaTxop (uint32_t minCw, uint32_t maxCw); + DcaTxop (uint32_t cwMin, uint32_t cwMax, uint32_t aifsn, DcfManager *manager); ~DcaTxop (); void SetLow (MacLow *low); - void SetPhy (Ptr phy); void SetParameters (MacParameters *parameters); void SetTxMiddle (MacTxMiddle *txMiddle); /** @@ -89,9 +92,6 @@ */ void SetTxFailedCallback (TxFailed callback); - void SetDifs (Time difs); - void SetEifs (Time eifs); - void SetCwBounds (uint32_t min, uint32_t max); void SetMaxQueueSize (uint32_t size); void SetMaxQueueDelay (Time delay); @@ -103,21 +103,24 @@ * can be sent safely. */ void Queue (Packet packet, WifiMacHeader const &hdr); + private: - class AccessListener; class TransmissionListener; class NavListener; class PhyListener; - friend class AccessListener; + class Dcf; + friend class Dcf; friend class TransmissionListener; MacLow *Low (void); MacParameters *Parameters (void); + /* dcf notifications forwarded here */ + bool NeedsAccess (void) const; + void NotifyAccessGranted (void); + void NotifyInternalCollision (void); + void NotifyCollision (void); /* event handlers */ - void AccessGrantedNow (void); - bool AccessingAndWillNotify (void); - bool AccessNeeded (void); void GotCts (double snr, WifiMode txMode); void MissedCts (void); void GotAck (double snr, WifiMode txMode); @@ -125,6 +128,8 @@ void StartNext (void); void Cancel (void); + void RestartAccessIfNeeded (void); + void StartAccessIfNeeded (void); bool NeedRts (void); bool NeedFragmentation (void); uint32_t GetNFragments (void); @@ -136,6 +141,7 @@ Packet GetFragmentPacket (WifiMacHeader *hdr); Dcf *m_dcf; + DcfManager *m_manager; TxOk m_txOkCallback; TxFailed m_txFailedCallback; WifiMacQueue *m_queue; @@ -143,11 +149,10 @@ MacLow *m_low; MacParameters *m_parameters; TransmissionListener *m_transmissionListener; - AccessListener *m_accessListener; - NavListener *m_navListener; - PhyListener *m_phyListener; + RandomStream *m_rng; + bool m_accessOngoing; Packet m_currentPacket; bool m_hasCurrent; WifiMacHeader m_currentHdr; diff -r 3eeabad35e98 -r b6243a53c93f src/devices/wifi/dcf-manager-test.cc --- a/src/devices/wifi/dcf-manager-test.cc Sat Nov 17 18:58:47 2007 +0100 +++ b/src/devices/wifi/dcf-manager-test.cc Mon Nov 19 16:54:04 2007 +0100 @@ -18,10 +18,9 @@ void QueueTx (uint64_t txTime, uint64_t expectedGrantTime); private: friend class DcfManagerTest; - virtual bool NeedsAccess (void) const; - virtual void NotifyAccessGranted (void); - virtual void NotifyInternalCollision (void); - virtual void NotifyCollision (void); + virtual void DoNotifyAccessGranted (void); + virtual void DoNotifyInternalCollision (void); + virtual void DoNotifyCollision (void); typedef std::pair ExpectedGrant; typedef std::list ExpectedGrants; @@ -83,23 +82,18 @@ { m_expectedGrants.push_back (std::make_pair (txTime, expectedGrantTime)); } -bool -DcfStateTest::NeedsAccess (void) const -{ - return !m_expectedGrants.empty (); -} void -DcfStateTest::NotifyAccessGranted (void) +DcfStateTest::DoNotifyAccessGranted (void) { m_test->NotifyAccessGranted (m_i); } void -DcfStateTest::NotifyInternalCollision (void) +DcfStateTest::DoNotifyInternalCollision (void) { m_test->NotifyInternalCollision (m_i); } void -DcfStateTest::NotifyCollision (void) +DcfStateTest::DoNotifyCollision (void) { m_test->NotifyCollision (m_i); } @@ -411,6 +405,22 @@ AddAccessRequest (30, 10, 91, 0); ExpectCollision (30, 2, 0); // backoff: 2 slot EndTest (); + + + StartTest (4, 6, 10); + AddDcfState (2); + AddRxOkEvt (20, 40); + AddAccessRequest (80, 10, 80, 0); + EndTest (); + + + StartTest (4, 6, 10); + AddDcfState (2); + AddRxOkEvt (20, 40); + AddRxOkEvt (78, 8); + AddAccessRequest (30, 50, 108, 0); + ExpectCollision (30, 3, 0); // backoff: 3 slots + EndTest (); return m_result; diff -r 3eeabad35e98 -r b6243a53c93f src/devices/wifi/dcf-manager.cc --- a/src/devices/wifi/dcf-manager.cc Sat Nov 17 18:58:47 2007 +0100 +++ b/src/devices/wifi/dcf-manager.cc Mon Nov 19 16:54:04 2007 +0100 @@ -11,7 +11,7 @@ NS_LOG_COMPONENT_DEFINE ("DcfManager"); #define MY_DEBUG(x) \ - NS_LOG_DEBUG (Simulator::Now () << " " x) + NS_LOG_DEBUG (Simulator::Now () << " " << this << " " << x) namespace ns3 { @@ -21,7 +21,8 @@ DcfState::DcfState () : m_backoffSlots (0), - m_backoffStart (Seconds (0.0)) + m_backoffStart (Seconds (0.0)), + m_accessRequested (false) {} DcfState::~DcfState () @@ -57,9 +58,9 @@ void DcfState::UpdateBackoffSlotsNow (uint32_t nSlots, Time backoffUpdateBound) { - uint32_t n = std::min (nSlots, m_backoffSlots); - m_backoffSlots -= n; + m_backoffSlots -= nSlots; m_backoffStart = backoffUpdateBound; + MY_DEBUG ("update slots="< - */ - -#include - -#include "ns3/simulator.h" -#include "ns3/assert.h" -#include "ns3/log.h" - -#include "dcf.h" -#include "random-stream.h" -#include "mac-parameters.h" - - -NS_LOG_COMPONENT_DEFINE ("Dcf"); - -namespace ns3 { - - - - -DcfAccessListener::DcfAccessListener () -{} -DcfAccessListener::~DcfAccessListener () -{} - - - -Dcf::Dcf (uint32_t min, uint32_t max) - : m_accessTimerEvent (), - m_cwMin (min), - m_cwMax (max), - m_backoffStart (MicroSeconds (0)), - m_backoffLeft (MicroSeconds (0)), - m_lastNavStart (MicroSeconds (0)), - m_lastNavDuration (MicroSeconds (0)), - m_lastRxStart (MicroSeconds (0)), - m_lastRxDuration (MicroSeconds (0)), - m_lastRxReceivedOk (true), - m_lastRxEnd (MicroSeconds (0)), - m_lastTxStart (MicroSeconds (0)), - m_lastTxDuration (MicroSeconds (0)), - m_lastBusyStart (MicroSeconds (0)), - m_lastBusyDuration (MicroSeconds (0)), - m_rxing (false) -{ - ResetCw (); - m_rng = new RealRandomStream (); -} - -Dcf::~Dcf () -{ - delete m_rng; -} - -void -Dcf::ResetRngForTest (RandomStream *stream) -{ - delete m_rng; - m_rng = stream; -} -void -Dcf::SetParameters (MacParameters const*parameters) -{ - m_parameters = parameters; -} - -void -Dcf::SetDifs (Time difs) -{ - m_difs = difs; -} -void -Dcf::SetEifs (Time eifs) -{ - m_eifs = eifs; -} -void -Dcf::SetCwBounds (uint32_t min, uint32_t max) -{ - m_cwMin = min; - m_cwMax = max; - m_cw = min; -} -void -Dcf::RegisterAccessListener (DcfAccessListener *listener) -{ - m_listener = listener; -} - - -/*************************************************************** - * public API. - ***************************************************************/ - -void -Dcf::RequestAccess (void) -{ - Time delayUntilAccessGranted = GetDelayUntilAccessGranted (Now ()); - if (m_listener->AccessingAndWillNotify ()) - { - /* don't do anything. We will start a backoff and maybe - * a timer when the txop notifies us of the end-of-access. - */ - NS_LOG_DEBUG ("accessing. will be notified."); - } - else if (m_accessTimerEvent.IsRunning ()) - { - /* we don't need to do anything because we have an access - * timer which will expire soon. - */ - NS_LOG_DEBUG ("access timer running. will be notified"); - } - else if (IsBackoffNotCompleted (Now ()) && m_accessTimerEvent.IsExpired ()) - { - /* start timer for ongoing backoff. - */ - NS_LOG_DEBUG ("request access X delayed for="<AccessGrantedNow (); - } -} - -/*************************************************************** - * Timeout method. Notifies when Access is Granted. - ***************************************************************/ - - -void -Dcf::AccessTimeout () -{ - UpdateBackoff (Now ()); - if (m_backoffLeft.IsZero ()) - { - NS_LOG_DEBUG ("timeout access granted"); - m_listener->AccessGrantedNow (); - } - else - { - Time delayUntilAccessGranted = GetDelayUntilAccessGranted (Now ()); - NS_LOG_DEBUG ("timeout access delayed for "<< delayUntilAccessGranted); - m_accessTimerEvent = Simulator::Schedule (delayUntilAccessGranted, - &Dcf::AccessTimeout, this); - } -} - - -/*************************************************************** - * Random trivial helper methods. - ***************************************************************/ - -Time -Dcf::PickBackoffDelay (void) -{ - uint32_t pickedCw = m_rng->GetNext (0, m_cw); - NS_LOG_DEBUG ("cw="<AccessGrantedNow (); - } - } - else - { - if (m_accessTimerEvent.IsRunning ()) - { - NS_LOG_DEBUG ("no access needed because timer running."); - } - if (!m_listener->AccessNeeded ()) - { - NS_LOG_DEBUG ("no access needed."); - } - NS_LOG_DEBUG ("no access needed for now."); - } -} -Time -Dcf::GetAccessGrantedStart (void) const -{ - /* This method evaluates the time where access to the - * medium is allowed. The return value could be - * somewhere in the past or in the future. - */ - Time rxAccessStart; - if (m_lastRxEnd >= m_lastRxStart) - { - if (m_lastRxReceivedOk) - { - rxAccessStart = m_lastRxEnd + GetDifs (); - } - else - { - rxAccessStart = m_lastRxEnd + GetEifs (); - } - } - else - { - rxAccessStart = m_lastRxStart + m_lastRxDuration + GetDifs (); - } - Time busyAccessStart = m_lastBusyStart + m_lastBusyDuration + GetDifs (); - Time txAccessStart = m_lastTxStart + m_lastTxDuration + GetDifs (); - Time navAccessStart = m_lastNavStart + m_lastNavDuration + GetDifs (); - Time accessGrantedStart = MostRecent (rxAccessStart, - busyAccessStart, - txAccessStart, - navAccessStart); - NS_LOG_DEBUG ("access granted start=" << accessGrantedStart); - return accessGrantedStart; -} - -bool -Dcf::IsBackoffNotCompleted (Time now) -{ - UpdateBackoff (now); - if (m_backoffLeft.IsStrictlyPositive ()) - { - return true; - } - else - { - return false; - } -} - - -Time -Dcf::GetDelayUntilAccessGranted (Time now) -{ - Time deltaTo = GetAccessGrantedStart () - now; - Time retval = Max (deltaTo, Seconds (0)); - UpdateBackoff (now); - retval += m_backoffLeft; - return retval; -} -void -Dcf::UpdateBackoff (Time time) -{ - if (m_backoffLeft.IsZero ()) - { - return; - } - - //NS_LOG_DEBUG ("time: %f, backoffstart: %f\n", time, m_backoffStart); - NS_ASSERT (time >= m_backoffStart); - - Time mostRecentEvent = MostRecent (m_backoffStart, - GetAccessGrantedStart ()); - if (mostRecentEvent < time) - { - Time newBackoffLeft = m_backoffLeft - (time - mostRecentEvent); - m_backoffLeft = Max (newBackoffLeft, Seconds (0)); - m_backoffStart = time; - } - NS_LOG_DEBUG ("backoff at="< - -namespace ns3 { - -class DcfTest : public Test { -public: - DcfTest (); - virtual bool RunTests (void); - - // callback from DcfListener - void AccessGrantedNow (void); - bool AccessNeeded (void); - bool AccessingAndWillNotify (void); -private: - - void AddRxOkEvt (uint64_t at, uint64_t duration); - void AddRxErrorEvt (uint64_t at, uint64_t duration); - void AddTxEvt (uint64_t at, uint64_t duration); - void AddNavReset (uint64_t at, uint64_t start, uint64_t duration); - void AddNavStart (uint64_t at, uint64_t start, uint64_t duration); - void AddNavContinue (uint64_t at, uint64_t start, uint64_t duration); - void AddAccessRequest (uint64_t time); - void AddAccessError (uint64_t time); - void AddAccessErrorButOk (uint64_t time); - void AddAccessOk (uint64_t time); - - void ExpectAccessGranted (uint64_t time); - - // callback to forward to DCF - void AccessError (uint64_t time); - void AccessErrorButOk (uint64_t time); - void AccessOk (uint64_t time); - - void StartTest (void); - void EndTest (void); - - Dcf *m_dcf; - MacParameters *m_parameters; - class TestAccessListener *m_listener; - std::list m_accessGrantedExpected; - bool m_failed; -}; - -class TestAccessListener : public DcfAccessListener { -public: - TestAccessListener (DcfTest *test) - : m_test (test) {} - virtual ~TestAccessListener () {} - virtual void AccessGrantedNow (void) { - m_test->AccessGrantedNow (); - } - virtual bool AccessNeeded (void) { - return m_test->AccessNeeded (); - } - virtual bool AccessingAndWillNotify (void) { - return m_test->AccessingAndWillNotify (); - } -private: - DcfTest *m_test; -}; - - - -DcfTest::DcfTest () - : Test ("Dcf") {} - -void -DcfTest::AccessGrantedNow (void) -{ - if (m_accessGrantedExpected.empty ()) - { - Failure () << "DCF " - << "Failure: unexpected access granted at="<UpdateFailedCw (); - m_dcf->StartBackoff (); -} -void -DcfTest::AccessErrorButOk (uint64_t time) -{ - m_dcf->ResetCw (); - m_dcf->StartBackoff (); -} -void -DcfTest::AccessOk (uint64_t time) -{ - m_dcf->ResetCw (); - m_dcf->StartBackoff (); -} - -void -DcfTest::ExpectAccessGranted (uint64_t time) -{ - m_accessGrantedExpected.push_back (time); -} - -void -DcfTest::StartTest (void) -{ - m_dcf = new Dcf (8, 64); - TestRandomStream *stream = new TestRandomStream (); - stream->AddNext (1); - stream->AddNext (1); - stream->AddNext (1); - stream->AddNext (1); - stream->AddNext (1); - stream->AddNext (1); - m_dcf->ResetRngForTest (stream); - m_parameters = new MacParameters (); - m_listener = new TestAccessListener (this); - m_dcf->SetParameters (m_parameters); - m_dcf->RegisterAccessListener (m_listener); - - m_parameters->SetSlotTime (MicroSeconds (1)); - m_dcf->SetDifs (MicroSeconds (3)); - m_dcf->SetEifs (MicroSeconds (4)); -} -void -DcfTest::EndTest (void) -{ - if (!m_accessGrantedExpected.empty ()) - { - Failure () << "DCF: access not granted as expected" - << std::endl; - } - m_accessGrantedExpected.erase (m_accessGrantedExpected.begin (), - m_accessGrantedExpected.end ()); - Simulator::Destroy (); - delete m_dcf; - delete m_parameters; - delete m_listener; -} - -bool -DcfTest::RunTests (void) -{ - m_failed = false; - - // 32 37 - // | rx ok | - // | idle | rx ok | nav busy | difs | backoff | - // 0 10 30 40 43 44 - // - StartTest (); - AddRxOkEvt (10, 20); - AddNavStart (30, 30, 2+8); - AddRxOkEvt (32, 5); - AddAccessRequest (15); - AddAccessRequest (16); - AddAccessRequest (20); - ExpectAccessGranted (44); - Simulator::Run (); - EndTest (); - - // 32 39 - // | rx ok | - // | idle | rx ok | nav busy | | difs | backoff | - // 0 10 30 37 42 43 - // - StartTest (); - AddRxOkEvt (10, 20); - AddNavStart (30, 30, 2+5); - AddRxOkEvt (32, 7); - AddAccessRequest (15); - AddAccessRequest (16); - AddAccessRequest (20); - ExpectAccessGranted (43); - Simulator::Run (); - EndTest (); - - StartTest (); - AddAccessRequest (10); - ExpectAccessGranted (10); - Simulator::Run (); - EndTest (); - - // 32 39 - // | rx ok | - // | idle | rx ok | nav busy | difs | - // 0 10 30 40 43 - // - StartTest (); - AddRxOkEvt (10, 20); - AddNavStart (30, 30, 2+8); - AddRxOkEvt (32, 7); - AddAccessRequest (40); - ExpectAccessGranted (43); - Simulator::Run (); - EndTest (); - - // 32 39 - // | rx ok | - // | idle | rx ok | nav busy | difs | - // 0 10 30 40 43 - // - StartTest (); - AddRxOkEvt (10, 20); - AddNavStart (30, 30, 2+8); - AddRxOkEvt (32, 7); - AddAccessRequest (41); - ExpectAccessGranted (43); - Simulator::Run (); - EndTest (); - - // 32 39 - // | rx ok | - // | idle | rx ok | nav busy | difs | - // 0 10 30 40 43 - // - StartTest (); - AddRxOkEvt (10, 20); - AddNavStart (30, 30, 2+8); - AddRxOkEvt (32, 7); - AddAccessRequest (43); - ExpectAccessGranted (43); - Simulator::Run (); - EndTest (); - - // - // | idle | rx error | idle | rx ok | difs | - // 0 10 30 31 38 41 - // - StartTest (); - AddRxErrorEvt (10, 20); - AddRxOkEvt (31, 7); - AddAccessRequest (39); - ExpectAccessGranted (41); - Simulator::Run (); - EndTest (); - - // - // | idle | rx error | idle | rx error | eifs | - // 0 10 30 31 38 42 - // - StartTest (); - AddRxErrorEvt (10, 20); - AddRxErrorEvt (31, 7); - AddAccessRequest (39); - ExpectAccessGranted (42); - Simulator::Run (); - EndTest (); - - - // - // 30 45 - // | nav busy | - // | idle | rx ok | idle | rx ok | difs | backoff | - // 0 10 30 35 45 48 49 - // - StartTest (); - AddRxOkEvt (10, 20); - AddNavStart (30, 30, 200); - AddRxOkEvt (35, 10); - AddNavReset (45, 45, 0); - AddAccessRequest (32); - ExpectAccessGranted (49); - Simulator::Run (); - EndTest (); - - // - // 30 45 - // | nav busy | - // | idle | rx ok | idle | rx ok | - // 0 10 30 35 45 - // - StartTest (); - AddRxOkEvt (10, 20); - AddNavStart (30, 30, 200); - AddRxOkEvt (35, 10); - AddNavReset (45, 45, 0); - Simulator::Run (); - EndTest (); - - // - // 30 45 - // | nav busy | - // | idle | rx ok | idle | rx ok | difs | - // 0 10 30 35 45 48 - // - StartTest (); - AddRxOkEvt (10, 20); - AddNavStart (30, 30, 200); - AddRxOkEvt (35, 10); - AddNavReset (45, 45, 0); - AddAccessRequest (49); - ExpectAccessGranted (49); - Simulator::Run (); - EndTest (); - - - return !m_failed; -} - -static DcfTest gDcfTest; - -} // namespace ns3 - - -#endif /* RUN_SELF_TESTS */ diff -r 3eeabad35e98 -r b6243a53c93f src/devices/wifi/dcf.h --- a/src/devices/wifi/dcf.h Sat Nov 17 18:58:47 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,261 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2005 INRIA - * - * 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: Mathieu Lacage - */ -#ifndef DCF_H -#define DCF_H - -#include -#include "ns3/event-id.h" -#include "ns3/uv-trace-source.h" -#include "ns3/callback-trace-source.h" -#include "ns3/nstime.h" - -namespace ns3 { - -class RandomStream; -class MacParameters; - -/** - * \brief listen to DCF events - * - * If you want to call methods from the ns3::Dcf class, - * you need to provide an instance of this class - * to be notified of the DCF evens. - */ -class DcfAccessListener { -public: - DcfAccessListener (); - virtual ~DcfAccessListener (); - - /** - * Tell the listener than it can start - * accessing the medium right now. - */ - virtual void AccessGrantedNow (void) = 0; - /** - * ask the listener if there are candidates - * who need access to the medium. - * - * \return true if access to the medium is - * needed, false otherwise. - */ - virtual bool AccessNeeded (void) = 0; - /** - * ask the listener if it is currently - * performing an access which was granted - * earlier to him and if it will notify - * the Dcf when the access is complete. - * - * \return true if the listener expects to call - * Dcf::RequestAccess later, false otherwise. - */ - virtual bool AccessingAndWillNotify (void) = 0; -}; - -/** - * \brief the Distributed Coordination Function - * - * This class implements the DCF as described in IEEE 802.11-1999 - * section 9.2, p72. - * - * This implementation is based on the technique described in - * Scalable simulation of large-scale wireless networks with - * bounded inaccuracies., by Z. Ji, J. Zhou, M. Takai, and R. Bagrodia. - */ -class Dcf -{ -public: - /** - * \param minCw the minimum value for CW - * \param maxCw the maximum value for CW - */ - Dcf (uint32_t minCw, uint32_t maxCw); - ~Dcf (); - - /** - * \param parameters - * - * Must be invoked after construction to configure - * a set of parameters. - */ - void SetParameters (const MacParameters *parameters); - /** - * \param difs the difs - * - * Must be invoked after construction. - */ - void SetDifs (Time difs); - /** - * \param eifs the eifs - * - * Must be invoked after construction. - */ - void SetEifs (Time eifs); - /** - * \param minCw the minimum value for CW - * \param maxCw the maximum value for CW - * - * Reset the cw bounds and CW to minCW. - */ - void SetCwBounds (uint32_t minCw, uint32_t maxCw); - /** - * \param listener the listener - * - * This listener is notified of DCF-specific events - * when they happen. You _must_ register a listener - * before calling Dcf::RequestAccess. - */ - void RegisterAccessListener (DcfAccessListener *listener); - - /** - * Request access to the medium. This method will grant - * access by calling the DcfAccessListener::AccessGrantedNow - * method - */ - void RequestAccess (void); - - /** - * Reset the CW to CWmin - * This method is typically invoked after a successfully - * transmission or after the maximum number of retries has - * been reached. - */ - void ResetCw (void); - /** - * Update the CW to a new value. This method is typically - * invoked after a failed transmission before calling - * Dcf::StartBackoff. - */ - void UpdateFailedCw (void); - /** - * Start a backoff now by picking a backoff duration - * in the [0, cw] interval. - */ - void StartBackoff (void); - - /** - * \param duration expected duration of reception - * - * Notify the DCF that a packet reception started - * for the expected duration. - */ - void NotifyRxStartNow (Time duration); - /** - * Notify the DCF that a packet reception was just - * completed successfully. - */ - void NotifyRxEndOkNow (void); - /** - * Notify the DCF that a packet reception was just - * completed unsuccessfully. - */ - void NotifyRxEndErrorNow (void); - /** - * \param duration expected duration of transmission - * - * Notify the DCF that a packet transmission was - * just started and is expected to last for the specified - * duration. - */ - void NotifyTxStartNow (Time duration); - /** - * \param duration expected duration of cca busy period - * - * Notify the DCF that a CCA busy period has just started. - */ - void NotifyCcaBusyStartNow (Time duration); - /** - * \param now the time at which a NAV starts - * \param duration the value of the received NAV. - */ - void NotifyNavReset (Time now, Time duration); - /** - * \param now the time at which a NAV starts - * \param duration the value of the received NAV. - */ - void NotifyNavStart (Time now, Time duration); - /** - * \param now the time at which a NAV starts - * \param duration the value of the received NAV. - */ - void NotifyNavContinue (Time now, Time duration); - - /** - * \param stream a random stream - * - * This method is used for testing only to force a predictable - * set of random numbers to be used. - */ - void ResetRngForTest (RandomStream *stream); -private: - void AccessTimeout (void); - - /* trivial helpers */ - Time PickBackoffDelay (void); - Time MostRecent (Time a, Time b) const; - Time MostRecent (Time a, Time b, Time c) const; - Time MostRecent (Time a, Time b, Time c, Time d) const; - Time GetDifs (void) const; - Time GetEifs (void) const; - uint32_t GetCwMin (void) const; - uint32_t GetCwMax (void) const; - - /* time calculation helpers */ - bool IsPhyBusy (void) const; - bool IsNavBusy (void) const; - bool IsBackoffNotCompleted (Time now); - Time GetDelayUntilAccessGranted (Time now); - Time GetAccessGrantedStart (void) const; - void UpdateBackoff (Time time); - - EventId m_accessTimerEvent; - - RandomStream *m_rng; - const MacParameters *m_parameters; - DcfAccessListener *m_listener; - Time m_difs; - Time m_eifs; - uint32_t m_cwMin; - uint32_t m_cwMax; - - UVTraceSource m_cw; - Time m_backoffStart; - Time m_backoffLeft; - Time m_lastNavStart; - Time m_lastNavDuration; - Time m_lastRxStart; - Time m_lastRxDuration; - bool m_lastRxReceivedOk; - Time m_lastRxEnd; - Time m_lastTxStart; - Time m_lastTxDuration; - Time m_lastBusyStart; - Time m_lastBusyDuration; - bool m_rxing; - bool m_sleeping; - /* "80211-dcf-backoff" - * param1: backoff Duration - * reports the start of a backoff - */ - CallbackTraceSource