21 #include "ns3/assert.h"
23 #include "ns3/simulator.h"
26 #include "dcf-manager.h"
34 NS_LOG_DEBUG (Simulator::Now () << " " << this << " " << x)
48 m_accessRequested (false)
52 DcfState::~DcfState ()
62 DcfState::SetCwMin (uint32_t minCw)
68 DcfState::SetCwMax (uint32_t maxCw)
74 DcfState::GetAifsn (
void)
const
79 DcfState::GetCwMin (
void)
const
84 DcfState::GetCwMax (
void)
const
98 m_cw = std::min ( 2 * (m_cw + 1) - 1, m_cwMax);
101 DcfState::UpdateBackoffSlotsNow (uint32_t nSlots,
Time backoffUpdateBound)
103 m_backoffSlots -= nSlots;
104 m_backoffStart = backoffUpdateBound;
105 MY_DEBUG (
"update slots=" << nSlots <<
" slots, backoff=" << m_backoffSlots);
112 MY_DEBUG (
"start backoff=" << nSlots <<
" slots");
113 m_backoffSlots = nSlots;
123 DcfState::GetBackoffSlots (
void)
const
125 return m_backoffSlots;
128 DcfState::GetBackoffStart (
void)
const
130 return m_backoffStart;
135 return m_accessRequested;
138 DcfState::NotifyAccessRequested (
void)
140 m_accessRequested =
true;
143 DcfState::NotifyAccessGranted (
void)
146 m_accessRequested =
false;
147 DoNotifyAccessGranted ();
150 DcfState::NotifyCollision (
void)
152 DoNotifyCollision ();
155 DcfState::NotifyInternalCollision (
void)
157 DoNotifyInternalCollision ();
160 DcfState::NotifyChannelSwitching (Time duration, uint16_t toChannel)
162 DoNotifyChannelSwitching (duration, toChannel);
165 DcfState::NotifyChannelSensing (
void)
167 DoNotifyChannelSensing ();
187 m_dcf->NotifyNavStartNow (duration);
191 m_dcf->NotifyNavResetNow (duration);
193 virtual void AckTimeoutStart (
Time duration)
195 m_dcf->NotifyAckTimeoutStartNow (duration);
197 virtual void AckTimeoutReset ()
199 m_dcf->NotifyAckTimeoutResetNow ();
201 virtual void CtsTimeoutStart (Time duration)
203 m_dcf->NotifyCtsTimeoutStartNow (duration);
205 virtual void CtsTimeoutReset ()
207 m_dcf->NotifyCtsTimeoutResetNow ();
229 m_dcf->NotifyRxStartNow (duration);
233 m_dcf->NotifyRxEndOkNow ();
237 m_dcf->NotifyRxEndErrorNow ();
241 m_dcf->NotifyTxStartNow (duration);
245 m_dcf->NotifyMaybeCcaBusyStartNow (duration);
249 m_dcf->NotifySwitchingStartNow (duration, toChannel);
253 m_dcf->NotifySensingStartNow (duration);
263 DcfManager::DcfManager ()
270 m_lastRxReceivedOk (true),
289 DcfManager::~DcfManager ()
291 delete m_phyListener;
292 delete m_lowListener;
298 DcfManager::SetupPhyListener (Ptr<WifiPhy> phy)
301 m_phyListener =
new PhyListener (
this);
302 phy->RegisterListener (m_phyListener);
305 DcfManager::SetupLowListener (Ptr<MacLow> low)
308 m_lowListener =
new LowDcfListener (
this);
309 low->RegisterDcfListener (m_lowListener);
328 m_eifsNoDifs = eifsNoDifs;
341 m_states.push_back (dcf);
345 DcfManager::MostRecent (
Time a,
Time b)
const
351 DcfManager::MostRecent (Time a, Time b, Time c)
const
356 retval = Max (retval, c);
360 DcfManager::MostRecent (Time a, Time b, Time c, Time d)
const
365 Time retval = Max (e, f);
369 DcfManager::MostRecent (Time a, Time b, Time c, Time d, Time e, Time f)
const
376 Time retval = Max (k, i);
381 DcfManager::MostRecent (Time a, Time b, Time c, Time d, Time e, Time f, Time g, Time h)
const
390 Time retval = Max (m, n);
395 DcfManager::IsBusy (
void)
const
403 Time lastTxEnd = m_lastTxStart + m_lastTxDuration;
409 Time lastNavEnd = m_lastNavStart + m_lastNavDuration;
424 state->NotifyAccessRequested ();
429 if (state->GetBackoffSlots () == 0
432 MY_DEBUG (
"medium is busy: collision");
436 state->NotifyCollision ();
447 for (States::const_iterator i = m_states.begin (); i != m_states.end (); k++)
457 MY_DEBUG (
"dcf " << k <<
" needs access. backoff expired. access granted. slots=" << state->GetBackoffSlots ());
460 std::vector<DcfState *> internalCollisionStates;
461 for (States::const_iterator j = i; j != m_states.end (); j++, k++)
467 MY_DEBUG (
"dcf " << k <<
" needs access. backoff expired. internal collision. slots=" <<
468 otherState->GetBackoffSlots ());
474 internalCollisionStates.push_back (otherState);
485 state->NotifyAccessGranted ();
486 for (std::vector<DcfState *>::const_iterator k = internalCollisionStates.begin ();
487 k != internalCollisionStates.end (); k++)
489 (*k)->NotifyInternalCollision ();
498 DcfManager::AccessTimeout (
void)
513 rxAccessStart = m_lastRxEnd + m_sifs;
514 if (!m_lastRxReceivedOk)
516 rxAccessStart += m_eifsNoDifs;
521 rxAccessStart = m_lastRxStart + m_lastRxDuration + m_sifs;
523 Time busyAccessStart = m_lastBusyStart + m_lastBusyDuration + m_sifs;
524 Time txAccessStart = m_lastTxStart + m_lastTxDuration + m_sifs;
525 Time navAccessStart = m_lastNavStart + m_lastNavDuration + m_sifs;
526 Time ackTimeoutAccessStart = m_lastAckTimeoutEnd + m_sifs;
527 Time ctsTimeoutAccessStart = m_lastCtsTimeoutEnd + m_sifs;
528 Time switchingAccessStart = m_lastSwitchingStart + m_lastSwitchingDuration + m_sifs;
529 Time sensingAccessStart = m_lastSensingStart + m_lastSensingDuration + m_sifs;
530 Time accessGrantedStart = MostRecent (rxAccessStart,
534 ackTimeoutAccessStart,
535 ctsTimeoutAccessStart,
536 switchingAccessStart,
539 NS_LOG_INFO (
"access grant start=" << accessGrantedStart <<
540 ", rx access start=" << rxAccessStart <<
541 ", busy access start=" << busyAccessStart <<
542 ", tx access start=" << txAccessStart <<
543 ", nav access start=" << navAccessStart);
544 return accessGrantedStart;
548 DcfManager::GetBackoffStartFor (
DcfState *state)
551 Time mostRecentEvent = MostRecent (state->GetBackoffStart (),
554 return mostRecentEvent;
558 DcfManager::GetBackoffEndFor (DcfState *state)
560 return GetBackoffStartFor (state) +
MicroSeconds (state->GetBackoffSlots () * m_slotTimeUs);
564 DcfManager::UpdateBackoff (
void)
568 for (States::const_iterator i = m_states.begin (); i != m_states.end (); i++, k++)
570 DcfState *state = *i;
572 Time backoffStart = GetBackoffStartFor (state);
575 uint32_t nus = (
Simulator::Now () - backoffStart).GetMicroSeconds ();
576 uint32_t nIntSlots = nus / m_slotTimeUs;
577 uint32_t n = std::min (nIntSlots, state->GetBackoffSlots ());
578 MY_DEBUG (
"dcf " << k <<
" dec backoff slots=" << n);
579 Time backoffUpdateBound = backoffStart +
MicroSeconds (n * m_slotTimeUs);
580 state->UpdateBackoffSlotsNow (n, backoffUpdateBound);
593 bool accessTimeoutNeeded =
false;
595 for (States::const_iterator i = m_states.begin (); i != m_states.end (); i++)
600 Time tmp = GetBackoffEndFor (state);
603 accessTimeoutNeeded =
true;
604 expectedBackoffEnd = std::min (expectedBackoffEnd, tmp);
608 if (accessTimeoutNeeded)
610 MY_DEBUG (
"expected backoff end=" << expectedBackoffEnd);
615 m_accessTimeout.
Cancel ();
620 &DcfManager::AccessTimeout,
this);
629 MY_DEBUG (
"rx start for=" << duration);
632 m_lastRxDuration = duration;
639 MY_DEBUG (
"rx end ok");
641 m_lastRxReceivedOk =
true;
648 MY_DEBUG (
"rx end error");
650 m_lastRxReceivedOk =
false;
664 m_lastRxDuration = m_lastRxEnd - m_lastRxStart;
665 m_lastRxReceivedOk =
true;
668 MY_DEBUG (
"tx start for " << duration);
671 m_lastTxDuration = duration;
677 MY_DEBUG (
"busy start for " << duration);
680 m_lastBusyDuration = duration;
689 NS_ASSERT (m_lastTxStart + m_lastTxDuration <= now);
690 NS_ASSERT (m_lastSwitchingStart + m_lastSwitchingDuration <= now);
696 m_lastRxDuration = m_lastRxEnd - m_lastRxStart;
697 m_lastRxReceivedOk =
true;
700 if (m_lastNavStart + m_lastNavDuration > now)
702 m_lastNavDuration = now - m_lastNavStart;
704 if (m_lastBusyStart + m_lastBusyDuration > now)
706 m_lastBusyDuration = now - m_lastBusyStart;
708 if (m_lastAckTimeoutEnd > now)
710 m_lastAckTimeoutEnd = now;
712 if (m_lastCtsTimeoutEnd > now)
714 m_lastCtsTimeoutEnd = now;
720 m_accessTimeout.
Cancel ();
724 for (States::iterator i = m_states.begin (); i != m_states.end (); i++)
727 uint32_t remainingSlots = state->GetBackoffSlots ();
728 if (remainingSlots > 0)
730 state->UpdateBackoffSlotsNow (remainingSlots, now);
731 NS_ASSERT (state->GetBackoffSlots () == 0);
734 state->m_accessRequested =
false;
735 state->NotifyChannelSwitching (duration, toChannel);
738 MY_DEBUG (
"switching start for " << duration);
740 m_lastSwitchingDuration = duration;
745 DcfManager::NotifySensingStartNow (
Time duration)
749 NS_ASSERT (m_lastTxStart + m_lastTxDuration <= now);
750 NS_ASSERT (m_lastSensingStart + m_lastSensingDuration <= now);
756 m_lastRxDuration = m_lastRxEnd - m_lastRxStart;
757 m_lastRxReceivedOk =
true;
760 if (m_lastNavStart + m_lastNavDuration > now)
762 m_lastNavDuration = now - m_lastNavStart;
764 if (m_lastBusyStart + m_lastBusyDuration > now)
766 m_lastBusyDuration = now - m_lastBusyStart;
768 if (m_lastAckTimeoutEnd > now)
770 m_lastAckTimeoutEnd = now;
772 if (m_lastCtsTimeoutEnd > now)
774 m_lastCtsTimeoutEnd = now;
780 m_accessTimeout.
Cancel ();
784 for (States::iterator i = m_states.begin (); i != m_states.end (); i++)
786 DcfState *state = *i;
787 uint32_t remainingSlots = state->GetBackoffSlots ();
788 if (remainingSlots > 0)
790 state->UpdateBackoffSlotsNow (remainingSlots, now);
791 NS_ASSERT (state->GetBackoffSlots () == 0);
794 state->m_accessRequested =
false;
795 state->NotifyChannelSensing ();
798 MY_DEBUG (
"sensing start for " << duration);
800 m_lastSensingDuration = duration;
808 MY_DEBUG (
"nav reset for=" << duration);
811 m_lastNavDuration = duration;
826 MY_DEBUG (
"nav start for=" << duration);
829 Time lastNavEnd = m_lastNavStart + m_lastNavDuration;
830 if (newNavEnd > lastNavEnd)
833 m_lastNavDuration = duration;
837 DcfManager::NotifyAckTimeoutStartNow (
Time duration)
844 DcfManager::NotifyAckTimeoutResetNow ()
851 DcfManager::NotifyCtsTimeoutStartNow (Time duration)
857 DcfManager::NotifyCtsTimeoutResetNow ()
static Time GetDelayLeft(const EventId &id)
#define NS_LOG_FUNCTION(parameters)
virtual void NavReset(Time duration)
virtual void NotifySensingStart(Time duration)
virtual void NotifyRxStart(Time duration)
void RequestAccess(DcfState *state)
#define NS_ASSERT(condition)
#define NS_LOG_COMPONENT_DEFINE(name)
void SetAifsn(uint32_t aifsn)
bool IsRunning(void) const
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
virtual void NotifyRxEndOk(void)
void NotifyNavResetNow(Time duration)
void NotifyRxEndOkNow(void)
int64_t GetMicroSeconds(void) const
Time GetAccessGrantStart(void) const
receive notifications about phy events.
void NotifyTxStartNow(Time duration)
virtual void NavStart(Time duration)
Manage a set of ns3::DcfStateHandle a set of independent ns3::DcfState, each of which represents a si...
keep track of the state needed for a single DCF function.Multiple instances of a DcfState can be regi...
bool IsAccessRequested(void) const
void StartBackoffNow(uint32_t nSlots)
virtual void NotifyMaybeCcaBusyStart(Time duration)
void NotifyRxEndErrorNow(void)
void SetEifsNoDifs(Time eifsNoDifs)
listen to NAV eventsThis class is typically connected to an instance of ns3::Dcf and calls to its met...
void NotifyMaybeCcaBusyStartNow(Time duration)
void SetSlot(Time slotTime)
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
void NotifyNavStartNow(Time duration)
uint32_t GetCw(void) const
void NotifyRxStartNow(Time duration)
virtual void NotifySwitchingStart(Time duration, uint16_t toChannel)
Time GetEifsNoDifs() const
virtual void NotifyRxEndError(void)
void DoRestartAccessTimeoutIfNeeded(void)
void UpdateFailedCw(void)
bool IsExpired(void) const
void NotifySwitchingStartNow(Time duration, uint16_t toChannel)
static Time GetMaximumSimulationTime(void)
Time MicroSeconds(uint64_t us)
create ns3::Time instances in units of microseconds.
virtual void NotifyTxStart(Time duration)