From 24a0b73ce3cee1da89513c64e5fd8c8aafce3124 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Tue, 9 Oct 2007 12:42:45 +0200 Subject: [PATCH] add DcaTxop to build --- src/devices/wifi/dca-txop.cc | 575 +++++++++++++++++++++++++++++++++++ src/devices/wifi/dca-txop.h | 129 ++++++++ src/devices/wifi/wscript | 1 + 3 files changed, 705 insertions(+) create mode 100644 src/devices/wifi/dca-txop.cc create mode 100644 src/devices/wifi/dca-txop.h diff --git a/src/devices/wifi/dca-txop.cc b/src/devices/wifi/dca-txop.cc new file mode 100644 index 000000000..d5bb6e46c --- /dev/null +++ b/src/devices/wifi/dca-txop.cc @@ -0,0 +1,575 @@ +/* -*- 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 + */ + +#include + +#include "ns3/packet.h" + +#include "dca-txop.h" +#include "dcf.h" +#include "mac-parameters.h" +#include "mac-low.h" +#include "wifi-mac-queue.h" +#include "mac-tx-middle.h" +#include "wifi-phy.h" + + + +#define noDCA_TXOP_TRACE 1 + +#ifdef DCA_TXOP_TRACE +#include "ns3/simulator.h" +#include +# define TRACE(x) \ + std::cout <<"DCA TXOP now="<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); + } +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 NotifyTxStart (Time duration) { + m_dcf->NotifyTxStartNow (duration); + } + virtual void NotifyCcaBusyStart (Time duration) { + m_dcf->NotifyCcaBusyStartNow (duration); + } +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 (); + } + +private: + DcaTxop *m_txop; +}; + +class DcaTxop::TransmissionListener : public MacLowTransmissionListener { +public: + TransmissionListener (DcaTxop *txop) + : MacLowTransmissionListener (), + m_txop (txop) {} + + virtual ~TransmissionListener () {} + + virtual void GotCts (double snr, WifiMode txMode) { + m_txop->GotCts (snr, txMode); + } + virtual void MissedCts (void) { + m_txop->MissedCts (); + } + virtual void GotAck (double snr, WifiMode txMode) { + m_txop->GotAck (snr, txMode); + } + virtual void MissedAck (void) { + m_txop->MissedAck (); + } + virtual void StartNext (void) { + m_txop->StartNext (); + } + + virtual void Cancel (void) { + assert (false); + } + +private: + DcaTxop *m_txop; +}; + +DcaTxop::DcaTxop () + : m_accessListener (0), + m_hasCurrent (false), + m_ssrc (0), + m_slrc (0) +{ + m_transmissionListener = new DcaTxop::TransmissionListener (this); + m_dcf = new Dcf (); + m_accessListener = new DcaTxop::AccessListener (this); + m_dcf->RegisterAccessListener (m_accessListener); + m_queue = new WifiMacQueue (); +} + +DcaTxop::~DcaTxop () +{ + delete m_accessListener; + delete m_transmissionListener; + delete m_navListener; + delete m_phyListener; + delete m_queue; +} + +void +DcaTxop::SetLow (MacLow *low) +{ + m_low = low; + m_navListener = new DcaTxop::NavListener (m_dcf); + m_low->RegisterNavListener (m_navListener); +} +void +DcaTxop::SetPhy (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) +{ + m_txMiddle = txMiddle; +} +void +DcaTxop::SetTxOkCallback (TxOk callback) +{ + m_txOkCallback = callback; +} +void +DcaTxop::SetTxFailedCallback (TxFailed callback) +{ + m_txFailedCallback = callback; +} + +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); +} +void +DcaTxop::SetMaxQueueDelay (Time delay) +{ + m_queue->SetMaxDelay (delay); +} + +void +DcaTxop::Queue (Packet packet, WifiMacHeader const &hdr) +{ + m_queue->Enqueue (packet, hdr); + m_dcf->RequestAccess (); +} + + +MacLow * +DcaTxop::Low (void) +{ + return m_low; +} + +MacParameters * +DcaTxop::Parameters (void) +{ + return m_parameters; +} + + +bool +DcaTxop::NeedRts (void) +{ + if (m_currentPacket.GetSize () > Parameters ()->GetRtsCtsThreshold ()) + { + return true; + } + else + { + return false; + } +} + +bool +DcaTxop::NeedFragmentation (void) +{ + if (m_currentPacket.GetSize () > Parameters ()->GetFragmentationThreshold ()) + { + return true; + } + else + { + return false; + } +} + +uint32_t +DcaTxop::GetNFragments (void) +{ + uint32_t nFragments = m_currentPacket.GetSize () / Parameters ()->GetFragmentationThreshold () + 1; + return nFragments; +} +void +DcaTxop::NextFragment (void) +{ + m_fragmentNumber++; +} + +uint32_t +DcaTxop::GetLastFragmentSize (void) +{ + uint32_t lastFragmentSize = m_currentPacket.GetSize () % + Parameters ()->GetFragmentationThreshold (); + return lastFragmentSize; +} + +uint32_t +DcaTxop::GetFragmentSize (void) +{ + return Parameters ()->GetFragmentationThreshold (); +} +bool +DcaTxop::IsLastFragment (void) +{ + if (m_fragmentNumber == (GetNFragments () - 1)) + { + return true; + } + else + { + return false; + } +} + +uint32_t +DcaTxop::GetNextFragmentSize (void) +{ + if (IsLastFragment ()) + { + return 0; + } + + uint32_t nextFragmentNumber = m_fragmentNumber + 1; + if (nextFragmentNumber == (GetNFragments () - 1)) + { + return GetLastFragmentSize (); + } + else + { + return GetFragmentSize (); + } +} + +Packet +DcaTxop::GetFragmentPacket (WifiMacHeader *hdr) +{ + *hdr = m_currentHdr; + hdr->SetFragmentNumber (m_fragmentNumber); + uint32_t startOffset = m_fragmentNumber * GetFragmentSize (); + Packet fragment; + if (IsLastFragment ()) + { + hdr->SetNoMoreFragments (); + fragment = m_currentPacket.CreateFragment (startOffset, + GetLastFragmentSize ()); + } + else + { + hdr->SetMoreFragments (); + fragment = m_currentPacket.CreateFragment (startOffset, + GetFragmentSize ()); + } + return fragment; +} + +bool +DcaTxop::AccessingAndWillNotify (void) +{ + if (m_hasCurrent) + { + return true; + } + else + { + return false; + } +} + +bool +DcaTxop::AccessNeeded (void) +{ + if (!m_queue->IsEmpty () || + m_hasCurrent) + { + TRACE ("access needed here"); + return true; + } + else + { + TRACE ("no access needed here"); + return false; + } +} + +void +DcaTxop::AccessGrantedNow (void) +{ + if (!m_hasCurrent) + { + if (m_queue->IsEmpty ()) + { + TRACE ("queue empty"); + return; + } + bool found; + m_currentPacket = m_queue->Dequeue (&m_currentHdr, &found); + assert (found); + m_hasCurrent = true; + assert (m_hasCurrent); + uint16_t sequence = m_txMiddle->GetNextSequenceNumberfor (&m_currentHdr); + m_currentHdr.SetSequenceNumber (sequence); + m_currentHdr.SetFragmentNumber (0); + m_currentHdr.SetNoMoreFragments (); + m_ssrc = 0; + m_slrc = 0; + m_fragmentNumber = 0; + TRACE ("dequeued size="<StartTransmission (copy, &m_currentHdr, + params, m_transmissionListener); + } + } +} + + +void +DcaTxop::GotCts (double snr, WifiMode txMode) +{ + TRACE ("got cts"); + m_ssrc = 0; +} +void +DcaTxop::MissedCts (void) +{ + TRACE ("missed cts"); + m_ssrc++; + m_ctstimeoutTrace (m_ssrc); + if (m_ssrc > Parameters ()->GetMaxSsrc ()) + { + // to reset the dcf. + m_dcf->ResetCw (); + m_dcf->StartBackoff (); + m_hasCurrent = false; + } + else + { + m_dcf->UpdateFailedCw (); + m_dcf->StartBackoff (); + } +} +void +DcaTxop::GotAck (double snr, WifiMode txMode) +{ + m_slrc = 0; + if (!NeedFragmentation () || + IsLastFragment ()) + { + TRACE ("got ack. tx done."); + if (!m_txOkCallback.IsNull ()) + { + m_txOkCallback (m_currentHdr); + } + + /* we are not fragmenting or we are done fragmenting + * so we can get rid of that packet now. + */ + m_hasCurrent = false; + m_dcf->ResetCw (); + m_dcf->StartBackoff (); + } + else + { + TRACE ("got ack. tx not done, size="< Parameters ()->GetMaxSlrc ()) + { + // to reset the dcf. + m_dcf->ResetCw (); + m_dcf->StartBackoff (); + m_hasCurrent = false; + } + else + { + // XXX + //SetRetry (m_currentTxPacket); + if (!m_txFailedCallback.IsNull ()) + { + m_txFailedCallback (m_currentHdr); + } + m_dcf->UpdateFailedCw (); + m_dcf->StartBackoff (); + } + +} +void +DcaTxop::StartNext (void) +{ + TRACE ("start next packet fragment"); + /* this callback is used only for fragments. */ + NextFragment (); + WifiMacHeader hdr; + Packet fragment = GetFragmentPacket (&hdr); + MacLowTransmissionParameters params; + params.EnableAck (); + params.DisableRts (); + params.DisableOverrideDurationId (); + if (IsLastFragment ()) + { + params.DisableNextData (); + } + else + { + params.EnableNextData (GetNextFragmentSize ()); + } + Low ()->StartTransmission (fragment, &hdr, params, m_transmissionListener); +} + +} // namespace ns3 diff --git a/src/devices/wifi/dca-txop.h b/src/devices/wifi/dca-txop.h new file mode 100644 index 000000000..6e443b8b2 --- /dev/null +++ b/src/devices/wifi/dca-txop.h @@ -0,0 +1,129 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005 INRIA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ + +#ifndef DCA_TXOP_H +#define DCA_TXOP_H + +#include +#include "ns3/callback.h" +#include "ns3/packet.h" +#include "ns3/callback-trace-source.h" +#include "ns3/nstime.h" +#include "wifi-mac-header.h" +#include "wifi-mode.h" + +namespace ns3 { + +class Dcf; +class WifiMacQueue; +class MacLow; +class WifiPhy; +class MacParameters; +class MacTxMiddle; + +class DcaTxop +{ +public: + typedef Callback TxOk; + typedef Callback TxFailed; + + DcaTxop (); + ~DcaTxop (); + + void SetLow (MacLow *low); + void SetPhy (WifiPhy *phy); + void SetParameters (MacParameters *parameters); + void SetTxMiddle (MacTxMiddle *txMiddle); + void SetTxOkCallback (TxOk callback); + 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); + + void Queue (Packet packet, WifiMacHeader const &hdr); +private: + class AccessListener; + class TransmissionListener; + class NavListener; + class PhyListener; + friend class AccessListener; + friend class TransmissionListener; + + MacLow *Low (void); + MacParameters *Parameters (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); + void MissedAck (void); + void StartNext (void); + + bool NeedRts (void); + bool NeedFragmentation (void); + uint32_t GetNFragments (void); + uint32_t GetLastFragmentSize (void); + uint32_t GetNextFragmentSize (void); + uint32_t GetFragmentSize (void); + bool IsLastFragment (void); + void NextFragment (void); + Packet GetFragmentPacket (WifiMacHeader *hdr); + + Dcf *m_dcf; + TxOk m_txOkCallback; + TxFailed m_txFailedCallback; + WifiMacQueue *m_queue; + MacTxMiddle *m_txMiddle; + MacLow *m_low; + MacParameters *m_parameters; + TransmissionListener *m_transmissionListener; + AccessListener *m_accessListener; + NavListener *m_navListener; + PhyListener *m_phyListener; + + + Packet m_currentPacket; + bool m_hasCurrent; + WifiMacHeader m_currentHdr; + uint32_t m_ssrc; + uint32_t m_slrc; + uint8_t m_fragmentNumber; + + /* 80211-dca-acktimeout + * param1: slrc + */ + CallbackTraceSource m_acktimeoutTrace; + /* 80211-dca-ctstimeout + * param1: ssrc + */ + CallbackTraceSource m_ctstimeoutTrace; +}; + +} //namespace ns3 + + + +#endif /* DCA_TXOP_H */ diff --git a/src/devices/wifi/wscript b/src/devices/wifi/wscript index f0af5f073..58fc1c1b1 100644 --- a/src/devices/wifi/wscript +++ b/src/devices/wifi/wscript @@ -21,6 +21,7 @@ def build(bld): 'wifi-mac-queue.cc', 'mac-tx-middle.cc', 'mac-rx-middle.cc', + 'dca-txop.cc', ] headers = bld.create_obj('ns3header') headers.source = [