add Dcf to build

This commit is contained in:
Mathieu Lacage
2007-10-09 12:17:02 +02:00
parent 1e6415ce45
commit bc276b2bc1
3 changed files with 981 additions and 0 deletions

841
src/devices/wifi/dcf.cc Normal file
View File

@@ -0,0 +1,841 @@
/* -*- 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 <iostream>
#include <cassert>
#include <math.h>
#include "ns3/random-variable.h"
#include "ns3/simulator.h"
#include "dcf.h"
#include "mac-parameters.h"
#define noDCF_TRACE 1
#ifdef DCF_TRACE
# include <iostream>
# define TRACE(x) \
std::cout << "DCF " << x << std::endl;
#else /* DCF_TRACE */
# define TRACE(x)
#endif /* DCF_TRACE */
namespace ns3 {
DcfAccessListener::DcfAccessListener ()
{}
DcfAccessListener::~DcfAccessListener ()
{}
Dcf::Dcf ()
: m_accessTimerEvent (),
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_random = new UniformVariable ();
}
Dcf::~Dcf ()
{
delete m_random;
}
void
Dcf::ResetRng (uint32_t seed)
{
// XXX
// m_random->Reset (seed);
}
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.
*/
TRACE ("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.
*/
TRACE ("access timer running. will be notified");
}
else if (IsBackoffNotCompleted (Now ()) && m_accessTimerEvent.IsExpired ())
{
/* start timer for ongoing backoff.
*/
TRACE ("request access X delayed for="<<delayUntilAccessGranted);
m_accessTimerEvent = Simulator::Schedule (delayUntilAccessGranted,
&Dcf::AccessTimeout, this);
}
else if (IsPhyBusy ())
{
/* 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.
*/
TRACE ("request access Y delayed for="<< delayUntilAccessGranted);
assert (m_accessTimerEvent.IsExpired ());
m_accessTimerEvent = Simulator::Schedule (delayUntilAccessGranted,
&Dcf::AccessTimeout, this);
}
else
{
/* we can access the medium now.
*/
TRACE ("access granted immediatly");
m_listener->AccessGrantedNow ();
}
}
/***************************************************************
* Timeout method. Notifies when Access is Granted.
***************************************************************/
void
Dcf::AccessTimeout ()
{
UpdateBackoff (Now ());
if (m_backoffLeft.IsZero ())
{
TRACE ("timeout access granted");
m_listener->AccessGrantedNow ();
}
else
{
Time delayUntilAccessGranted = GetDelayUntilAccessGranted (Now ());
TRACE ("timeout access delayed for "<< delayUntilAccessGranted);
m_accessTimerEvent = Simulator::Schedule (delayUntilAccessGranted,
&Dcf::AccessTimeout, this);
}
}
/***************************************************************
* Random trivial helper methods.
***************************************************************/
Time
Dcf::PickBackoffDelay (void)
{
// XXX
//uint32_t pickedCw = m_random->GetSingleValue (0, m_cw);
uint32_t pickedCw = 0;
TRACE ("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)
{
if (m_rxing)
{
return true;
}
Time lastTxEnd = m_lastTxStart + m_lastTxDuration;
if (lastTxEnd > Simulator::Now ())
{
return true;
}
return false;
}
void
Dcf::StartBackoff (void)
{
Time backoffStart = Now ();
Time backoffDuration = PickBackoffDelay ();
m_backoffTrace (backoffDuration);
assert (m_backoffStart <= backoffStart);
m_backoffStart = backoffStart;
m_backoffLeft = backoffDuration;
if (m_listener->AccessNeeded () && m_accessTimerEvent.IsExpired ())
{
Time delayUntilAccessGranted = GetDelayUntilAccessGranted (Now ());
if (delayUntilAccessGranted.IsStrictlyPositive ())
{
TRACE ("start at "<<backoffStart<<", for "<<backoffDuration);
m_accessTimerEvent = Simulator::Schedule (delayUntilAccessGranted,
&Dcf::AccessTimeout, this);
}
else
{
TRACE ("access granted now");
m_listener->AccessGrantedNow ();
}
}
else
{
if (m_accessTimerEvent.IsRunning ())
{
TRACE ("no access needed because timer running.");
}
if (!m_listener->AccessNeeded ())
{
TRACE ("no access needed.");
}
TRACE ("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);
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;
}
//TRACE ("time: %f, backoffstart: %f\n", time, m_backoffStart);
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));
TRACE ("at="<<time<<", left="<< m_backoffLeft);
m_backoffStart = time;
}
}
/***************************************************************
* Notification methods.
***************************************************************/
void
Dcf::NotifyNavReset (Time navStart, Time duration)
{
m_lastNavStart = navStart;
m_lastNavDuration = duration;
Time navEnd = navStart + duration;
Time newDelayUntilAccessGranted = GetDelayUntilAccessGranted (navEnd);
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)
{
assert (m_lastNavStart < navStart);
TRACE ("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 ();
TRACE ("rx start at="<<now<<", for="<<duration);
UpdateBackoff (now);
m_lastRxStart = now;
m_lastRxDuration = duration;
m_rxing = true;
}
void
Dcf::NotifyRxEndOkNow (void)
{
Time now = Now ();
TRACE ("rx end ok at="<<now);
m_lastRxEnd = now;
m_lastRxReceivedOk = true;
m_rxing = false;
}
void
Dcf::NotifyRxEndErrorNow (void)
{
Time now = Now ();
TRACE ("rx end error at=");
m_lastRxEnd = now;
m_lastRxReceivedOk = false;
m_rxing = false;
}
void
Dcf::NotifyTxStartNow (Time duration)
{
Time now = Now ();
TRACE ("tx start at="<<now<<" for "<<duration);
UpdateBackoff (now);
m_lastTxStart = now;
m_lastTxDuration = duration;
}
void
Dcf::NotifyCcaBusyStartNow (Time duration)
{
Time now = Now ();
TRACE ("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 ();
m_dcf->ResetRng (0);
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));
m_dcf->SetCwBounds (8, 64);
}
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;
StartTest ();
AddRxOkEvt (10, 20);
AddNavStart (30, 30, 2+8);
AddRxOkEvt (32, 5);
AddAccessRequest (15);
AddAccessRequest (16);
AddAccessRequest (20);
ExpectAccessGranted (51);
Simulator::Run ();
EndTest ();
StartTest ();
AddRxOkEvt (10, 20);
AddNavStart (30, 30, 2+5);
AddRxOkEvt (32, 7);
AddAccessRequest (15);
AddAccessRequest (16);
AddAccessRequest (20);
ExpectAccessGranted (50);
Simulator::Run ();
EndTest ();
StartTest ();
AddAccessRequest (10);
ExpectAccessGranted (10);
Simulator::Run ();
EndTest ();
StartTest ();
AddRxOkEvt (10, 20);
AddNavStart (30, 30, 2+8);
AddRxOkEvt (32, 7);
AddAccessRequest (40);
ExpectAccessGranted (43);
Simulator::Run ();
EndTest ();
StartTest ();
AddRxOkEvt (10, 20);
AddNavStart (30, 30, 2+8);
AddRxOkEvt (32, 7);
AddAccessRequest (41);
ExpectAccessGranted (43);
Simulator::Run ();
EndTest ();
StartTest ();
AddRxOkEvt (10, 20);
AddNavStart (30, 30, 2+8);
AddRxOkEvt (32, 7);
AddAccessRequest (43);
ExpectAccessGranted (43);
Simulator::Run ();
EndTest ();
StartTest ();
AddRxErrorEvt (10, 20);
AddRxOkEvt (31, 7);
AddAccessRequest (39);
ExpectAccessGranted (41);
Simulator::Run ();
EndTest ();
StartTest ();
AddRxErrorEvt (10, 20);
AddRxErrorEvt (31, 7);
AddAccessRequest (39);
ExpectAccessGranted (42);
Simulator::Run ();
EndTest ();
StartTest ();
AddRxOkEvt (10, 20);
AddNavStart (30, 30, 200);
AddRxOkEvt (35, 10);
AddNavReset (45, 45, 0);
AddAccessRequest (32);
ExpectAccessGranted (48);
Simulator::Run ();
EndTest ();
StartTest ();
AddRxOkEvt (10, 20);
AddNavStart (30, 30, 200);
AddRxOkEvt (35, 10);
AddNavReset (45, 45, 0);
Simulator::Run ();
EndTest ();
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 */

139
src/devices/wifi/dcf.h Normal file
View File

@@ -0,0 +1,139 @@
/* -*- 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 UniformVariable;
class MacParameters;
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.
*/
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.
*/
virtual bool AccessingAndWillNotify (void) = 0;
};
class Dcf
{
public:
Dcf ();
~Dcf ();
void ResetRng (uint32_t seed);
void SetParameters (const MacParameters *parameters);
void SetDifs (Time difs);
void SetEifs (Time eifs);
void SetCwBounds (uint32_t min, uint32_t max);
void RegisterAccessListener (DcfAccessListener *listener);
void RequestAccess (void);
void ResetCw (void);
void UpdateFailedCw (void);
void StartBackoff (void);
/* notification methods. */
void NotifyRxStartNow (Time duration);
void NotifyRxEndOkNow (void);
void NotifyRxEndErrorNow (void);
void NotifyTxStartNow (Time duration);
void NotifyCcaBusyStartNow (Time duration);
void NotifyNavReset (Time now, Time duration);
void NotifyNavStart (Time now, Time duration);
void NotifyNavContinue (Time now, Time duration);
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);
bool IsBackoffNotCompleted (Time now);
Time GetDelayUntilAccessGranted (Time now);
Time GetAccessGrantedStart (void) const;
void UpdateBackoff (Time time);
EventId m_accessTimerEvent;
UniformVariable *m_random;
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 */

View File

@@ -17,6 +17,7 @@ def build(bld):
'wifi-mac-trailer.cc',
'mac-parameters.cc',
'mac-low.cc',
'dcf.cc',
]
headers = bld.create_obj('ns3header')
headers.source = [