--- a/src/devices/wifi/dca-txop.cc Mon Nov 19 16:20:30 2007 +0100
+++ b/src/devices/wifi/dca-txop.cc Mon Nov 19 16:53:05 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<WifiPhy> 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="<<m_currentPacket.GetSize ()<<
+ MY_DEBUG ("dequeued size="<<m_currentPacket.GetSize ()<<
", to="<<m_currentHdr.GetAddr1 ()<<
", seq="<<m_currentHdr.GetSequenceControl ());
}
@@ -417,8 +349,8 @@
m_transmissionListener);
m_hasCurrent = false;
m_dcf->ResetCw ();
- m_dcf->StartBackoff ();
- NS_LOG_DEBUG ("tx broadcast");
+ m_dcf->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="<<fragment.GetSize ());
+ MY_DEBUG ("fragmenting last fragment size="<<fragment.GetSize ());
params.DisableNextData ();
}
else
{
- NS_LOG_DEBUG ("fragmenting size="<<fragment.GetSize ());
+ MY_DEBUG ("fragmenting size="<<fragment.GetSize ());
params.EnableNextData (GetNextFragmentSize ());
}
Low ()->StartTransmission (fragment, &hdr, params,
@@ -447,12 +379,12 @@
if (NeedRts ())
{
params.EnableRts ();
- NS_LOG_DEBUG ("tx unicast rts");
+ MY_DEBUG ("tx unicast rts");
}
else
{
params.DisableRts ();
- NS_LOG_DEBUG ("tx unicast");
+ MY_DEBUG ("tx unicast");
}
params.DisableNextData ();
// We need to make a copy in case we need to
@@ -468,31 +400,43 @@
}
}
+void
+DcaTxop::NotifyInternalCollision (void)
+{
+ NotifyCollision ();
+}
+void
+DcaTxop::NotifyCollision (void)
+{
+ MY_DEBUG ("collision");
+ m_dcf->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="<<m_currentPacket.GetSize ());
+ MY_DEBUG ("got ack. tx not done, size="<<m_currentPacket.GetSize ());
}
}
void
DcaTxop::MissedAck (void)
{
- NS_LOG_DEBUG ("missed ack");
+ MY_DEBUG ("missed ack");
m_slrc++;
m_acktimeoutTrace (m_slrc);
if (m_slrc > 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.
--- a/src/devices/wifi/dca-txop.h Mon Nov 19 16:20:30 2007 +0100
+++ b/src/devices/wifi/dca-txop.h Mon Nov 19 16:53:05 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 <void, WifiMacHeader const&> 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<WifiPhy> 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;
--- a/src/devices/wifi/dcf.cc Mon Nov 19 16:20:30 2007 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,904 +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 <mathieu.lacage@sophia.inria.fr>
- */
-
-#include <math.h>
-
-#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="<<delayUntilAccessGranted);
- m_accessTimerEvent = Simulator::Schedule (delayUntilAccessGranted,
- &Dcf::AccessTimeout, this);
- }
- else if (IsPhyBusy () || IsNavBusy ())
- {
- /* someone else has accessed the medium.
- * generate a backoff, start timer.
- */
- StartBackoff ();
- }
- else if (delayUntilAccessGranted.IsStrictlyPositive ())
- {
- /* medium is IDLE, we have no backoff running but we
- * need to wait a bit before accessing the medium.
- */
- NS_LOG_DEBUG ("request access Y delayed for="<< delayUntilAccessGranted);
- NS_ASSERT (m_accessTimerEvent.IsExpired ());
- m_accessTimerEvent = Simulator::Schedule (delayUntilAccessGranted,
- &Dcf::AccessTimeout, this);
- }
- else
- {
- /* we can access the medium now.
- */
- NS_LOG_DEBUG ("access granted immediatly");
- m_listener->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="<<GetCwMin ()<<
- "<"<<m_cw<<"<"<<GetCwMax ()<<
- ", picked="<<pickedCw);
- Time delay = Scalar (pickedCw) * m_parameters->GetSlotTime ();
- return delay;
-}
-void
-Dcf::ResetCw (void)
-{
- m_cw = GetCwMin ();
-}
-void
-Dcf::UpdateFailedCw (void)
-{
- uint32_t cw = m_cw;
- cw *= 2;
- if (cw > GetCwMax ())
- {
- cw = GetCwMax ();
- }
- m_cw = cw;
-}
-
-Time
-Dcf::MostRecent (Time a, Time b) const
-{
- return Max (a, b);
-}
-Time
-Dcf::MostRecent (Time a, Time b, Time c) const
-{
- Time retval;
- retval = Max (a, b);
- retval = Max (retval, c);
- return retval;
-}
-Time
-Dcf::MostRecent (Time a, Time b, Time c, Time d) const
-{
- Time e = Max (a, b);
- Time f = Max (c, d);
- Time retval = Max (e, f);
- return retval;
-}
-
-Time
-Dcf::GetDifs (void) const
-{
- return m_difs;
-}
-Time
-Dcf::GetEifs (void) const
-{
- return m_eifs;
-}
-uint32_t
-Dcf::GetCwMin (void) const
-{
- return m_cwMin;
-}
-uint32_t
-Dcf::GetCwMax (void) const
-{
- return m_cwMax;
-}
-
-/***************************************************************
- * Complicated timekeeping backoff methods.
- ***************************************************************/
-
-bool
-Dcf::IsPhyBusy (void) const
-{
- if (m_rxing)
- {
- return true;
- }
- Time lastTxEnd = m_lastTxStart + m_lastTxDuration;
- if (lastTxEnd > Simulator::Now ())
- {
- return true;
- }
- return false;
-}
-
-bool
-Dcf::IsNavBusy (void) const
-{
- Time lastNavEnd = m_lastNavStart + m_lastNavDuration;
- if (lastNavEnd > Simulator::Now ())
- {
- return true;
- }
- return false;
-}
-
-void
-Dcf::StartBackoff (void)
-{
- Time backoffStart = Now ();
- Time backoffDuration = PickBackoffDelay ();
- m_backoffTrace (backoffDuration);
- NS_ASSERT (m_backoffStart <= backoffStart);
- m_backoffStart = backoffStart;
- m_backoffLeft = backoffDuration;
- if (m_listener->AccessNeeded () && m_accessTimerEvent.IsExpired ())
- {
- Time delayUntilAccessGranted = GetDelayUntilAccessGranted (Now ());
- if (delayUntilAccessGranted.IsStrictlyPositive ())
- {
- NS_LOG_DEBUG ("start at "<<backoffStart<<", for "<<backoffDuration);
- m_accessTimerEvent = Simulator::Schedule (delayUntilAccessGranted,
- &Dcf::AccessTimeout, this);
- }
- else
- {
- NS_LOG_DEBUG ("access granted now");
- m_listener->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="<<m_backoffStart<<", left="<< m_backoffLeft);
-}
-
-/***************************************************************
- * Notification methods.
- ***************************************************************/
-void
-Dcf::NotifyNavReset (Time navStart, Time duration)
-{
- NS_LOG_DEBUG ("nav reset at="<<navStart<<", for="<<duration);
- m_lastNavStart = navStart;
- m_lastNavDuration = duration;
- Time navEnd = navStart + duration;
- Time newDelayUntilAccessGranted = GetDelayUntilAccessGranted (navEnd);
- NS_ASSERT (newDelayUntilAccessGranted.IsStrictlyPositive ());
- /* This is quite unfortunate but we need to cancel the access timer
- * because this nav reset might have brought the time of
- * possible access closer to us than expected.
- */
- if (m_accessTimerEvent.IsRunning ())
- {
- m_accessTimerEvent.Cancel ();
- m_accessTimerEvent = Simulator::Schedule (newDelayUntilAccessGranted,
- &Dcf::AccessTimeout, this);
- }
-}
-void
-Dcf::NotifyNavStart (Time navStart, Time duration)
-{
- NS_ASSERT (m_lastNavStart < navStart);
- NS_LOG_DEBUG ("nav start at="<<navStart<<", for="<<duration);
- UpdateBackoff (navStart);
- m_lastNavStart = navStart;
- m_lastNavDuration = duration;
-}
-void
-Dcf::NotifyNavContinue (Time navStart, Time duration)
-{
- NotifyNavStart (navStart, duration);
-}
-
-void
-Dcf::NotifyRxStartNow (Time duration)
-{
- Time now = Now ();
- NS_LOG_DEBUG ("rx start at="<<now<<", for="<<duration);
- UpdateBackoff (now);
- m_lastRxStart = now;
- m_lastRxDuration = duration;
- m_rxing = true;
-}
-void
-Dcf::NotifyRxEndOkNow (void)
-{
- Time now = Now ();
- NS_LOG_DEBUG ("rx end ok at="<<now);
- m_lastRxEnd = now;
- m_lastRxReceivedOk = true;
- m_rxing = false;
-}
-void
-Dcf::NotifyRxEndErrorNow (void)
-{
- Time now = Now ();
- NS_LOG_DEBUG ("rx end error at=");
- m_lastRxEnd = now;
- m_lastRxReceivedOk = false;
- m_rxing = false;
-}
-void
-Dcf::NotifyTxStartNow (Time duration)
-{
- Time now = Now ();
- NS_LOG_DEBUG ("tx start at="<<now<<" for "<<duration);
- UpdateBackoff (now);
- m_lastTxStart = now;
- m_lastTxDuration = duration;
-}
-
-void
-Dcf::NotifyCcaBusyStartNow (Time duration)
-{
- Time now = Now ();
- NS_LOG_DEBUG ("busy start at="<<now<<" for "<<duration);
- UpdateBackoff (now);
- m_lastBusyStart = now;
- m_lastBusyDuration = duration;
-}
-
-} // namespace ns3
-
-#ifdef RUN_SELF_TESTS
-#include "ns3/test.h"
-#include <list>
-
-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<uint64_t> 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="<<Simulator::Now ()
- << std::endl;
- m_failed = true;
- return;
- }
- uint64_t expected = m_accessGrantedExpected.front ();
- uint64_t actual = Simulator::Now ().GetMicroSeconds ();
- if (expected != actual)
- {
- Failure () << "DCF "
- << "Failure: access granted at=" << Simulator::Now ()
- << ", expected at="<<expected<<"us"
- << std::endl;
- m_failed = true;
- return;
- }
- m_accessGrantedExpected.erase (m_accessGrantedExpected.begin ());
-}
-bool
-DcfTest::AccessNeeded (void)
-{
- return true;
-}
-bool
-DcfTest::AccessingAndWillNotify (void)
-{
- return false;
-}
-
-void
-DcfTest::AddRxOkEvt (uint64_t at, uint64_t duration)
-{
- Simulator::Schedule (MicroSeconds (at) - Now (),
- &Dcf::NotifyRxStartNow, m_dcf,
- MicroSeconds (duration));
- Simulator::Schedule (MicroSeconds (at+duration) - Now (),
- &Dcf::NotifyRxEndOkNow, m_dcf);
-}
-void
-DcfTest::AddRxErrorEvt (uint64_t at, uint64_t duration)
-{
- Simulator::Schedule (MicroSeconds (at) - Now (),
- &Dcf::NotifyRxStartNow, m_dcf,
- MicroSeconds (duration));
- Simulator::Schedule (MicroSeconds (at+duration) - Now (),
- &Dcf::NotifyRxEndErrorNow, m_dcf);
-}
-void
-DcfTest::AddTxEvt (uint64_t at, uint64_t duration)
-{
- Simulator::Schedule (MicroSeconds (at) - Now (),
- &Dcf::NotifyTxStartNow, m_dcf,
- MicroSeconds (duration));
-}
-void
-DcfTest::AddNavReset (uint64_t at, uint64_t start, uint64_t duration)
-{
- Simulator::Schedule (MicroSeconds (at) - Now (),
- &Dcf::NotifyNavReset, m_dcf,
- MicroSeconds (start),
- MicroSeconds (duration));
-}
-void
-DcfTest::AddNavStart (uint64_t at, uint64_t start, uint64_t duration)
-{
- Simulator::Schedule (MicroSeconds (at) - Now (),
- &Dcf::NotifyNavStart, m_dcf,
- MicroSeconds (start), MicroSeconds (duration));
-}
-void
-DcfTest::AddNavContinue (uint64_t at, uint64_t start, uint64_t duration)
-{
- Simulator::Schedule (MicroSeconds (at) - Now (),
- &Dcf::NotifyNavContinue, m_dcf,
- MicroSeconds (start),
- MicroSeconds (duration));
-}
-void
-DcfTest::AddAccessRequest (uint64_t time)
-{
- Simulator::Schedule (MicroSeconds (time) - Now (),
- &Dcf::RequestAccess, m_dcf);
-}
-void
-DcfTest::AddAccessError (uint64_t time)
-{
- Simulator::Schedule (MicroSeconds (time) - Now (),
- &DcfTest::AccessError, this,
- time);
-}
-void
-DcfTest::AddAccessErrorButOk (uint64_t time)
-{
- Simulator::Schedule (MicroSeconds (time) - Now (),
- &DcfTest::AccessErrorButOk, this,
- time);
-}
-void
-DcfTest::AddAccessOk (uint64_t time)
-{
- Simulator::Schedule (MicroSeconds (time) - Now (),
- &DcfTest::AccessOk, this,
- time);
-}
-
-void
-DcfTest::AccessError (uint64_t time)
-{
- m_dcf->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 */
--- a/src/devices/wifi/dcf.h Mon Nov 19 16:20:30 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 <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef DCF_H
-#define DCF_H
-
-#include <stdint.h>
-#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
- * <i>Scalable simulation of large-scale wireless networks with
- * bounded inaccuracies.</i>, 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<uint32_t> 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<Time> m_backoffTrace;
-};
-
-} // namespace ns3
-
-#endif /* DCF_H */
--- a/src/devices/wifi/mac-low.cc Mon Nov 19 16:20:30 2007 +0100
+++ b/src/devices/wifi/mac-low.cc Mon Nov 19 16:53:05 2007 +0100
@@ -35,7 +35,8 @@
NS_LOG_COMPONENT_DEFINE ("MacLow");
#define MY_DEBUG(x) \
- NS_LOG_DEBUG (Simulator::Now () << " " << m_device->GetNode ()->GetId () << " " << x)
+ NS_LOG_DEBUG (Simulator::Now () << " " << m_device->GetNode ()->GetId () << ":" << \
+ m_device->GetIfIndex () << " " << x)
namespace ns3 {
@@ -305,6 +306,11 @@
{
m_device = device;
}
+Ptr<NetDevice>
+MacLow::GetDevice (void) const
+{
+ return m_device;
+}
void
MacLow::SetPhy (Ptr<WifiPhy> phy)
{
@@ -405,12 +411,17 @@
WifiMacHeader hdr;
packet.RemoveHeader (hdr);
- bool isPrevNavZero = IsNavZero (Simulator::Now ());
+ bool isPrevNavZero = IsNavZero ();
MY_DEBUG ("duration/id=" << hdr.GetDuration ());
- NotifyNav (Simulator::Now (), &hdr);
+ NotifyNav (hdr, txMode, preamble);
if (hdr.IsRts ())
{
- /* XXX see section 9.9.2.2.1 802.11e/D12.1 */
+ /* see section 9.2.5.7 802.11-1999
+ * A STA that is addressed by an RTS frame shall transmit a CTS frame after a SIFS
+ * period if the NAV at the STA receiving the RTS frame indicates that the medium is
+ * idle. If the NAV at the STA receiving the RTS indicates the medium is not idle,
+ * that STA shall not respond to the RTS frame.
+ */
if (isPrevNavZero &&
hdr.GetAddr1 () == m_device->GetSelfAddress ())
{
@@ -656,56 +667,82 @@
return txTime;
}
+void
+MacLow::NotifyNav (const WifiMacHeader &hdr, WifiMode txMode, WifiPreamble preamble)
+{
+ NS_ASSERT (m_lastNavStart <= Simulator::Now ());
+ Time duration = hdr.GetDuration ();
+
+ if (hdr.IsCfpoll () &&
+ hdr.GetAddr2 () == m_device->GetBssid ())
+ {
+ // see section 9.3.2.2 802.11-1999
+ DoNavResetNow (duration);
+ return;
+ }
+ // XXX Note that we should also handle CF_END specially here
+ // but we don't for now because we do not generate them.
+ else if (hdr.GetAddr1 () == m_device->GetSelfAddress ())
+ {
+ // see section 9.2.5.4 802.11-1999
+ bool navUpdated = DoNavStartNow (duration);
+ if (hdr.IsRts () && navUpdated)
+ {
+ /**
+ * A STA that used information from an RTS frame as the most recent basis to update its NAV setting
+ * is permitted to reset its NAV if no PHY-RXSTART.indication is detected from the PHY during a
+ * period with a duration of (2 * aSIFSTime) + (CTS_Time) + (2 * aSlotTime) starting at the
+ * PHY-RXEND.indication corresponding to the detection of the RTS frame. The “CTS_Time” shall
+ * be calculated using the length of the CTS frame and the data rate at which the RTS frame
+ * used for the most recent NAV update was received.
+ */
+ WifiMacHeader cts;
+ cts.SetType (WIFI_MAC_CTL_CTS);
+ Time navCounterResetCtsMissedDelay =
+ m_phy->CalculateTxDuration (cts.GetSerializedSize (), txMode, preamble) +
+ Scalar (2) * m_parameters->GetSifs () + Scalar (2) * m_parameters->GetSlotTime ();
+ m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay,
+ &MacLow::NavCounterResetCtsMissed, this,
+ Simulator::Now ());
+ }
+ }
+}
void
-MacLow::NotifyNav (Time at, WifiMacHeader const *hdr)
+MacLow::NavCounterResetCtsMissed (Time rtsEndRxTime)
+{
+ if (m_phy->GetLastRxStartTime () > rtsEndRxTime)
+ {
+ DoNavResetNow (Seconds (0.0));
+ }
+}
+
+void
+MacLow::DoNavResetNow (Time duration)
{
- /* XXX
- * We might need to do something special for the
- * subtle case of RTS/CTS. I don't know what.
- *
- * See section 9.9.2.2.1, 802.11e/D12.1
- */
- NS_ASSERT (m_lastNavStart < at);
- Time oldNavStart = m_lastNavStart;
- Time oldNavEnd = oldNavStart + m_lastNavDuration;
- Time newNavStart = at;
- Time duration = hdr->GetDuration ();
-
- if (hdr->IsCfpoll () &&
- hdr->GetAddr2 () == m_device->GetBssid ())
+ for (NavListenersCI i = m_navListeners.begin (); i != m_navListeners.end (); i++)
{
- m_lastNavStart = newNavStart;
+ (*i)->NavReset (duration);
+ }
+ m_lastNavStart = Simulator::Now ();
+ m_lastNavStart = duration;
+}
+bool
+MacLow::DoNavStartNow (Time duration)
+{
+ for (NavListenersCI i = m_navListeners.begin (); i != m_navListeners.end (); i++)
+ {
+ (*i)->NavStart (duration);
+ }
+ Time newNavEnd = Simulator::Now () + duration;
+ Time oldNavEnd = m_lastNavStart + m_lastNavDuration;
+ if (newNavEnd > oldNavEnd)
+ {
+ m_lastNavStart = Simulator::Now ();
m_lastNavDuration = duration;
- for (NavListenersCI i = m_navListeners.begin (); i != m_navListeners.end (); i++)
- {
- // XXX !!!!!!!
- (*i)->NavReset (newNavStart, duration);
- }
- return;
+ return true;
}
-
- if (oldNavEnd > newNavStart)
- {
- Time newNavEnd = newNavStart + duration;
- /* The two NAVs overlap */
- if (newNavEnd > oldNavEnd)
- {
- for (NavListenersCI i = m_navListeners.begin (); i != m_navListeners.end (); i++)
- {
- (*i)->NavContinue (newNavStart, duration);
- }
- }
- }
- else
- {
- m_lastNavStart = newNavStart;
- m_lastNavDuration = duration;
- for (NavListenersCI i = m_navListeners.begin (); i != m_navListeners.end (); i++)
- {
- (*i)->NavStart (newNavStart, duration);
- }
- }
+ return false;
}
void
@@ -719,11 +756,13 @@
", duration=" << hdr->GetDuration () <<
", seq=0x"<< std::hex << m_currentHdr.GetSequenceControl () << std::dec);
m_phy->SendPacket (packet, txMode, WIFI_PREAMBLE_LONG, 0);
- /* Note that it is really important to notify the NAV
- * thing _after_ forwarding the packet to the PHY.
+ /*
+ * We have to notify the NAV of transmitted packets because of the 802.11e
+ * requirement from section 9.9.1.4 that each EDCAF update its NAV from the
+ * transmission of any other EDCAF within the same QSTA.
*/
Time txDuration = m_phy->CalculateTxDuration (packet.GetSize (), txMode, WIFI_PREAMBLE_LONG);
- NotifyNav (Simulator::Now ()+txDuration, hdr);
+ Simulator::Schedule (txDuration, &MacLow::NotifyNav, this, *hdr, txMode, WIFI_PREAMBLE_LONG);
}
void
@@ -904,9 +943,9 @@
}
bool
-MacLow::IsNavZero (Time now)
+MacLow::IsNavZero (void) const
{
- if (m_lastNavStart + m_lastNavDuration > now)
+ if (m_lastNavStart + m_lastNavDuration > Simulator::Now ())
{
return false;
}
--- a/src/devices/wifi/mac-low.h Mon Nov 19 16:20:30 2007 +0100
+++ b/src/devices/wifi/mac-low.h Mon Nov 19 16:53:05 2007 +0100
@@ -111,17 +111,12 @@
* \param now start of NAV timer
* \param duration duration of NAV timer
*/
- virtual void NavStart (Time now, Time duration) = 0;
+ virtual void NavStart (Time duration) = 0;
/**
* \param now start of NAV timer
* \param duration duration of NAV timer
*/
- virtual void NavContinue (Time now, Time duration) = 0;
- /**
- * \param now start of NAV timer
- * \param duration duration of NAV timer
- */
- virtual void NavReset (Time now, Time duration) = 0;
+ virtual void NavReset (Time duration) = 0;
};
/**
@@ -288,6 +283,7 @@
void SetPhy (Ptr<WifiPhy> phy);
void SetStations (MacStations *stations);
void SetParameters (MacParameters *parameters);
+ Ptr<NetDevice> GetDevice (void) const;
/**
* \param callback the callback which receives every incoming packet.
*
@@ -368,10 +364,13 @@
WifiMode GetAckTxModeForData (Mac48Address to, WifiMode dataTxMode) const;
Time GetCtsDuration (Mac48Address to, WifiMode rtsTxMode) const;
Time GetAckDuration (Mac48Address to, WifiMode dataTxMode) const;
- void NotifyNav (Time at, WifiMacHeader const*hdr);
- bool IsNavZero (Time at);
+ void NotifyNav (const WifiMacHeader &hdr, WifiMode txMode, WifiPreamble preamble);
+ void DoNavResetNow (Time duration);
+ bool DoNavStartNow (Time duration);
+ bool IsNavZero (void) const;
void MaybeCancelPrevious (void);
+ void NavCounterResetCtsMissed (Time rtsEndRxTime);
void NormalAckTimeout (void);
void FastAckTimeout (void);
void SuperFastAckTimeout (void);
@@ -405,6 +404,7 @@
EventId m_sendAckEvent;
EventId m_sendDataEvent;
EventId m_waitSifsEvent;
+ EventId m_navCounterResetCtsMissed;
Packet m_currentPacket;
bool m_hasCurrent;
--- a/src/devices/wifi/wifi-net-device.cc Mon Nov 19 16:20:30 2007 +0100
+++ b/src/devices/wifi/wifi-net-device.cc Mon Nov 19 16:53:05 2007 +0100
@@ -34,6 +34,7 @@
#include "mac-high-nqsta.h"
#include "mac-high-nqap.h"
#include "dca-txop.h"
+#include "dcf-manager.h"
#include "wifi-default-parameters.h"
#include "arf-mac-stations.h"
#include "aarf-mac-stations.h"
@@ -42,6 +43,10 @@
namespace ns3 {
+/***************************************************************
+ * hold an enumeration of the trace types
+ ***************************************************************/
+
WifiNetDeviceTraceType::WifiNetDeviceTraceType ()
: m_type (RX)
{}
@@ -79,6 +84,9 @@
return "ns3::WifiNetDeviceTraceType";
}
+/***************************************************************
+ * a static helper
+ ***************************************************************/
static WifiMode
GetWifiModeForPhyMode (Ptr<WifiPhy> phy, enum WifiDefaultParameters::PhyModeParameter mode)
@@ -96,6 +104,57 @@
return WifiMode ();
}
+/***************************************************************
+ * Listener for Nav events. Forwards to DcfManager
+ ***************************************************************/
+
+class WifiNetDevice::NavListener : public ns3::MacLowNavListener {
+public:
+ NavListener (ns3::DcfManager *dcf)
+ : m_dcf (dcf) {}
+ virtual ~NavListener () {}
+ virtual void NavStart (Time duration) {
+ m_dcf->NotifyNavStartNow (duration);
+ }
+ virtual void NavReset (Time duration) {
+ m_dcf->NotifyNavResetNow (duration);
+ }
+private:
+ ns3::DcfManager *m_dcf;
+};
+
+/***************************************************************
+ * Listener for PHY events. Forwards to DcfManager
+ ***************************************************************/
+
+class WifiNetDevice::PhyListener : public ns3::WifiPhyListener {
+public:
+ PhyListener (ns3::DcfManager *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 NotifyTxStart (Time duration) {
+ m_dcf->NotifyTxStartNow (duration);
+ }
+ virtual void NotifyCcaBusyStart (Time duration) {
+ m_dcf->NotifyCcaBusyStartNow (duration);
+ }
+private:
+ ns3::DcfManager *m_dcf;
+};
+
+/***************************************************************
+ * The NetDevice itself
+ ***************************************************************/
+
WifiNetDevice::WifiNetDevice (Ptr<Node> node)
: NetDevice (node, Mac48Address::Allocate ())
@@ -180,25 +239,24 @@
MacTxMiddle *txMiddle = new MacTxMiddle ();
m_txMiddle = txMiddle;
+ m_manager = new DcfManager ();
+ Time ackTxDuration = m_phy->CalculateTxDuration (8 * (2+2+6+4), m_phy->GetMode (0), WIFI_PREAMBLE_LONG);
+ m_manager->SetAckTxDuration (ackTxDuration);
+ m_manager->SetSlotTime (m_parameters->GetSlotTime ());
+ m_manager->SetSifs (m_parameters->GetSifs ());
+ m_phyListener = new WifiNetDevice::PhyListener (m_manager);
+ m_phy->RegisterListener (m_phyListener);
+ m_navListener = new WifiNetDevice::NavListener (m_manager);
+ m_low->RegisterNavListener (m_navListener);
}
DcaTxop *
-WifiNetDevice::CreateDca (uint32_t minCw, uint32_t maxCw) const
+WifiNetDevice::CreateDca (uint32_t minCw, uint32_t maxCw, uint32_t aifsn) const
{
- DcaTxop *dca = new DcaTxop (minCw, maxCw);
+ DcaTxop *dca = new DcaTxop (minCw, maxCw, aifsn, m_manager);
dca->SetParameters (m_parameters);
dca->SetTxMiddle (m_txMiddle);
dca->SetLow (m_low);
- dca->SetPhy (m_phy);
-
- Time difs = m_parameters->GetSifs () +
- m_parameters->GetSlotTime () +
- m_parameters->GetSlotTime ();
- // see 802.11 p85 section 9.2.10
- Time eifs = difs + m_parameters->GetSifs () +
- m_phy->CalculateTxDuration (8 * (2+2+6+4), m_phy->GetMode (0), WIFI_PREAMBLE_LONG);
- dca->SetDifs (difs);
- dca->SetEifs (eifs);
dca->SetMaxQueueSize (400);
dca->SetMaxQueueDelay (Seconds (10));
return dca;
@@ -288,6 +346,9 @@
delete m_rxMiddle;
delete m_txMiddle;
delete m_parameters;
+ delete m_manager;
+ delete m_phyListener;
+ delete m_navListener;
m_phy = 0;
m_stations = 0;
m_low = 0;
@@ -305,7 +366,7 @@
: WifiNetDevice (node)
{
m_ssid = WifiDefaultParameters::GetSsid ();
- m_dca = CreateDca (15, 1023);
+ m_dca = CreateDca (15, 1023, 2);
MacHighAdhoc *high = new MacHighAdhoc ();
high->SetDevice (this);
@@ -367,7 +428,7 @@
: WifiNetDevice (node)
{
m_ssid = WifiDefaultParameters::GetSsid ();
- m_dca = CreateDca (15, 1023);
+ m_dca = CreateDca (15, 1023, 2);
MacHighNqsta *high = new MacHighNqsta ();
high->SetDevice (this);
@@ -447,17 +508,10 @@
{
m_ssid = WifiDefaultParameters::GetSsid ();
- m_dca = CreateDca (15, 1023);
- m_beaconDca = CreateDca (15, 1023);
- /**
- * We use a DIFS value for the beacons smaller than the 802.11 default
- * value to ensure that the beacon queue will get access to the medium
- * even when a lot of data has been queued. This is an 'extension' of
- * 802.11 which is a first step towards 802.11e but it is a nice way
- * to get timely beacons without a lot of other hacks.
- */
- Time beaconDifs = m_parameters->GetSifs () + m_parameters->GetSlotTime ();
- m_beaconDca->SetDifs (beaconDifs);
+ // The Beacon DCA is higher priority than
+ // the normal DCA so, we create it first.
+ m_beaconDca = CreateDca (0, 0, 1);
+ m_dca = CreateDca (15, 1023, 2);
// By default, we configure the Basic Rate Set to be the set
// of rates we support which are mandatory.
--- a/src/devices/wifi/wifi-net-device.h Mon Nov 19 16:20:30 2007 +0100
+++ b/src/devices/wifi/wifi-net-device.h Mon Nov 19 16:53:05 2007 +0100
@@ -41,6 +41,7 @@
class MacHighAdhoc;
class MacHighNqsta;
class MacHighNqap;
+class DcfManager;
/**
* \brief hold the type of trace event generated by
@@ -98,6 +99,10 @@
virtual Ssid GetSsid (void) const = 0;
private:
+ class PhyListener;
+ class NavListener;
+ friend class WifiNetDeviceFactory;
+
// inherited from parent.
virtual bool DoNeedsArp (void) const;
virtual Ptr<Channel> DoGetChannel (void) const;
@@ -109,15 +114,13 @@
// private helper
void Construct (void);
- friend class WifiNetDeviceFactory;
-
CallbackTraceSource<Packet, Mac48Address> m_rxLogger;
CallbackTraceSource<Packet, Mac48Address> m_txLogger;
protected:
WifiNetDevice (Ptr<Node> node);
void DoForwardUp (Packet packet, const Mac48Address &from);
virtual void DoDispose (void);
- DcaTxop *CreateDca (uint32_t minCw, uint32_t maxCw) const;
+ DcaTxop *CreateDca (uint32_t minCw, uint32_t maxCw, uint32_t aifsn) const;
Ptr<WifiChannel> m_channel;
Ptr<WifiPhy> m_phy;
@@ -126,6 +129,9 @@
MacRxMiddle *m_rxMiddle;
MacTxMiddle *m_txMiddle;
MacParameters *m_parameters;
+ DcfManager *m_manager;
+ PhyListener *m_phyListener;
+ NavListener *m_navListener;
};
/**
--- a/src/devices/wifi/wscript Mon Nov 19 16:20:30 2007 +0100
+++ b/src/devices/wifi/wscript Mon Nov 19 16:53:05 2007 +0100
@@ -17,7 +17,6 @@
'wifi-mac-trailer.cc',
'mac-parameters.cc',
'mac-low.cc',
- 'dcf.cc',
'wifi-mac-queue.cc',
'mac-tx-middle.cc',
'mac-rx-middle.cc',