21 #include "ns3/assert.h"
22 #include "ns3/packet.h"
24 #include "ns3/simulator.h"
26 #include "ns3/uinteger.h"
27 #include "ns3/pointer.h"
30 #include "dcf-manager.h"
32 #include "wifi-mac-queue.h"
33 #include "mac-tx-middle.h"
34 #include "wifi-mac-trailer.h"
36 #include "random-stream.h"
37 #include "yans-wifi-phy.h"
41 #undef NS_LOG_APPEND_CONTEXT
42 #define NS_LOG_APPEND_CONTEXT if (m_low != 0) { std::clog << "[mac=" << m_low->GetAddress () << "] "; }
46 DcaTxop::ActiveChannels::ActiveChannels(uint16_t channel, Time lastActive)
48 lastActive (lastActive)
62 m_txop->NotifyAccessGranted ();
66 m_txop->NotifyInternalCollision ();
70 m_txop->NotifyCollision ();
76 virtual void DoNotifyChannelSensing (
void)
78 m_txop->NotifyChannelSensing ();
95 m_txop->GotCts (snr, txMode);
103 m_txop->GotAck (snr, txMode);
107 m_txop->MissedAck ();
111 m_txop->StartNext ();
119 m_txop->EndTxNoAck ();
126 NS_OBJECT_ENSURE_REGISTERED (
DcaTxop);
129 DcaTxop::GetTypeId (
void)
134 .AddAttribute (
"Queue",
"The WifiMacQueue object",
136 MakePointerAccessor (&DcaTxop::GetQueue),
137 MakePointerChecker<WifiMacQueue> ())
138 .AddAttribute (
"ChannelActiveTimeout",
139 "After how long should a channel be considered inactive if not used",
141 MakeTimeAccessor (&DcaTxop::m_activeChannelTimeout),
143 .AddAttribute (
"QueueUtilizationInterval",
144 "How long should we transmit on a queue for a specific channel",
146 MakeTimeAccessor (&DcaTxop::m_queueUtilizationTime),
155 m_currentChannel (1),
156 m_switchQueueTimer ()
159 m_transmissionListener =
new DcaTxop::TransmissionListener (
this);
160 m_dcf =
new DcaTxop::Dcf (
this);
161 m_queue = CreateObject<WifiMacQueue> ();
162 m_rng =
new RealRandomStream ();
163 m_txMiddle =
new MacTxMiddle ();
169 m_switchQueueTimer.
Cancel();
178 m_stationManager = 0;
179 delete m_transmissionListener;
183 m_transmissionListener = 0;
194 m_manager->
Add (m_dcf);
198 DcaTxop::SetLow (Ptr<MacLow> low)
204 DcaTxop::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> remoteManager)
207 m_stationManager = remoteManager;
213 m_txOkCallback = callback;
219 m_txFailedCallback = callback;
223 DcaTxop::GetQueue ()
const
230 DcaTxop::SetMinCw (uint32_t minCw)
233 m_dcf->SetCwMin (minCw);
236 DcaTxop::SetMaxCw (uint32_t maxCw)
239 m_dcf->SetCwMax (maxCw);
242 DcaTxop::SetAifsn (uint32_t aifsn)
248 DcaTxop::GetMinCw (
void)
const
251 return m_dcf->GetCwMin ();
254 DcaTxop::GetMaxCw (
void)
const
257 return m_dcf->GetCwMax ();
260 DcaTxop::GetAifsn (
void)
const
263 return m_dcf->GetAifsn ();
272 m_stationManager->PrepareForQueue (hdr.GetAddr1 (), &hdr,
273 packet, fullPacketSize);
275 bool found = packet->PeekPacketTag(pcpt);
276 NS_LOG_LOGIC (
"Enqueue packet to channel : " << pcpt.GetChannel() <<
277 " current channel: " << m_low->GetPhy()->GetChannelNumber());
280 if (m_low->IsTxRadio() && m_low->GetPhy()->GetChannelNumber() == 1)
282 NS_LOG_LOGIC (
"Switch PHY to channel: " << pcpt.GetChannel());
283 m_low->GetPhy()->SetChannelNumber(pcpt.GetChannel());
286 m_queue->Enqueue (packet, hdr);
287 if (pcpt.GetChannel()!=1 && pcpt.GetChannel()!=0 &&
289 UpdateActiveChannels(pcpt.GetChannel());
291 if (!m_switchQueueTimer.
IsRunning() && m_low->IsTxRadio ())
294 &DcaTxop::SwitchQueueHandler,
this);
296 StartAccessIfNeeded ();
300 DcaTxop::UpdateActiveChannels(uint16_t channel)
304 if (m_activeChannels.empty())
311 ListActiveChannelsI it;
312 for (it = m_activeChannels.begin (); it != m_activeChannels.end (); ++it)
314 uint16_t chan = it->channel;
326 m_activeChannels.push_back(DcaTxop::ActiveChannels(channel,
Simulator::Now()));
331 DcaTxop::GetNextActiveChannel (
void)
334 if (!m_activeChannels.empty() && m_activeChannels.size()!=1)
336 ListActiveChannelsI it;
337 ListActiveChannelsI startIterator;
338 bool startLooking =
false;
339 bool keepRunning =
true;
340 while (keepRunning) {
342 it = m_activeChannels.begin();
343 long unsigned int count = 0;
344 while (it != startIterator)
347 if (it->channel == m_currentChannel && !startLooking)
356 && it->channel != m_currentChannel)
359 NS_LOG_LOGIC (
"Disabling channel " << it->channel <<
" usage in TX radio");
360 m_activeChannels.erase(it);
361 if (m_activeChannels.size() == 1)
return m_currentChannel;
365 else if ( it->channel != m_currentChannel )
368 NS_LOG_LOGIC (
"Found next active channel " << it->channel);
374 if (count == m_activeChannels.size()) {
375 it = m_activeChannels.begin();
384 return m_currentChannel;
399 if ((m_currentPacket != 0
400 || !m_queue->IsEmpty (m_currentChannel))
408 DcaTxop::StartAccessIfNeeded (
void)
411 if (m_currentPacket == 0
412 && !m_queue->IsEmpty (m_currentChannel)
428 DcaTxop::NeedRts (Ptr<const Packet> packet,
const WifiMacHeader *header)
431 return m_stationManager->NeedRts (header->GetAddr1 (), header,
441 m_currentChannel = m_low->GetPhy()->GetChannelNumber();
445 DcaTxop::NeedRtsRetransmission (
void)
448 return m_stationManager->NeedRtsRetransmission (m_currentHdr.GetAddr1 (), &m_currentHdr,
453 DcaTxop::NeedDataRetransmission (
void)
456 return m_stationManager->NeedDataRetransmission (m_currentHdr.GetAddr1 (), &m_currentHdr,
460 DcaTxop::NeedFragmentation (
void)
463 return m_stationManager->NeedFragmentation (m_currentHdr.GetAddr1 (), &m_currentHdr,
468 DcaTxop::NextFragment (
void)
475 DcaTxop::GetFragmentSize (
void)
478 return m_stationManager->GetFragmentSize (m_currentHdr.GetAddr1 (), &m_currentHdr,
479 m_currentPacket, m_fragmentNumber);
482 DcaTxop::IsLastFragment (
void)
485 return m_stationManager->IsLastFragment (m_currentHdr.GetAddr1 (), &m_currentHdr,
486 m_currentPacket, m_fragmentNumber);
490 DcaTxop::GetNextFragmentSize (
void)
493 return m_stationManager->GetFragmentSize (m_currentHdr.GetAddr1 (), &m_currentHdr,
494 m_currentPacket, m_fragmentNumber + 1);
498 DcaTxop::GetFragmentOffset (
void)
501 return m_stationManager->GetFragmentOffset (m_currentHdr.GetAddr1 (), &m_currentHdr,
502 m_currentPacket, m_fragmentNumber);
506 DcaTxop::GetFragmentPacket (WifiMacHeader *hdr)
510 hdr->SetFragmentNumber (m_fragmentNumber);
511 uint32_t startOffset = GetFragmentOffset ();
512 Ptr<Packet> fragment;
513 if (IsLastFragment ())
515 hdr->SetNoMoreFragments ();
519 hdr->SetMoreFragments ();
527 DcaTxop::NeedsAccess (
void)
const
530 return !m_queue->IsEmpty (m_currentChannel) || m_currentPacket != 0;
533 DcaTxop::NotifyAccessGranted (
void)
536 if (m_currentPacket == 0)
538 if (m_queue->IsEmpty (m_currentChannel))
543 m_currentPacket = m_queue->DequeueForChannel (&m_currentHdr, m_currentChannel);
545 uint16_t sequence = m_txMiddle->GetNextSequenceNumberfor (&m_currentHdr);
546 m_currentHdr.SetSequenceNumber (sequence);
547 m_currentHdr.SetFragmentNumber (0);
548 m_currentHdr.SetNoMoreFragments ();
549 m_currentHdr.SetNoRetry ();
550 m_fragmentNumber = 0;
552 ", to=" << m_currentHdr.GetAddr1 () <<
553 ", seq=" << m_currentHdr.GetSequenceControl ());
555 MacLowTransmissionParameters params;
556 params.DisableOverrideDurationId ();
557 if (m_currentHdr.GetAddr1 ().
IsGroup ())
559 params.DisableRts ();
560 params.DisableAck ();
561 params.DisableNextData ();
562 Low ()->StartTransmission (m_currentPacket,
565 m_transmissionListener);
572 if (NeedFragmentation ())
575 Ptr<Packet> fragment = GetFragmentPacket (&hdr);
576 if (NeedRts (fragment, &hdr))
582 params.DisableRts ();
584 if (IsLastFragment ())
586 NS_LOG_DEBUG (
"fragmenting last fragment size=" << fragment->GetSize ());
587 params.DisableNextData ();
591 NS_LOG_DEBUG (
"fragmenting size=" << fragment->GetSize ());
592 params.EnableNextData (GetNextFragmentSize ());
594 Low ()->StartTransmission (fragment, &hdr, params,
595 m_transmissionListener);
599 if (NeedRts (m_currentPacket, &m_currentHdr))
606 params.DisableRts ();
609 params.DisableNextData ();
610 Low ()->StartTransmission (m_currentPacket, &m_currentHdr,
611 params, m_transmissionListener);
617 DcaTxop::NotifyInternalCollision (
void)
623 DcaTxop::NotifyCollision (
void)
635 m_currentChannel = toChannel;
640 DcaTxop::NotifyChannelSensing (
void)
647 DcaTxop::GotCts (
double snr, WifiMode txMode)
653 DcaTxop::MissedCts (
void)
657 if (!NeedRtsRetransmission ())
660 m_stationManager->ReportFinalRtsFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
661 if (!m_txFailedCallback.IsNull ())
663 m_txFailedCallback (m_currentHdr);
677 DcaTxop::GotAck (
double snr, WifiMode txMode)
680 if (!NeedFragmentation ()
681 || IsLastFragment ())
684 if (!m_txOkCallback.IsNull ())
686 m_txOkCallback (m_currentHdr);
703 DcaTxop::MissedAck (
void)
707 if (!NeedDataRetransmission ())
710 m_stationManager->ReportFinalDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
711 if (!m_txFailedCallback.IsNull ())
713 m_txFailedCallback (m_currentHdr);
722 m_currentHdr.SetRetry ();
729 DcaTxop::StartNext (
void)
736 Ptr<Packet> fragment = GetFragmentPacket (&hdr);
737 MacLowTransmissionParameters params;
739 params.DisableRts ();
740 params.DisableOverrideDurationId ();
741 if (IsLastFragment ())
743 params.DisableNextData ();
747 params.EnableNextData (GetNextFragmentSize ());
749 Low ()->StartTransmission (fragment, &hdr, params, m_transmissionListener);
785 DcaTxop::EndTxNoAck (
void)
788 NS_LOG_DEBUG (
"a transmission that did not require an ACK just finished");
792 StartAccessIfNeeded ();
796 DcaTxop::SwitchQueueHandler (
void)
800 uint16_t channel = GetNextActiveChannel();
801 Time nextQueueSwitch = m_queueUtilizationTime;
802 if (m_currentChannel != channel)
805 NS_LOG_DEBUG (
"Queue switching on TX radio from channel "
806 << m_currentChannel <<
" to channel " << channel);
808 m_low->GetPhy()->SetChannelNumber(channel);
810 m_currentChannel = channel;
812 nextQueueSwitch = nextQueueSwitch + m_low->GetPhy()->GetDelayUntilIdle();
814 Ptr<YansWifiPhy> phy = DynamicCast<YansWifiPhy>(m_low->GetPhy());
815 if (phy->GetDelayUntilIdle()<phy->GetSwitchingDelay())
816 nextQueueSwitch = nextQueueSwitch + phy->GetSwitchingDelay();
822 &DcaTxop::SwitchQueueHandler,
this);
smart pointer class similar to boost::intrusive_ptr
#define NS_LOG_FUNCTION(parameters)
TypeId AddConstructor(void)
virtual void DoNotifyInternalCollision(void)
void SetTxFailedCallback(TxFailed callback)
virtual void MissedAck(void)
void RequestAccess(DcfState *state)
#define NS_ASSERT(condition)
virtual int64_t AssignStreams(int64_t stream)=0
#define NS_LOG_COMPONENT_DEFINE(name)
uint32_t GetSize(void) const
void SetAifsn(uint32_t aifsn)
bool IsRunning(void) const
int64_t AssignStreams(int64_t stream)
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
listen to events coming from ns3::MacLow.
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
virtual void GotCts(double snr, WifiMode txMode)
void SetTxOkCallback(TxOk callback)
virtual void GotAck(double snr, WifiMode txMode)
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
void Queue(Ptr< const Packet > packet, const WifiMacHeader &hdr)
hold objects of type ns3::Time
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
#define NS_LOG_LOGIC(msg)
void StartBackoffNow(uint32_t nSlots)
void NotifyChannelSwitching(Time duration, uint16_t toChannel)
hold objects of type Ptr<T>
virtual void EndTxNoAck(void)
virtual void Cancel(void)
virtual void MissedCts(void)
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
virtual void DoNotifyCollision(void)
uint32_t GetCw(void) const
#define NS_LOG_DEBUG(msg)
virtual void StartNext(void)
virtual void DoDispose(void)
Time MilliSeconds(uint64_t ms)
create ns3::Time instances in units of milliseconds.
virtual void DoNotifyAccessGranted(void)
void RestartAccessIfNeeded(void)
virtual void DoNotifyChannelSwitching(Time duration, uint16_t toChannel)
void UpdateFailedCw(void)
handle packet fragmentation and retransmissions.This class implements the packet fragmentation and re...
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
virtual void DoInitialize(void)
virtual uint32_t GetSerializedSize(void) const