From 8a94aee8aa38fd59bb858642411b456df281e8bf Mon Sep 17 00:00:00 2001 From: Mirko Banchi Date: Fri, 24 Apr 2009 10:21:37 +0200 Subject: [PATCH] add qos MACs --- examples/simple-wifi-frame-aggregation.cc | 151 ++++ examples/wscript | 4 + src/devices/wifi/amsdu-subframe-header.cc | 116 +++ src/devices/wifi/amsdu-subframe-header.h | 57 ++ src/devices/wifi/edca-txop-n.cc | 691 ++++++++++++++++ src/devices/wifi/edca-txop-n.h | 170 ++++ src/devices/wifi/msdu-aggregator.cc | 78 ++ src/devices/wifi/msdu-aggregator.h | 55 ++ src/devices/wifi/msdu-standard-aggregator.cc | 86 ++ src/devices/wifi/msdu-standard-aggregator.h | 56 ++ src/devices/wifi/qadhoc-wifi-mac.cc | 441 +++++++++++ src/devices/wifi/qadhoc-wifi-mac.h | 120 +++ src/devices/wifi/qap-wifi-mac.cc | 790 +++++++++++++++++++ src/devices/wifi/qap-wifi-mac.h | 145 ++++ src/devices/wifi/qsta-wifi-mac.cc | 768 ++++++++++++++++++ src/devices/wifi/qsta-wifi-mac.h | 168 ++++ src/devices/wifi/wscript | 16 +- src/helper/qos-wifi-mac-helper.cc | 191 +++++ src/helper/qos-wifi-mac-helper.h | 123 +++ src/helper/wscript | 2 + 20 files changed, 4227 insertions(+), 1 deletion(-) create mode 100644 examples/simple-wifi-frame-aggregation.cc create mode 100644 src/devices/wifi/amsdu-subframe-header.cc create mode 100644 src/devices/wifi/amsdu-subframe-header.h create mode 100644 src/devices/wifi/edca-txop-n.cc create mode 100644 src/devices/wifi/edca-txop-n.h create mode 100644 src/devices/wifi/msdu-aggregator.cc create mode 100644 src/devices/wifi/msdu-aggregator.h create mode 100644 src/devices/wifi/msdu-standard-aggregator.cc create mode 100644 src/devices/wifi/msdu-standard-aggregator.h create mode 100644 src/devices/wifi/qadhoc-wifi-mac.cc create mode 100644 src/devices/wifi/qadhoc-wifi-mac.h create mode 100644 src/devices/wifi/qap-wifi-mac.cc create mode 100644 src/devices/wifi/qap-wifi-mac.h create mode 100644 src/devices/wifi/qsta-wifi-mac.cc create mode 100644 src/devices/wifi/qsta-wifi-mac.h create mode 100644 src/helper/qos-wifi-mac-helper.cc create mode 100644 src/helper/qos-wifi-mac-helper.h diff --git a/examples/simple-wifi-frame-aggregation.cc b/examples/simple-wifi-frame-aggregation.cc new file mode 100644 index 000000000..765b108ca --- /dev/null +++ b/examples/simple-wifi-frame-aggregation.cc @@ -0,0 +1,151 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 MIRKO BANCHI + * + * 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: Mirko Banchi + */ +#include "ns3/core-module.h" +#include "ns3/simulator-module.h" +#include "ns3/node-module.h" +#include "ns3/helper-module.h" +#include "ns3/global-routing-module.h" +#include "ns3/wifi-module.h" +#include "ns3/mobility-module.h" + +//This is a simple example in order to show how 802.11n frame aggregation feature (A-MSDU) works. +// +//Network topology: +// +// Wifi 192.168.1.0 +// +// AP +// * * * +// | | | +// n1 n2 n3 +// +//Packets in this simulation aren't marked with a QosTag so they are considered +//belonging to BestEffort Access Class (AC_BE). + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("SimpleWifiFrameAggregation"); + +int main (int argc, char *argv[]) +{ + //LogComponentEnable ("EdcaTxopN", LOG_LEVEL_DEBUG); + LogComponentEnable ("MsduAggregator", LOG_LEVEL_INFO); + LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO); + LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO); + + uint32_t nWifi = 1; + CommandLine cmd; + cmd.AddValue ("nWifi", "Number of wifi STA devices", nWifi); + cmd.Parse (argc,argv); + + NodeContainer wifiNodes; + wifiNodes.Create (2); + NodeContainer wifiApNode; + wifiApNode.Create (1); + + YansWifiChannelHelper channel = YansWifiChannelHelper::Default (); + YansWifiPhyHelper phy = YansWifiPhyHelper::Default (); + phy.SetChannel (channel.Create ()); + + WifiHelper wifi = WifiHelper::Default (); + QosWifiMacHelper mac = QosWifiMacHelper::Default (); + wifi.SetRemoteStationManager ("ns3::AarfWifiManager", "FragmentationThreshold", UintegerValue (2500)); + + Ssid ssid = Ssid ("ns-3-802.11n"); + mac.SetType ("ns3::QstaWifiMac", + "Ssid", SsidValue (ssid), + "ActiveProbing", BooleanValue (false)); + mac.SetMsduAggregatorForAc (AC_BE, "ns3::MsduStandardAggregator", + "MaxAmsduSize", UintegerValue (3839)); + + NetDeviceContainer staDevices; + staDevices = wifi.Install (phy, mac, wifiNodes); + + mac.SetType ("ns3::QapWifiMac", + "Ssid", SsidValue (ssid), + "BeaconGeneration", BooleanValue (true), + "BeaconInterval", TimeValue (Seconds (2.5))); + mac.SetMsduAggregatorForAc (AC_BE, "ns3::MsduStandardAggregator", + "MaxAmsduSize", UintegerValue (7935)); + + NetDeviceContainer apDevice; + apDevice = wifi.Install (phy, mac, wifiApNode); + + /* Setting mobility model */ + MobilityHelper mobility; + + mobility.SetPositionAllocator ("ns3::GridPositionAllocator", + "MinX", DoubleValue (0.0), + "MinY", DoubleValue (0.0), + "DeltaX", DoubleValue (5.0), + "DeltaY", DoubleValue (10.0), + "GridWidth", UintegerValue (3), + "LayoutType", StringValue ("RowFirst")); + + mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel", + "Bounds", RectangleValue (Rectangle (-50, 50, -50, 50))); + mobility.Install (wifiNodes); + + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (wifiApNode); + + /* Internet stack*/ + InternetStackHelper stack; + stack.Install (wifiApNode); + stack.Install (wifiNodes); + + Ipv4AddressHelper address; + + address.SetBase ("192.168.1.0", "255.255.255.0"); + Ipv4InterfaceContainer wifiNodesInterfaces; + Ipv4InterfaceContainer apNodeInterface; + + wifiNodesInterfaces = address.Assign (staDevices); + apNodeInterface = address.Assign (apDevice); + + /* Setting applications */ + UdpEchoServerHelper echoServer (9); + + ApplicationContainer serverApps = echoServer.Install (wifiNodes.Get (1)); + serverApps.Start (Seconds (1.0)); + serverApps.Stop (Seconds (10.0)); + + UdpEchoClientHelper echoClient (wifiNodesInterfaces.GetAddress (1), 9); + echoClient.SetAttribute ("MaxPackets", UintegerValue (3)); + echoClient.SetAttribute ("Interval", TimeValue (Seconds (0.000001))); + echoClient.SetAttribute ("PacketSize", UintegerValue (1500)); + + ApplicationContainer clientApps = + echoClient.Install (wifiNodes.Get (0)); + clientApps.Start (Seconds (2.0)); + clientApps.Stop (Seconds (10.0)); + + GlobalRouteManager::PopulateRoutingTables (); + + Simulator::Stop (Seconds (10.0)); + + YansWifiPhyHelper::EnablePcap ("test-802.11n", + wifiNodes.Get (nWifi - 1)->GetId (), 0); + + Simulator::Run (); + Simulator::Destroy (); + + return 0; +} diff --git a/examples/wscript b/examples/wscript index f56a6e8e0..a324e865a 100644 --- a/examples/wscript +++ b/examples/wscript @@ -149,3 +149,7 @@ def build(bld): obj = bld.create_ns3_program('tap-wifi-dumbbell', ['wifi', 'csma', 'point-to-point', 'tap-bridge', 'internet-stack']) obj.source = 'tap-wifi-dumbbell.cc' + + obj = bld.create_ns3_program('simple-wifi-frame-aggregation', + ['core', 'simulator', 'mobility', 'wifi']) + obj.source = 'simple-wifi-frame-aggregation.cc' diff --git a/src/devices/wifi/amsdu-subframe-header.cc b/src/devices/wifi/amsdu-subframe-header.cc new file mode 100644 index 000000000..f30278bf3 --- /dev/null +++ b/src/devices/wifi/amsdu-subframe-header.cc @@ -0,0 +1,116 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 MIRKO BANCHI + * + * 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: Mirko Banchi + */ +#include "amsdu-subframe-header.h" +#include "ns3/address-utils.h" + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (AmsduSubframeHeader); + +TypeId +AmsduSubframeHeader::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::AmsduSubframeHeader") + .SetParent
() + .AddConstructor () + ; + return tid; +} + +TypeId +AmsduSubframeHeader::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +AmsduSubframeHeader::AmsduSubframeHeader () + : m_length (0) +{} + +AmsduSubframeHeader::~AmsduSubframeHeader () +{} + +uint32_t +AmsduSubframeHeader::GetSerializedSize () const +{ + return (6 + 6 + 2); +} + +void +AmsduSubframeHeader::Serialize (Buffer::Iterator i) const +{ + WriteTo (i, m_da); + WriteTo (i, m_sa); + i.WriteHtonU16 (m_length); +} + +uint32_t +AmsduSubframeHeader::Deserialize (Buffer::Iterator start) +{ + Buffer::Iterator i = start; + ReadFrom (i, m_da); + ReadFrom (i, m_sa); + m_length = i.ReadNtohU16 (); + return i.GetDistanceFrom (start); +} + +void +AmsduSubframeHeader::Print (std::ostream &os) const +{ + os << "DA = " << m_da << ", SA = " << m_sa << ", length = " << m_length; +} + +void +AmsduSubframeHeader::SetDestinationAddr (Mac48Address to) +{ + m_da = to; +} + +void +AmsduSubframeHeader::SetSourceAddr (Mac48Address from) +{ + m_sa = from; +} + +void +AmsduSubframeHeader::SetLength (uint16_t length) +{ + m_length = length; +} + +Mac48Address +AmsduSubframeHeader::GetDestinationAddr (void) const +{ + return m_da; +} + +Mac48Address +AmsduSubframeHeader::GetSourceAddr (void) const +{ + return m_sa; +} + +uint16_t +AmsduSubframeHeader::GetLength (void) const +{ + return m_length; +} + +} //namespace ns3 diff --git a/src/devices/wifi/amsdu-subframe-header.h b/src/devices/wifi/amsdu-subframe-header.h new file mode 100644 index 000000000..a19dfcc77 --- /dev/null +++ b/src/devices/wifi/amsdu-subframe-header.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 MIRKO BANCHI + * + * 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: Mirko Banchi + */ +#ifndef AMSDU_SUBFRAME_HEADER_H +#define AMSDU_SUBFRAME_HEADER_H + +#include "ns3/header.h" +#include "ns3/mac48-address.h" + +namespace ns3 { + +class AmsduSubframeHeader : public Header +{ +public: + + AmsduSubframeHeader (); + virtual ~AmsduSubframeHeader (); + + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual void Print (std::ostream &os) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (Buffer::Iterator start) const; + virtual uint32_t Deserialize (Buffer::Iterator start); + + void SetDestinationAddr (Mac48Address to); + void SetSourceAddr (Mac48Address to); + void SetLength (uint16_t); + Mac48Address GetDestinationAddr (void) const; + Mac48Address GetSourceAddr (void) const; + uint16_t GetLength (void) const; + +private: + Mac48Address m_da; + Mac48Address m_sa; + uint16_t m_length; +}; + +} //namespace ns3 + +#endif /* AMSDU_SUBFRAME_HEADER_H */ diff --git a/src/devices/wifi/edca-txop-n.cc b/src/devices/wifi/edca-txop-n.cc new file mode 100644 index 000000000..dc5052c7a --- /dev/null +++ b/src/devices/wifi/edca-txop-n.cc @@ -0,0 +1,691 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006, 2009 INRIA + * Copyright (c) 2009 MIRKO BANCHI + * + * 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 + * Author: Mirko Banchi + */ +#include "ns3/log.h" +#include "ns3/assert.h" + +#include "edca-txop-n.h" +#include "mac-low.h" +#include "dcf-manager.h" +#include "mac-tx-middle.h" +#include "wifi-mac-trailer.h" +#include "wifi-mac.h" +#include "random-stream.h" +#include "wifi-mac-queue.h" +#include "msdu-aggregator.h" + +NS_LOG_COMPONENT_DEFINE ("EdcaTxopN"); + +#define MY_DEBUG(x) \ + NS_LOG_DEBUG (m_low->GetAddress () << " " << x) + +namespace ns3 { + +class EdcaTxopN::Dcf : public DcfState +{ +public: + Dcf (EdcaTxopN *txop) + : m_txop (txop) + {} +private: + virtual void DoNotifyAccessGranted (void) { + m_txop->NotifyAccessGranted (); + } + virtual void DoNotifyInternalCollision (void) { + m_txop->NotifyInternalCollision (); + } + virtual void DoNotifyCollision (void) { + m_txop->NotifyCollision (); + } + EdcaTxopN *m_txop; +}; + +class EdcaTxopN::TransmissionListener : public MacLowTransmissionListener +{ +public: + TransmissionListener (EdcaTxopN *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) { + m_txop->Cancel (); + } + +private: + EdcaTxopN *m_txop; +}; + +NS_OBJECT_ENSURE_REGISTERED (EdcaTxopN); + +TypeId +EdcaTxopN::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::EdcaTxopN") + .SetParent () + .AddConstructor () + .AddAttribute ("MinCw", "The minimun value of the contention window.", + UintegerValue (31), + MakeUintegerAccessor (&EdcaTxopN::SetMinCw, + &EdcaTxopN::GetMinCw), + MakeUintegerChecker ()) + .AddAttribute ("MaxCw", "The maximum value of the contention window.", + UintegerValue (1023), + MakeUintegerAccessor (&EdcaTxopN::SetMaxCw, + &EdcaTxopN::GetMaxCw), + MakeUintegerChecker ()) + .AddAttribute ("Aifsn", "The AIFSN: the default value conforms to simple DCA.", + UintegerValue (3), + MakeUintegerAccessor (&EdcaTxopN::SetAifsn, + &EdcaTxopN::GetAifsn), + MakeUintegerChecker ()) + ; + return tid; +} + +EdcaTxopN::EdcaTxopN () + : m_manager (0), + m_currentPacket(0), + m_aggregator (0) +{ + NS_LOG_FUNCTION (this); + m_transmissionListener = new EdcaTxopN::TransmissionListener (this); + m_dcf = new EdcaTxopN::Dcf (this); + m_queue = CreateObject (); + m_rng = new RealRandomStream (); +} + +EdcaTxopN::~EdcaTxopN () +{ + NS_LOG_FUNCTION (this); +} + +void +EdcaTxopN::DoDispose (void) +{ + NS_LOG_FUNCTION (this); + m_queue = 0; + m_low = 0; + m_stationManager = 0; + delete m_transmissionListener; + delete m_dcf; + delete m_rng; + m_transmissionListener = 0; + m_dcf = 0; + m_rng = 0; + m_txMiddle = 0; + m_aggregator = 0; +} + +void +EdcaTxopN::SetManager (DcfManager *manager) +{ + NS_LOG_FUNCTION (this << manager); + m_manager = manager; + m_manager->Add (m_dcf); +} + +void +EdcaTxopN::SetTxOkCallback (TxOk callback) +{ + m_txOkCallback = callback; +} + +void +EdcaTxopN::SetTxFailedCallback (TxFailed callback) +{ + m_txFailedCallback = callback; +} + +void +EdcaTxopN::SetWifiRemoteStationManager (Ptr remoteManager) +{ + NS_LOG_FUNCTION (this << remoteManager); + m_stationManager = remoteManager; +} +void +EdcaTxopN::SetTypeOfStation (enum TypeOfStation type) +{ + NS_LOG_FUNCTION (this << type); + m_typeOfStation = type; +} + +enum TypeOfStation +EdcaTxopN::GetTypeOfStation (void) const +{ + return m_typeOfStation; +} + +void +EdcaTxopN::SetMaxQueueSize (uint32_t size) +{ + NS_LOG_FUNCTION (this << size); + m_queue->SetMaxSize (size); +} + +void +EdcaTxopN::SetMaxQueueDelay (Time delay) +{ + NS_LOG_FUNCTION (this << delay); + m_queue->SetMaxDelay (delay); +} + +void +EdcaTxopN::SetMinCw (uint32_t minCw) +{ + NS_LOG_FUNCTION (this << minCw); + m_dcf->SetCwMin (minCw); +} + +void +EdcaTxopN::SetMaxCw (uint32_t maxCw) +{ + NS_LOG_FUNCTION (this << maxCw); + m_dcf->SetCwMax (maxCw); +} + +void +EdcaTxopN::SetAifsn (uint32_t aifsn) +{ + NS_LOG_FUNCTION (this << aifsn); + m_dcf->SetAifsn (aifsn); +} + +uint32_t +EdcaTxopN::GetMinCw (void) const +{ + return m_dcf->GetCwMin (); +} + +uint32_t +EdcaTxopN::GetMaxCw (void) const +{ + return m_dcf->GetCwMax (); +} + +uint32_t +EdcaTxopN::GetAifsn (void) const +{ + return m_dcf->GetAifsn (); +} + +void +EdcaTxopN::SetTxMiddle (MacTxMiddle *txMiddle) +{ + m_txMiddle = txMiddle; +} + +Ptr +EdcaTxopN::Low (void) +{ + return m_low; +} + +void +EdcaTxopN::SetLow(Ptr low) +{ + NS_LOG_FUNCTION (this << low); + m_low = low; +} + +bool +EdcaTxopN::NeedsAccess (void) const +{ + return !m_queue->IsEmpty () || m_currentPacket != 0; +} + +void +EdcaTxopN::NotifyAccessGranted (void) +{ + NS_LOG_FUNCTION (this); + if (m_currentPacket == 0) + { + if (m_queue->IsEmpty ()) + { + MY_DEBUG ("queue is empty"); + return; + } + m_currentPacket = m_queue->Dequeue (&m_currentHdr); + NS_ASSERT (m_currentPacket != 0); + + uint16_t sequence = m_txMiddle->GetNextSequenceNumberfor (&m_currentHdr); + m_currentHdr.SetSequenceNumber (sequence); + m_currentHdr.SetFragmentNumber (0); + m_currentHdr.SetNoMoreFragments (); + m_currentHdr.SetNoRetry (); + m_fragmentNumber = 0; + MY_DEBUG ("dequeued size="<GetSize ()<< + ", to="< fragment = GetFragmentPacket (&hdr); + if (IsLastFragment ()) + { + MY_DEBUG ("fragmenting last fragment size=" << fragment->GetSize ()); + params.DisableNextData (); + } + else + { + MY_DEBUG ("fragmenting size=" << fragment->GetSize ()); + params.EnableNextData (GetNextFragmentSize ()); + } + m_low->StartTransmission (fragment, &hdr, params, + m_transmissionListener); + } + else + { + WifiMacHeader peekedHdr; + if (m_currentHdr.IsQosData () && + m_queue->PeekByTidAndAddress (&peekedHdr, m_currentHdr.GetQosTid (), + WifiMacHeader::ADDR1, m_currentHdr.GetAddr1 ()) && + !m_currentHdr.GetAddr1 ().IsBroadcast () && + m_aggregator != 0) + { + /* here is performed aggregation */ + Ptr currentAggregatedPacket = Create (); + m_aggregator->Aggregate (m_currentPacket, currentAggregatedPacket, + MapSrcAddressForAggregation (peekedHdr), + MapDestAddressForAggregation (peekedHdr)); + bool aggregated = false; + bool isAmsdu = false; + Ptr peekedPacket = m_queue->PeekByTidAndAddress (&peekedHdr, m_currentHdr.GetQosTid (), + WifiMacHeader::ADDR1, + m_currentHdr.GetAddr1 ()); + while (peekedPacket != 0) + { + aggregated = m_aggregator->Aggregate (peekedPacket, currentAggregatedPacket, + MapSrcAddressForAggregation (peekedHdr), + MapDestAddressForAggregation (peekedHdr)); + if (aggregated) + { + isAmsdu = true; + m_queue->Remove (peekedPacket); + } + else + { + break; + } + peekedPacket = m_queue->PeekByTidAndAddress (&peekedHdr, m_currentHdr.GetQosTid (), + WifiMacHeader::ADDR1, m_currentHdr.GetAddr1 ()); + } + if (isAmsdu) + { + m_currentHdr.SetQosAmsdu (); + m_currentHdr.SetAddr3 (m_low->GetBssid ()); + m_currentPacket = currentAggregatedPacket; + currentAggregatedPacket = 0; + MY_DEBUG ("tx unicast A-MSDU"); + } + } + if (NeedRts ()) + { + params.EnableRts (); + MY_DEBUG ("tx unicast rts"); + } + else + { + params.DisableRts (); + MY_DEBUG ("tx unicast"); + } + params.DisableNextData (); + m_low->StartTransmission (m_currentPacket, &m_currentHdr, + params, m_transmissionListener); + } + } +} + +void EdcaTxopN::NotifyInternalCollision (void) +{ + NS_LOG_FUNCTION (this); + NotifyCollision (); +} + +void +EdcaTxopN::NotifyCollision (void) +{ + NS_LOG_FUNCTION (this); + m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); + RestartAccessIfNeeded (); +} + +void +EdcaTxopN::GotCts (double snr, WifiMode txMode) +{ + NS_LOG_FUNCTION (this << snr << txMode); + MY_DEBUG ("got cts"); +} + +void +EdcaTxopN::MissedCts (void) +{ + NS_LOG_FUNCTION (this); + MY_DEBUG ("missed cts"); + if (!NeedRtsRetransmission ()) + { + MY_DEBUG ("Cts Fail"); + WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); + station->ReportFinalRtsFailed (); + if (!m_txFailedCallback.IsNull ()) + { + m_txFailedCallback (m_currentHdr); + } + // to reset the dcf. + m_currentPacket = 0; + m_dcf->ResetCw (); + } + else + { + m_dcf->UpdateFailedCw (); + } + m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); + RestartAccessIfNeeded (); +} + +void +EdcaTxopN::Queue (Ptr packet, WifiMacHeader const &hdr) +{ + NS_LOG_FUNCTION (this << packet << &hdr); + WifiMacTrailer fcs; + uint32_t fullPacketSize = hdr.GetSerializedSize () + packet->GetSize () + fcs.GetSerializedSize (); + WifiRemoteStation *station = GetStation (hdr.GetAddr1 ()); + station->PrepareForQueue (packet, fullPacketSize); + m_queue->Enqueue (packet, hdr); + StartAccessIfNeeded (); +} + +void +EdcaTxopN::GotAck (double snr, WifiMode txMode) +{ + NS_LOG_FUNCTION (this << snr << txMode); + if (!NeedFragmentation () || + IsLastFragment () || + m_currentHdr.IsQosAmsdu ()) + { + MY_DEBUG ("got ack. tx done."); + if (!m_txOkCallback.IsNull ()) + { + m_txOkCallback (m_currentHdr); + } + m_currentPacket = 0; + + m_dcf->ResetCw (); + m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); + RestartAccessIfNeeded (); + } + else + { + MY_DEBUG ("got ack. tx not done, size="<GetSize ()); + } +} + +void +EdcaTxopN::MissedAck (void) +{ + NS_LOG_FUNCTION (this); + MY_DEBUG ("missed ack"); + if (!NeedDataRetransmission ()) + { + MY_DEBUG ("Ack Fail"); + WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); + station->ReportFinalDataFailed (); + if (!m_txFailedCallback.IsNull ()) + { + m_txFailedCallback (m_currentHdr); + } + // to reset the dcf. + m_currentPacket = 0; + m_dcf->ResetCw (); + } + else + { + MY_DEBUG ("Retransmit"); + m_currentHdr.SetRetry (); + m_dcf->UpdateFailedCw (); + } + m_dcf->StartBackoffNow (m_rng->GetNext (0, m_dcf->GetCw ())); + RestartAccessIfNeeded (); +} + +Ptr +EdcaTxopN::GetMsduAggregator (void) const +{ + return m_aggregator; +} + +void +EdcaTxopN::RestartAccessIfNeeded (void) +{ + NS_LOG_FUNCTION (this); + if ((m_currentPacket != 0 || + !m_queue->IsEmpty ()) && + !m_dcf->IsAccessRequested ()) + { + m_manager->RequestAccess (m_dcf); + } +} + +void +EdcaTxopN::StartAccessIfNeeded (void) +{ + NS_LOG_FUNCTION (this); + if (m_currentPacket == 0 && + !m_queue->IsEmpty () && + !m_dcf->IsAccessRequested ()) + { + m_manager->RequestAccess (m_dcf); + } +} + +bool +EdcaTxopN::NeedRts (void) +{ + WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); + return station->NeedRts (m_currentPacket); +} + +bool +EdcaTxopN::NeedRtsRetransmission (void) +{ + WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); + return station->NeedRtsRetransmission (m_currentPacket); +} + +bool +EdcaTxopN::NeedDataRetransmission (void) +{ + WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); + return station->NeedDataRetransmission (m_currentPacket); +} + +void +EdcaTxopN::NextFragment (void) +{ + m_fragmentNumber++; +} + +void +EdcaTxopN::StartNext (void) +{ + NS_LOG_FUNCTION (this); + MY_DEBUG ("start next packet fragment"); + /* this callback is used only for fragments. */ + NextFragment (); + WifiMacHeader hdr; + Ptr 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); +} + +void +EdcaTxopN::Cancel (void) +{ + NS_LOG_FUNCTION (this); + MY_DEBUG ("transmission cancelled"); +} + +bool +EdcaTxopN::NeedFragmentation (void) const +{ + WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); + return station->NeedFragmentation (m_currentPacket); +} + +uint32_t +EdcaTxopN::GetFragmentSize (void) +{ + WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); + return station->GetFragmentSize (m_currentPacket, m_fragmentNumber); +} + +uint32_t +EdcaTxopN::GetNextFragmentSize (void) +{ + WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); + return station->GetFragmentSize (m_currentPacket, m_fragmentNumber + 1); +} + +uint32_t +EdcaTxopN::GetFragmentOffset (void) +{ + WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); + return station->GetFragmentOffset (m_currentPacket, m_fragmentNumber); +} + +WifiRemoteStation * +EdcaTxopN::GetStation (Mac48Address ad) const +{ + return m_stationManager->Lookup (ad); +} + +bool +EdcaTxopN::IsLastFragment (void) const +{ + WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); + return station->IsLastFragment (m_currentPacket, m_fragmentNumber); +} + +Ptr +EdcaTxopN::GetFragmentPacket (WifiMacHeader *hdr) +{ + *hdr = m_currentHdr; + hdr->SetFragmentNumber (m_fragmentNumber); + uint32_t startOffset = GetFragmentOffset (); + Ptr fragment; + if (IsLastFragment ()) + { + hdr->SetNoMoreFragments (); + } + else + { + hdr->SetMoreFragments (); + } + fragment = m_currentPacket->CreateFragment (startOffset, + GetFragmentSize ()); + return fragment; +} + +Mac48Address +EdcaTxopN::MapSrcAddressForAggregation (WifiMacHeader const &hdr) +{ + if (m_typeOfStation == STA || m_typeOfStation == ADHOC_STA) + { + return hdr.GetAddr2 (); + } + else + { + return hdr.GetAddr3 (); + } +} + +Mac48Address +EdcaTxopN::MapDestAddressForAggregation (WifiMacHeader const &hdr) +{ + if (m_typeOfStation == AP || m_typeOfStation == ADHOC_STA) + { + return hdr.GetAddr1 (); + } + else + { + return hdr.GetAddr3 (); + } +} + +void +EdcaTxopN::SetMsduAggregator (Ptr aggr) +{ + m_aggregator = aggr; +} + +} //namespace ns3 diff --git a/src/devices/wifi/edca-txop-n.h b/src/devices/wifi/edca-txop-n.h new file mode 100644 index 000000000..497871b61 --- /dev/null +++ b/src/devices/wifi/edca-txop-n.h @@ -0,0 +1,170 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006, 2009 INRIA + * Copyright (c) 2009 MIRKO BANCHI + * + * 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 + * Author: Mirko Banchi + */ +#ifndef EDCA_TXOP_N_H +#define EDCA_TXOP_N_H + +#include "ns3/object.h" +#include "ns3/mac48-address.h" +#include "ns3/packet.h" + +#include "wifi-mode.h" +#include "wifi-mac.h" +#include "wifi-mac-header.h" +#include "qos-utils.h" + +#include +#include + +namespace ns3 { + +class DcfState; +class DcfManager; +class MacLow; +class MacTxMiddle; +class WifiMacParameters; +class WifiMacQueue; +class RandomStream; +class MsduAggregator; + +/* This queue contains packets for a particular access class. + * possibles access classes are: + * + * -AC_VO : voice, tid = 6,7 ^ + * -AC_VI : video, tid = 4,5 | + * -AC_BE : best-effort, tid = 0,3 | priority + * -AC_BK : background, tid = 1,2 | + * + * For more details see section 9.1.3.1 in 802.11 standard. + */ +enum TypeOfStation +{ + STA, + AP, + ADHOC_STA +}; + +class EdcaTxopN : public Object +{ +public: + + typedef Callback TxOk; + typedef Callback TxFailed; + + static TypeId GetTypeId (void); + EdcaTxopN (); + virtual ~EdcaTxopN (); + void DoDispose (); + + void SetLow (Ptr low); + void SetTxMiddle (MacTxMiddle *txMiddle); + void SetManager (DcfManager *manager); + void SetTxOkCallback (TxOk callback); + void SetTxFailedCallback (TxFailed callback); + void SetWifiRemoteStationManager (Ptr remoteManager); + void SetTypeOfStation (enum TypeOfStation type); + enum TypeOfStation GetTypeOfStation (void) const; + + void SetMaxQueueSize (uint32_t size); + void SetMaxQueueDelay (Time delay); + void SetMinCw (uint32_t minCw); + void SetMaxCw (uint32_t maxCw); + void SetAifsn (uint32_t aifsn); + uint32_t GetMinCw (void) const; + uint32_t GetMaxCw (void) const; + uint32_t GetAifsn (void) const; + + Ptr Low (void); + Ptr GetMsduAggregator (void) const; + + /* dcf notifications forwarded here */ + bool NeedsAccess (void) const; + void NotifyAccessGranted (void); + void NotifyInternalCollision (void); + void NotifyCollision (void); + + /*event handlers*/ + void GotCts (double snr, WifiMode txMode); + void MissedCts (void); + void GotAck (double snr, WifiMode txMode); + void MissedAck (void); + void StartNext (void); + void Cancel (void); + + void RestartAccessIfNeeded (void); + void StartAccessIfNeeded (void); + bool NeedRts (void); + bool NeedRtsRetransmission (void); + bool NeedDataRetransmission (void); + bool NeedFragmentation (void) const; + uint32_t GetNextFragmentSize (void); + uint32_t GetFragmentSize (void); + uint32_t GetFragmentOffset (void); + WifiRemoteStation *GetStation (Mac48Address to) const; + bool IsLastFragment (void) const; + void NextFragment (void); + Ptr GetFragmentPacket (WifiMacHeader *hdr); + + void Queue (Ptr packet, WifiMacHeader const &hdr); + void SetMsduAggregator (Ptr aggr); + +private: + /** + * This functions are used only to correctly set addresses in a-msdu subframe. + * If aggregating sta is a STA (in an infrastructured network): + * SA = Address2 + * DA = Address3 + * If aggregating sta is an AP + * SA = Address3 + * DA = Address1 + */ + Mac48Address MapSrcAddressForAggregation (WifiMacHeader const &hdr); + Mac48Address MapDestAddressForAggregation (WifiMacHeader const &hdr); + + class Dcf; + class TransmissionListener; + friend class Dcf; + friend class TransmissionListener; + Dcf *m_dcf; + DcfManager *m_manager; + Ptr m_queue; + TxOk m_txOkCallback; + TxFailed m_txFailedCallback; + Ptr m_low; + MacTxMiddle *m_txMiddle; + TransmissionListener *m_transmissionListener; + RandomStream *m_rng; + Ptr m_stationManager; + uint8_t m_fragmentNumber; + + /* current packet could be a simple MSDU or, if an aggregator for this queue is + present, could be an A-MSDU. + */ + Ptr m_currentPacket; + + WifiMacHeader m_currentHdr; + Ptr m_aggregator; + TypeOfStation m_typeOfStation; +}; + +} //namespace ns3 + +#endif /* EDCA_TXOP_N_H */ diff --git a/src/devices/wifi/msdu-aggregator.cc b/src/devices/wifi/msdu-aggregator.cc new file mode 100644 index 000000000..5455bcb79 --- /dev/null +++ b/src/devices/wifi/msdu-aggregator.cc @@ -0,0 +1,78 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 MIRKO BANCHI + * + * 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: Mirko Banchi + */ +#include "ns3/log.h" + +#include "msdu-aggregator.h" +#include "wifi-mac-header.h" + +NS_LOG_COMPONENT_DEFINE ("MsduAggregator"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (MsduAggregator); + +TypeId +MsduAggregator::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::MsduAggregator") + .SetParent () + ; + return tid; +} + +MsduAggregator::DeaggregatedMsdus +MsduAggregator::Deaggregate (Ptr aggregatedPacket) +{ + NS_LOG_FUNCTION_NOARGS (); + DeaggregatedMsdus set; + + AmsduSubframeHeader hdr; + uint32_t maxSize = aggregatedPacket->GetSize (); + // The worst condition is: two aggregated packets with no padding. + // 28 bytes is the size of two Amsdu subframe headers. + uint8_t *buffer = new uint8_t[maxSize-28]; + uint32_t padding; + uint32_t deserialized = 0; + + while (deserialized < maxSize) + { + deserialized += aggregatedPacket->RemoveHeader (hdr); + deserialized += aggregatedPacket->CopyData (buffer, hdr.GetLength ()); + aggregatedPacket->RemoveAtStart (hdr.GetLength ()); + + padding = (4 - ((hdr.GetLength () + 14) %4 )) % 4; + + if (padding > 0) + { + aggregatedPacket->RemoveAtStart (padding); + deserialized += padding; + } + //a new packet is created with the content of extracted msdu + Ptr p = Create (buffer, hdr.GetLength ()); + + std::pair, AmsduSubframeHeader> packetHdr (p,hdr); + set.push_back (packetHdr); + } + delete [] buffer; + NS_LOG_INFO ("Deaggreated A-MSDU: extracted "<< set.size () << " MSDUs"); + return set; +} + +} //namespace ns3 diff --git a/src/devices/wifi/msdu-aggregator.h b/src/devices/wifi/msdu-aggregator.h new file mode 100644 index 000000000..3845766a7 --- /dev/null +++ b/src/devices/wifi/msdu-aggregator.h @@ -0,0 +1,55 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 MIRKO BANCHI + * + * 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: Mirko Banchi + */ +#ifndef MSDU_AGGREGATOR_H +#define MSDU_AGGREGATOR_H + +#include "ns3/ptr.h" +#include "ns3/packet.h" +#include "ns3/object.h" + +#include "amsdu-subframe-header.h" + +#include + +namespace ns3 { + +class WifiMacHeader; +/** + * \brief Abstract class that concrete msdu aggregators have to implement + */ +class MsduAggregator : public Object +{ +public: + typedef std::list, AmsduSubframeHeader> > DeaggregatedMsdus; + + static TypeId GetTypeId (void); + /* Adds packet to aggregatedPacket. In concrete aggregator's implementation is + * specified how and if packet can be added to aggregatedPacket. If packet + * can be added returns true, false otherwise. + */ + virtual bool Aggregate (Ptr packet, Ptr aggregatedPacket, + Mac48Address src, Mac48Address dest) = 0; + + static DeaggregatedMsdus Deaggregate (Ptr aggregatedPacket); +}; + +} //namespace ns3 + +#endif /* MSDU_AGGREGATOR_H */ diff --git a/src/devices/wifi/msdu-standard-aggregator.cc b/src/devices/wifi/msdu-standard-aggregator.cc new file mode 100644 index 000000000..5fcb0ca24 --- /dev/null +++ b/src/devices/wifi/msdu-standard-aggregator.cc @@ -0,0 +1,86 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 MIRKO BANCHI + * + * 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: Mirko Banchi + */ +#include "ns3/log.h" +#include "ns3/uinteger.h" + +#include "amsdu-subframe-header.h" +#include "msdu-standard-aggregator.h" + +NS_LOG_COMPONENT_DEFINE ("MsduStandardAggregator"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (MsduStandardAggregator); + +TypeId +MsduStandardAggregator::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::MsduStandardAggregator") + .SetParent () + .AddConstructor () + .AddAttribute ("MaxAmsduSize", "Max length in byte of an A-MSDU", + UintegerValue (7935), + MakeUintegerAccessor (&MsduStandardAggregator::m_maxAmsduLength), + MakeUintegerChecker ()) + ; + return tid; +} + +MsduStandardAggregator::MsduStandardAggregator () +{} + +MsduStandardAggregator::~MsduStandardAggregator () +{} + +bool +MsduStandardAggregator::Aggregate (Ptr packet, Ptr aggregatedPacket, + Mac48Address src, Mac48Address dest) +{ + NS_LOG_FUNCTION (this); + Ptr currentPacket; + AmsduSubframeHeader currentHdr; + + uint32_t padding = CalculatePadding (packet); + uint32_t actualSize = aggregatedPacket->GetSize (); + + if ((14 + packet->GetSize () + actualSize + padding) <= m_maxAmsduLength) + { + currentHdr.SetDestinationAddr (dest); + currentHdr.SetSourceAddr (src); + currentHdr.SetLength (packet->GetSize ()); + currentPacket = packet->Copy (); + if (padding) + { + currentPacket->AddPaddingAtEnd (padding); + } + currentPacket->AddHeader (currentHdr); + aggregatedPacket->AddAtEnd (currentPacket); + return true; + } + return false; +} + +uint32_t +MsduStandardAggregator::CalculatePadding (Ptr packet) +{ + return (4 - ((packet->GetSize() + 14) %4 )) % 4; +} + +} //namespace ns3 diff --git a/src/devices/wifi/msdu-standard-aggregator.h b/src/devices/wifi/msdu-standard-aggregator.h new file mode 100644 index 000000000..7e626fe2d --- /dev/null +++ b/src/devices/wifi/msdu-standard-aggregator.h @@ -0,0 +1,56 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 MIRKO BANCHI + * + * 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: Mirko Banchi + */ +#ifndef MSDU_STANDARD_AGGREGATOR_H +#define MSDU_STANDARD_AGGREGATOR_H + +#include "msdu-aggregator.h" + +namespace ns3 { + +class MsduStandardAggregator : public MsduAggregator +{ +public: + + static TypeId GetTypeId (void); + MsduStandardAggregator (); + ~MsduStandardAggregator (); + /** + * \param packet Packet we have to insert into aggregatedPacket. + * \param aggregatedPacket Packet that will contain packet, if aggregation is possible, + * \param src Source address of packet. + * \param dest Destination address of packet. + * + * This method performs an MSDU aggregation. + * Returns true if packet can be aggregated to aggregatedPacket, false otherwise. + */ + virtual bool Aggregate (Ptr packet, Ptr aggregatedPacket, + Mac48Address src, Mac48Address dest); +private: + /* Calculates how much padding must be added to the end of packet. + Each A-MSDU subframe is padded so that its length is multiple of 4 octects. + */ + uint32_t CalculatePadding (Ptr packet); + + uint32_t m_maxAmsduLength; +}; + +} //namespace ns3 + +#endif /* MSDU_STANDARD_AGGREGATOR_H */ diff --git a/src/devices/wifi/qadhoc-wifi-mac.cc b/src/devices/wifi/qadhoc-wifi-mac.cc new file mode 100644 index 000000000..66793e4fa --- /dev/null +++ b/src/devices/wifi/qadhoc-wifi-mac.cc @@ -0,0 +1,441 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006, 2009 INRIA + * Copyright (c) 2009 MIRKO BANCHI + * + * 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 + * Author: Mirko Banchi + */ +#include "ns3/pointer.h" +#include "ns3/log.h" +#include "ns3/string.h" + +#include "qos-tag.h" +#include "edca-txop-n.h" +#include "qadhoc-wifi-mac.h" +#include "mac-low.h" +#include "dcf-manager.h" +#include "mac-rx-middle.h" +#include "mac-tx-middle.h" +#include "wifi-mac-header.h" +#include "msdu-aggregator.h" +#include "amsdu-subframe-header.h" +#include "mgt-headers.h" + +NS_LOG_COMPONENT_DEFINE ("QadhocWifiMac"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (QadhocWifiMac); + +TypeId +QadhocWifiMac::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::QadhocWifiMac") + .SetParent () + .AddConstructor () + .AddAttribute ("VO_EdcaTxopN", + "Queue that manages packets belonging to AC_VO access class", + PointerValue (), + MakePointerAccessor(&QadhocWifiMac::GetVOQueue, + &QadhocWifiMac::SetVOQueue), + MakePointerChecker ()) + .AddAttribute ("VI_EdcaTxopN", + "Queue that manages packets belonging to AC_VI access class", + PointerValue (), + MakePointerAccessor(&QadhocWifiMac::GetVIQueue, + &QadhocWifiMac::SetVIQueue), + MakePointerChecker ()) + .AddAttribute ("BE_EdcaTxopN", + "Queue that manages packets belonging to AC_BE access class", + PointerValue (), + MakePointerAccessor(&QadhocWifiMac::GetBEQueue, + &QadhocWifiMac::SetBEQueue), + MakePointerChecker ()) + .AddAttribute ("BK_EdcaTxopN", + "Queue that manages packets belonging to AC_BK access class", + PointerValue (), + MakePointerAccessor(&QadhocWifiMac::GetBKQueue, + &QadhocWifiMac::SetBKQueue), + MakePointerChecker ()) + ; + return tid; +} + +QadhocWifiMac::QadhocWifiMac () +{ + NS_LOG_FUNCTION (this); + m_rxMiddle = new MacRxMiddle (); + m_rxMiddle->SetForwardCallback (MakeCallback (&QadhocWifiMac::Receive, this)); + + m_txMiddle = new MacTxMiddle (); + + m_low = CreateObject (); + m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle)); + + m_dcfManager = new DcfManager (); + m_dcfManager->SetupLowListener (m_low); +} + +QadhocWifiMac::~QadhocWifiMac () +{ + NS_LOG_FUNCTION (this); +} + +void +QadhocWifiMac::DoDispose (void) +{ + NS_LOG_FUNCTION (this); + delete m_rxMiddle; + m_rxMiddle = 0; + delete m_txMiddle; + m_txMiddle = 0; + delete m_dcfManager; + m_dcfManager = 0; + m_low = 0; + m_phy = 0; + m_voEdca = 0; + m_viEdca = 0; + m_beEdca = 0; + m_bkEdca = 0; + m_stationManager = 0; + std::map >::iterator it = m_queues.begin (); + for (;it != m_queues.end (); it++) + { + it->second = 0; + } + WifiMac::DoDispose (); +} + +void +QadhocWifiMac::SetSlot (Time slotTime) +{ + m_dcfManager->SetSlot (slotTime); + m_low->SetSlotTime (slotTime); +} + +void +QadhocWifiMac::SetSifs (Time sifs) +{ + m_dcfManager->SetSifs (sifs); + m_low->SetSifs (sifs); +} + +void +QadhocWifiMac::SetEifsNoDifs (Time eifsNoDifs) +{ + m_dcfManager->SetEifsNoDifs (eifsNoDifs); + m_eifsNoDifs = eifsNoDifs; +} + +void +QadhocWifiMac::SetAckTimeout (Time ackTimeout) +{ + m_low->SetAckTimeout (ackTimeout); +} + +void +QadhocWifiMac::SetCtsTimeout (Time ctsTimeout) +{ + m_low->SetCtsTimeout (ctsTimeout); +} + +void +QadhocWifiMac::SetPifs (Time pifs) +{ + m_low->SetPifs (pifs); +} + +Time +QadhocWifiMac::GetSlot (void) const +{ + return m_low->GetSlotTime (); +} + +Time +QadhocWifiMac::GetSifs (void) const +{ + return m_low->GetSifs (); +} + +Time +QadhocWifiMac::GetEifsNoDifs (void) const +{ + return m_eifsNoDifs; +} + +Time +QadhocWifiMac::GetAckTimeout (void) const +{ + return m_low->GetAckTimeout (); +} + +Time +QadhocWifiMac::GetCtsTimeout (void) const +{ + return m_low->GetCtsTimeout (); +} + +Time +QadhocWifiMac::GetPifs (void) const +{ + return m_low->GetPifs (); +} + +void +QadhocWifiMac::SetWifiPhy (Ptr phy) +{ + m_phy = phy; + m_dcfManager->SetupPhyListener (phy); + m_low->SetPhy (phy); +} + +void +QadhocWifiMac::SetWifiRemoteStationManager (Ptr stationManager) +{ + NS_LOG_FUNCTION (this << stationManager); + m_stationManager = stationManager; + m_voEdca->SetWifiRemoteStationManager (stationManager); + m_viEdca->SetWifiRemoteStationManager (stationManager); + m_beEdca->SetWifiRemoteStationManager (stationManager); + m_bkEdca->SetWifiRemoteStationManager (stationManager); + m_low->SetWifiRemoteStationManager (stationManager); +} + +void +QadhocWifiMac::Enqueue (Ptr packet, Mac48Address to, Mac48Address from) +{ + NS_FATAL_ERROR ("Adhoc does not support a from != m_low->GetAddress ()"); +} + +void +QadhocWifiMac::Enqueue (Ptr packet, Mac48Address to) +{ + /* For now Qos adhoc stations sends only Qos frame. In the future they + * should be able to send frames also to Non-Qos Stas. + */ + NS_LOG_FUNCTION (packet->GetSize () << to); + WifiMacHeader hdr; + hdr.SetType (WIFI_MAC_QOSDATA); + hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK); + hdr.SetQosNoEosp (); + hdr.SetQosNoAmsdu (); + /* Transmission of multiple frames in the same + Txop is not supported for now */ + hdr.SetQosTxopLimit (0); + + hdr.SetAddr1 (to); + hdr.SetAddr2 (m_low->GetAddress ()); + hdr.SetAddr3 (GetBssid ()); + hdr.SetDsNotFrom (); + hdr.SetDsNotTo (); + + WifiRemoteStation *destination = m_stationManager->Lookup (to); + if (destination->IsBrandNew ()) + { + // in adhoc mode, we assume that every destination + // supports all the rates we support. + for (uint32_t i = 0; i < m_phy->GetNModes (); i++) + { + destination->AddSupportedMode (m_phy->GetMode (i)); + } + destination->RecordDisassociated (); + } + + uint8_t tid = QosUtilsGetTidForPacket (packet); + if (tid < 8) + { + hdr.SetQosTid (tid); + AccessClass ac = QosUtilsMapTidToAc (tid); + m_queues[ac]->Queue (packet, hdr); + } + else + { + //packet is considerated belonging to BestEffort AC + hdr.SetQosTid (0); + m_queues[AC_BE]->Queue (packet, hdr); + } +} + +bool +QadhocWifiMac::SupportsSendFrom (void) const +{ + return false; +} + +void +QadhocWifiMac::SetForwardUpCallback (Callback, Mac48Address, Mac48Address> upCallback) +{ + m_forwardUp = upCallback; +} + +void +QadhocWifiMac::SetLinkUpCallback (Callback linkUp) +{ + // an Adhoc network is always UP. + linkUp (); +} + +void +QadhocWifiMac::SetLinkDownCallback (Callback linkDown) +{} + +Mac48Address +QadhocWifiMac::GetAddress (void) const +{ + return m_low->GetAddress (); +} + +Ssid +QadhocWifiMac::GetSsid (void) const +{ + return m_ssid; +} + +void +QadhocWifiMac::SetAddress (Mac48Address address) +{ + m_low->SetAddress (address); + m_low->SetBssid (address); +} + +void +QadhocWifiMac::SetSsid (Ssid ssid) +{ + NS_LOG_FUNCTION (this << ssid); + // XXX: here, we should start a special adhoc network + m_ssid = ssid; +} + +Mac48Address +QadhocWifiMac::GetBssid (void) const +{ + return m_low->GetBssid (); +} + +void +QadhocWifiMac::ForwardUp (Ptr packet, Mac48Address from, Mac48Address to) +{ + NS_LOG_FUNCTION (this << packet << from); + m_forwardUp (packet, from, to); +} + +void +QadhocWifiMac::Receive (Ptr packet, WifiMacHeader const *hdr) +{ + NS_LOG_FUNCTION (this << packet << hdr); + NS_ASSERT (!hdr->IsCtl ()); + Mac48Address from = hdr->GetAddr2 (); + Mac48Address to = hdr->GetAddr1 (); + if (hdr->IsData ()) + { + if (hdr->IsQosData () && hdr->IsQosAmsdu ()) + { + NS_LOG_DEBUG ("Received A-MSDU from"<IsMgt ()) + { + //Handling action frames + } +} + +void +QadhocWifiMac::DeaggregateAmsduAndForward (Ptr aggregatedPacket, + WifiMacHeader const *hdr) +{ + DeaggregatedMsdus packets = MsduAggregator::Deaggregate (aggregatedPacket); + for (DeaggregatedMsdusCI i = packets.begin (); i != packets.end (); ++i) + { + ForwardUp ((*i).first, (*i).second.GetSourceAddr (), + (*i).second.GetDestinationAddr ()); + } +} + +Ptr +QadhocWifiMac::GetVOQueue (void) const +{ + return m_voEdca; +} + +Ptr +QadhocWifiMac::GetVIQueue (void) const +{ + return m_viEdca; +} + +Ptr +QadhocWifiMac::GetBEQueue (void) const +{ + return m_beEdca; +} + +Ptr +QadhocWifiMac::GetBKQueue (void) const +{ + return m_bkEdca; +} + +void +QadhocWifiMac::SetVOQueue (Ptr voQueue) +{ + m_voEdca = voQueue; + m_queues.insert (std::make_pair(AC_VO, m_voEdca)); + m_queues[AC_VO]->SetLow (m_low); + m_queues[AC_VO]->SetManager (m_dcfManager); + m_queues[AC_VO]->SetTypeOfStation (ADHOC_STA); + m_queues[AC_VO]->SetTxMiddle (m_txMiddle); +} + +void +QadhocWifiMac::SetVIQueue (Ptr viQueue) +{ + m_viEdca = viQueue; + m_queues.insert (std::make_pair(AC_VI, m_viEdca)); + m_queues[AC_VI]->SetLow (m_low); + m_queues[AC_VI]->SetManager (m_dcfManager); + m_queues[AC_VI]->SetTypeOfStation (ADHOC_STA); + m_queues[AC_VI]->SetTxMiddle (m_txMiddle); +} + +void +QadhocWifiMac::SetBEQueue (Ptr beQueue) +{ + m_beEdca = beQueue; + m_queues.insert (std::make_pair(AC_BE, m_beEdca)); + m_queues[AC_BE]->SetLow (m_low); + m_queues[AC_BE]->SetManager (m_dcfManager); + m_queues[AC_BE]->SetTypeOfStation (ADHOC_STA); + m_queues[AC_BE]->SetTxMiddle (m_txMiddle); +} + +void +QadhocWifiMac::SetBKQueue (Ptr bkQueue) +{ + m_bkEdca = bkQueue; + m_queues.insert (std::make_pair(AC_BK, m_bkEdca)); + m_queues[AC_BK]->SetLow (m_low); + m_queues[AC_BK]->SetManager (m_dcfManager); + m_queues[AC_BK]->SetTypeOfStation (ADHOC_STA); + m_queues[AC_BK]->SetTxMiddle (m_txMiddle); +} + +} //namespace ns3 diff --git a/src/devices/wifi/qadhoc-wifi-mac.h b/src/devices/wifi/qadhoc-wifi-mac.h new file mode 100644 index 000000000..52573c46d --- /dev/null +++ b/src/devices/wifi/qadhoc-wifi-mac.h @@ -0,0 +1,120 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006, 2009 INRIA + * Copyright (c) 2009 MIRKO BANCHI + * + * 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 + * Author: Mirko Banchi + */ +#ifndef QADHOC_WIFI_MAC_H +#define QADHOC_WIFI_MAC_H + +#include "ns3/mac48-address.h" +#include "ns3/callback.h" +#include "ns3/packet.h" + +#include "wifi-mac.h" +#include "qos-utils.h" +#include "amsdu-subframe-header.h" + +namespace ns3 { + +class EdcaTxopN; +class WifiMacHeader; +class WifiPhy; +class DcfManager; +class MacLow; +class MacRxMiddle; + +class QadhocWifiMac : public WifiMac +{ +public: + static TypeId GetTypeId (void); + + QadhocWifiMac (); + ~QadhocWifiMac (); + + // all inherited from WifiMac base class. + virtual void SetSlot (Time slotTime); + virtual void SetSifs (Time sifs); + virtual void SetEifsNoDifs (Time eifsNoDifs); + virtual void SetAckTimeout (Time ackTimeout); + virtual void SetCtsTimeout (Time ctsTimeout); + virtual void SetPifs (Time pifs); + virtual Time GetSlot (void) const; + virtual Time GetSifs (void) const; + virtual Time GetEifsNoDifs (void) const; + virtual Time GetAckTimeout (void) const; + virtual Time GetCtsTimeout (void) const; + virtual Time GetPifs (void) const; + virtual void SetWifiPhy (Ptr phy); + virtual void SetWifiRemoteStationManager (Ptr stationManager); + virtual void Enqueue (Ptr packet, Mac48Address to, Mac48Address from); + virtual void Enqueue (Ptr packet, Mac48Address to); + virtual bool SupportsSendFrom (void) const; + virtual void SetForwardUpCallback (Callback, Mac48Address, Mac48Address> upCallback); + virtual void SetLinkUpCallback (Callback linkUp); + virtual void SetLinkDownCallback (Callback linkDown); + virtual Mac48Address GetAddress (void) const; + virtual Ssid GetSsid (void) const; + virtual void SetAddress (Mac48Address address); + virtual void SetSsid (Ssid ssid); + virtual Mac48Address GetBssid (void) const; + +private: + Callback, Mac48Address, Mac48Address> m_forwardUp; + virtual void DoDispose (void); + void Receive (Ptr packet, WifiMacHeader const *hdr); + void ForwardUp (Ptr packet, Mac48Address from, Mac48Address to); + + /** + * When an A-MSDU is received, is deaggregated by this method and all extracted packets are + * forwarded up. + */ + void DeaggregateAmsduAndForward (Ptr aggregatedPacket, WifiMacHeader const *hdr); + + typedef std::map > Queues; + typedef std::list, AmsduSubframeHeader> > DeaggregatedMsdus; + typedef std::list, AmsduSubframeHeader> >::const_iterator DeaggregatedMsdusCI; + + Ptr GetVOQueue (void) const; + Ptr GetVIQueue (void) const; + Ptr GetBEQueue (void) const; + Ptr GetBKQueue (void) const; + + void SetVOQueue (Ptr voQueue); + void SetVIQueue (Ptr viQueue); + void SetBEQueue (Ptr beQueue); + void SetBKQueue (Ptr bkQueue); + + Queues m_queues; + Ptr m_voEdca; + Ptr m_viEdca; + Ptr m_beEdca; + Ptr m_bkEdca; + Ptr m_low; + Ptr m_phy; + Ptr m_stationManager; + MacRxMiddle *m_rxMiddle; + MacTxMiddle *m_txMiddle; + DcfManager *m_dcfManager; + Ssid m_ssid; + Time m_eifsNoDifs; +}; + +} //namespace ns3 + +#endif /* QADHOC_WIFI_MAC_H */ diff --git a/src/devices/wifi/qap-wifi-mac.cc b/src/devices/wifi/qap-wifi-mac.cc new file mode 100644 index 000000000..fae27f94a --- /dev/null +++ b/src/devices/wifi/qap-wifi-mac.cc @@ -0,0 +1,790 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006, 2009 INRIA + * Copyright (c) 2009 MIRKO BANCHI + * + * 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 + * Author: Mirko Banchi + */ +#include "ns3/assert.h" +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/string.h" +#include "ns3/pointer.h" + +#include "qos-tag.h" +#include "qap-wifi-mac.h" +#include "dca-txop.h" +#include "edca-txop-n.h" +#include "wifi-phy.h" +#include "dcf-manager.h" +#include "mac-rx-middle.h" +#include "mac-tx-middle.h" +#include "mgt-headers.h" +#include "mac-low.h" +#include "amsdu-subframe-header.h" +#include "msdu-aggregator.h" + +NS_LOG_COMPONENT_DEFINE ("QapWifiMac"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (QapWifiMac); + +TypeId +QapWifiMac::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::QapWifiMac") + .SetParent () + .AddConstructor () + .AddAttribute ("BeaconInterval", "Delay between two beacons", + TimeValue (Seconds (0.1)), + MakeTimeAccessor (&QapWifiMac::GetBeaconInterval, + &QapWifiMac::SetBeaconInterval), + MakeTimeChecker ()) + .AddAttribute ("BeaconGeneration", "Whether or not beacons are generated.", + BooleanValue (true), + MakeBooleanAccessor (&QapWifiMac::SetBeaconGeneration, + &QapWifiMac::GetBeaconGeneration), + MakeBooleanChecker ()) + .AddAttribute ("VO_EdcaTxopN", + "Queue that manages packets belonging to AC_VO access class", + PointerValue (), + MakePointerAccessor(&QapWifiMac::GetVOQueue, + &QapWifiMac::SetVOQueue), + MakePointerChecker ()) + .AddAttribute ("VI_EdcaTxopN", + "Queue that manages packets belonging to AC_VI access class", + PointerValue (), + MakePointerAccessor(&QapWifiMac::GetVIQueue, + &QapWifiMac::SetVIQueue), + MakePointerChecker ()) + .AddAttribute ("BE_EdcaTxopN", + "Queue that manages packets belonging to AC_BE access class", + PointerValue (), + MakePointerAccessor(&QapWifiMac::GetBEQueue, + &QapWifiMac::SetBEQueue), + MakePointerChecker ()) + .AddAttribute ("BK_EdcaTxopN", + "Queue that manages packets belonging to AC_BK access class", + PointerValue (), + MakePointerAccessor(&QapWifiMac::GetBKQueue, + &QapWifiMac::SetBKQueue), + MakePointerChecker ()) + ; + return tid; +} + +QapWifiMac::QapWifiMac () +{ + NS_LOG_FUNCTION (this); + m_rxMiddle = new MacRxMiddle (); + m_rxMiddle->SetForwardCallback (MakeCallback (&QapWifiMac::Receive, this)); + + m_txMiddle = new MacTxMiddle (); + + m_low = CreateObject (); + m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle)); + + m_dcfManager = new DcfManager (); + m_dcfManager->SetupLowListener (m_low); + + m_beaconDca = CreateObject (); + m_beaconDca->SetAifsn(1); + m_beaconDca->SetMinCw(0); + m_beaconDca->SetMaxCw(0); + m_beaconDca->SetLow (m_low); + m_beaconDca->SetManager (m_dcfManager); +} + +QapWifiMac::~QapWifiMac () +{ + NS_LOG_FUNCTION (this); +} + +void +QapWifiMac::DoDispose () +{ + delete m_rxMiddle; + m_rxMiddle = 0; + delete m_txMiddle; + m_txMiddle = 0; + delete m_dcfManager; + m_dcfManager = 0; + m_low = 0; + m_phy = 0; + m_beaconDca = 0; + m_beaconEvent.Cancel (); + m_voEdca = 0; + m_viEdca = 0; + m_beEdca = 0; + m_bkEdca = 0; + m_stationManager = 0; + std::map >::iterator it = m_queues.begin (); + for (;it != m_queues.end (); it++) + { + it->second = 0; + } + WifiMac::DoDispose (); +} + +void +QapWifiMac::SetBeaconGeneration (bool enable) +{ + NS_LOG_FUNCTION (this << enable); + if (enable) + { + m_beaconEvent = Simulator::ScheduleNow (&QapWifiMac::SendOneBeacon, this); + } + else + { + m_beaconEvent.Cancel (); + } +} + +bool +QapWifiMac::GetBeaconGeneration (void) const +{ + return m_beaconEvent.IsRunning (); +} + +Time +QapWifiMac::GetBeaconInterval (void) const +{ + return m_beaconInterval; +} + +void +QapWifiMac::SetSlot (Time slotTime) +{ + NS_LOG_FUNCTION (this << slotTime); + m_dcfManager->SetSlot (slotTime); + m_low->SetSlotTime (slotTime); +} + +void +QapWifiMac::SetSifs (Time sifs) +{ + NS_LOG_FUNCTION (this << sifs); + m_dcfManager->SetSifs (sifs); + m_low->SetSifs (sifs); +} + +void +QapWifiMac::SetEifsNoDifs (Time eifsNoDifs) +{ + NS_LOG_FUNCTION (this << eifsNoDifs); + m_dcfManager->SetEifsNoDifs (eifsNoDifs); + m_eifsNoDifs = eifsNoDifs; +} + +void +QapWifiMac::SetAckTimeout (Time ackTimeout) +{ + m_low->SetAckTimeout (ackTimeout); +} + +void +QapWifiMac::SetCtsTimeout (Time ctsTimeout) +{ + m_low->SetCtsTimeout (ctsTimeout); +} + +void +QapWifiMac::SetPifs (Time pifs) +{ + m_low->SetPifs (pifs); +} + +Time +QapWifiMac::GetSlot (void) const +{ + return m_low->GetSlotTime (); +} + +Time +QapWifiMac::GetSifs (void) const +{ + return m_low->GetSifs (); +} + +Time +QapWifiMac::GetEifsNoDifs (void) const +{ + return m_eifsNoDifs; +} + +Time +QapWifiMac::GetAckTimeout (void) const +{ + return m_low->GetAckTimeout (); +} + +Time +QapWifiMac::GetCtsTimeout (void) const +{ + return m_low->GetCtsTimeout (); +} + +Time +QapWifiMac::GetPifs (void) const +{ + return m_low->GetPifs (); +} + +void +QapWifiMac::SetWifiPhy (Ptr phy) +{ + NS_LOG_FUNCTION (this << phy); + m_phy = phy; + m_dcfManager->SetupPhyListener (phy); + m_low->SetPhy (phy); +} + +void +QapWifiMac::SetWifiRemoteStationManager (Ptr stationManager) +{ + NS_LOG_FUNCTION (this << stationManager); + m_stationManager = stationManager; + m_voEdca->SetWifiRemoteStationManager (stationManager); + m_viEdca->SetWifiRemoteStationManager (stationManager); + m_beEdca->SetWifiRemoteStationManager (stationManager); + m_bkEdca->SetWifiRemoteStationManager (stationManager); + m_beaconDca->SetWifiRemoteStationManager (stationManager); + m_low->SetWifiRemoteStationManager (stationManager); +} + +void +QapWifiMac::SetForwardUpCallback (Callback, Mac48Address, Mac48Address> upCallback) +{ + NS_LOG_FUNCTION (this); + m_forwardUp = upCallback; +} + +void +QapWifiMac::SetLinkUpCallback (Callback linkUp) +{ + NS_LOG_FUNCTION (this); + if (!linkUp.IsNull ()) + { + linkUp (); + } +} + +void +QapWifiMac::SetLinkDownCallback (Callback linkDown) +{ + NS_LOG_FUNCTION (this); +} + +Mac48Address +QapWifiMac::GetAddress () const +{ + return m_low->GetAddress (); +} + +Ssid +QapWifiMac::GetSsid (void) const +{ + return m_ssid; +} + +void +QapWifiMac::SetAddress (Mac48Address address) +{ + NS_LOG_FUNCTION (address); + m_low->SetAddress (address); + m_low->SetBssid (address); +} + +void +QapWifiMac::SetSsid (Ssid ssid) +{ + NS_LOG_FUNCTION (this << ssid); + m_ssid = ssid; +} + +Mac48Address +QapWifiMac::GetBssid (void) const +{ + return m_low->GetBssid (); +} + +void +QapWifiMac::SetBeaconInterval (Time interval) +{ + NS_LOG_FUNCTION (this << interval); + m_beaconInterval = interval; +} + +void +QapWifiMac::StartBeaconing (void) +{ + NS_LOG_FUNCTION (this); + SendOneBeacon (); +} + +void +QapWifiMac::ForwardUp (Ptr packet, Mac48Address from, Mac48Address to) +{ + NS_LOG_FUNCTION (this << packet << from); + m_forwardUp (packet, from, to); +} + +void +QapWifiMac::ForwardDown (Ptr packet, Mac48Address from, Mac48Address to) +{ + /* For now Qos AP sends only Qos frame. In the future it should be able to + send frames also to Non-Qos Stas. + */ + NS_LOG_FUNCTION (this << packet << from << to); + WifiMacHeader hdr; + hdr.SetType (WIFI_MAC_QOSDATA); + hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK); + hdr.SetQosNoEosp (); + hdr.SetQosNoAmsdu (); + /* Transmission of multiple frames in the same + Txop is not supported for now */ + hdr.SetQosTxopLimit (0); + + hdr.SetAddr1 (to); + hdr.SetAddr2 (GetAddress ()); + hdr.SetAddr3 (from); + hdr.SetDsFrom (); + hdr.SetDsNotTo (); + + uint8_t tid = QosUtilsGetTidForPacket (packet); + if (tid < 8) + { + hdr.SetQosTid (tid); + AccessClass ac = QosUtilsMapTidToAc (tid); + m_queues[ac]->Queue (packet, hdr); + } + else + { + //packet is considerated belonging to BestEffort AC + hdr.SetQosTid (0); + m_queues[AC_BE]->Queue (packet, hdr); + } +} + +void +QapWifiMac::ForwardDown (Ptr packet, Mac48Address from, Mac48Address to, + WifiMacHeader const *oldHdr) +{ + /* For now Qos AP sends only Qos frame. In the future it should be able to + send frames also to Non-Qos Stas. + */ + NS_LOG_FUNCTION (this << packet << from << to); + NS_ASSERT (oldHdr->IsQosData ()); + WifiMacHeader hdr; + hdr.SetType (WIFI_MAC_QOSDATA); + hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK); + hdr.SetQosNoEosp (); + hdr.SetQosNoAmsdu (); + /* Transmission of multiple frames in the same + Txop is not supported for now */ + hdr.SetQosTxopLimit (0); + hdr.SetQosTid (oldHdr->GetQosTid ()); + + hdr.SetAddr1 (to); + hdr.SetAddr2 (GetAddress ()); + hdr.SetAddr3 (from); + hdr.SetDsFrom (); + hdr.SetDsNotTo (); + + AccessClass ac = QosUtilsMapTidToAc (oldHdr->GetQosTid ()); + m_queues[ac]->Queue (packet, hdr); +} + +void +QapWifiMac::Enqueue (Ptr packet, Mac48Address to, Mac48Address from) +{ + NS_LOG_FUNCTION (this << packet << from << to); + ForwardDown (packet, from, to); +} + +void +QapWifiMac::Enqueue (Ptr packet, Mac48Address to) +{ + NS_LOG_FUNCTION (this << packet << to); + ForwardDown (packet, m_low->GetAddress (), to); +} + +bool +QapWifiMac::SupportsSendFrom (void) const +{ + return true; +} + +SupportedRates +QapWifiMac::GetSupportedRates (void) const +{ + // send the set of supported rates and make sure that we indicate + // the Basic Rate set in this set of supported rates. + SupportedRates rates; + for (uint32_t i = 0; i < m_phy->GetNModes (); i++) + { + WifiMode mode = m_phy->GetMode (i); + rates.AddSupportedRate (mode.GetDataRate ()); + } + // set the basic rates + for (uint32_t j = 0; j < m_stationManager->GetNBasicModes (); j++) + { + WifiMode mode = m_stationManager->GetBasicMode (j); + rates.SetBasicRate (mode.GetDataRate ()); + } + return rates; +} + +void +QapWifiMac::SendProbeResp (Mac48Address to) +{ + NS_LOG_FUNCTION (this << to); + WifiMacHeader hdr; + hdr.SetProbeResp (); + hdr.SetAddr1 (to); + hdr.SetAddr2 (GetAddress ()); + hdr.SetAddr3 (GetAddress ()); + hdr.SetDsNotFrom (); + hdr.SetDsNotTo (); + Ptr packet = Create (); + MgtProbeResponseHeader probe; + probe.SetSsid (GetSsid ()); + probe.SetSupportedRates (GetSupportedRates ()); + probe.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ()); + packet->AddHeader (probe); + + /* Which is correct queue for management frames ? */ + m_queues[AC_VO]->Queue (packet, hdr); +} + +void +QapWifiMac::SendAssocResp (Mac48Address to, bool success) +{ + NS_LOG_FUNCTION (this << to << success); + WifiMacHeader hdr; + hdr.SetAssocResp (); + hdr.SetAddr1 (to); + hdr.SetAddr2 (GetAddress ()); + hdr.SetAddr3 (GetAddress ()); + hdr.SetDsNotFrom (); + hdr.SetDsNotTo (); + Ptr packet = Create (); + MgtAssocResponseHeader assoc; + StatusCode code; + if (success) + { + code.SetSuccess (); + } + else + { + code.SetFailure (); + } + assoc.SetSupportedRates (GetSupportedRates ()); + assoc.SetStatusCode (code); + packet->AddHeader (assoc); + + /* Which is correct queue for management frames ? */ + m_queues[AC_VO]->Queue (packet, hdr); +} + +void +QapWifiMac::SendOneBeacon (void) +{ + NS_LOG_FUNCTION (this); + WifiMacHeader hdr; + hdr.SetBeacon (); + hdr.SetAddr1 (Mac48Address::GetBroadcast ()); + hdr.SetAddr2 (GetAddress ()); + hdr.SetAddr3 (GetAddress ()); + hdr.SetDsNotFrom (); + hdr.SetDsNotTo (); + Ptr packet = Create (); + MgtBeaconHeader beacon; + beacon.SetSsid (GetSsid ()); + beacon.SetSupportedRates (GetSupportedRates ()); + beacon.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ()); + + packet->AddHeader (beacon); + + m_beaconDca->Queue (packet, hdr); + m_beaconEvent = Simulator::Schedule (m_beaconInterval, &QapWifiMac::SendOneBeacon, this); +} + +void +QapWifiMac::TxOk (WifiMacHeader const &hdr) +{ + NS_LOG_FUNCTION (this); + WifiRemoteStation *station = m_stationManager->Lookup (hdr.GetAddr1 ()); + if (hdr.IsAssocResp () && + station->IsWaitAssocTxOk ()) + { + NS_LOG_DEBUG ("associated with sta="<RecordGotAssocTxOk (); + } +} + +void +QapWifiMac::TxFailed (WifiMacHeader const &hdr) +{ + NS_LOG_FUNCTION (this); + WifiRemoteStation *station = m_stationManager->Lookup (hdr.GetAddr1 ()); + if (hdr.IsAssocResp () && + station->IsWaitAssocTxOk ()) + { + NS_LOG_DEBUG ("assoc failed with sta="<RecordGotAssocTxFailed (); + } +} + +void +QapWifiMac::Receive (Ptr packet, WifiMacHeader const *hdr) +{ + NS_LOG_FUNCTION (this << packet << hdr); + + Mac48Address from = hdr->GetAddr2 (); + WifiRemoteStation *fromStation = m_stationManager->Lookup (from); + + if (hdr->IsData ()) + { + Mac48Address bssid = hdr->GetAddr1 (); + if (!hdr->IsFromDs () && + hdr->IsToDs () && + bssid == GetAddress () && + fromStation->IsAssociated ()) + { + Mac48Address to = hdr->GetAddr3 (); + WifiRemoteStation *toStation = m_stationManager->Lookup (to); + + if (to == GetAddress ()) + { + NS_LOG_DEBUG ("frame for me (Qap) from="<IsQosData ()) + { + if (hdr->IsQosAmsdu ()) + { + NS_LOG_DEBUG ("Received A-MSDU from="< + * Author: Mirko Banchi + */ +#ifndef QAP_WIFI_MAC_H +#define QAP_WIFI_MAC_H + +#include "ns3/mac48-address.h" +#include "ns3/callback.h" +#include "ns3/packet.h" +#include "ns3/nstime.h" +#include "ns3/event-id.h" + +#include "supported-rates.h" +#include "wifi-remote-station-manager.h" +#include "wifi-mac.h" +#include "qos-utils.h" + +#include + +namespace ns3 { + +class DcaTxop; +class EdcaTxopN; +class WifiMacHeader; +class WifiPhy; +class MacLow; +class MacRxMiddle; +class MacTxMiddle; +class DcfManager; +class AmsduSubframeHeader; +class MsduAggregator; + +class QapWifiMac : public WifiMac +{ +public: + static TypeId GetTypeId (void); + QapWifiMac (); + virtual ~QapWifiMac (); + + // inherited from WifiMac. + virtual void SetSlot (Time slotTime); + virtual void SetSifs (Time sifs); + virtual void SetEifsNoDifs (Time eifsNoDifs); + virtual void SetAckTimeout (Time ackTimeout); + virtual void SetCtsTimeout (Time ctsTimeout); + virtual void SetPifs (Time pifs); + virtual Time GetSlot (void) const; + virtual Time GetSifs (void) const; + virtual Time GetEifsNoDifs (void) const; + virtual Time GetAckTimeout (void) const; + virtual Time GetCtsTimeout (void) const; + virtual Time GetPifs (void) const; + virtual void SetWifiPhy (Ptr phy); + virtual void SetWifiRemoteStationManager (Ptr stationManager); + virtual void Enqueue (Ptr packet, Mac48Address to, Mac48Address from); + virtual void Enqueue (Ptr packet, Mac48Address to); + virtual bool SupportsSendFrom (void) const; + virtual void SetForwardUpCallback (Callback, Mac48Address, Mac48Address> upCallback); + virtual void SetLinkUpCallback (Callback linkUp); + virtual void SetLinkDownCallback (Callback linkDown); + virtual Mac48Address GetAddress (void) const; + virtual Ssid GetSsid (void) const; + virtual void SetAddress (Mac48Address address); + virtual void SetSsid (Ssid ssid); + virtual Mac48Address GetBssid (void) const; + + void SetBeaconInterval (Time interval); + Time GetBeaconInterval (void) const; + void StartBeaconing (void); + +private: + virtual void DoDispose (void); + void Receive (Ptr packet, WifiMacHeader const *hdr); + void ForwardUp (Ptr packet, Mac48Address from, Mac48Address to); + void ForwardDown (Ptr packet, Mac48Address from, Mac48Address to); + /* Next function is invoked only when ap relies a frame. */ + void ForwardDown (Ptr packet, Mac48Address from, Mac48Address to, + WifiMacHeader const *oldHdr); + void TxOk (WifiMacHeader const &hdr); + void TxFailed (WifiMacHeader const &hdr); + void SendProbeResp (Mac48Address to); + void SendAssocResp (Mac48Address to, bool success); + void SendOneBeacon (void); + SupportedRates GetSupportedRates (void) const; + void SetBeaconGeneration (bool enable); + bool GetBeaconGeneration (void) const; + + void DeaggregateAmsduAndForward (Ptr aggregatedPacket, WifiMacHeader const *hdr); + + typedef std::map > Queues; + typedef std::list, AmsduSubframeHeader> > DeaggregatedMsdus; + typedef std::list, AmsduSubframeHeader> >::const_iterator DeaggregatedMsdusCI; + + Callback, Mac48Address, Mac48Address> m_forwardUp; + + Ptr GetVOQueue (void) const; + Ptr GetVIQueue (void) const; + Ptr GetBEQueue (void) const; + Ptr GetBKQueue (void) const; + + void SetVOQueue (Ptr voQueue); + void SetVIQueue (Ptr viQueue); + void SetBEQueue (Ptr beQueue); + void SetBKQueue (Ptr bkQueue); + + /*Next map is used only for an esay access to a specific queue*/ + Queues m_queues; + Ptr m_voEdca; + Ptr m_viEdca; + Ptr m_beEdca; + Ptr m_bkEdca; + Ptr m_beaconDca; + Ptr m_low; + Ptr m_phy; + Ptr m_stationManager; + MacRxMiddle *m_rxMiddle; + MacTxMiddle *m_txMiddle; + DcfManager *m_dcfManager; + Ssid m_ssid; + EventId m_beaconEvent; + Time m_beaconInterval; + Time m_eifsNoDifs; +}; + +} //namespace ns3 + +#endif /* QAP_WIFI_MAC_H */ diff --git a/src/devices/wifi/qsta-wifi-mac.cc b/src/devices/wifi/qsta-wifi-mac.cc new file mode 100644 index 000000000..3bcaca399 --- /dev/null +++ b/src/devices/wifi/qsta-wifi-mac.cc @@ -0,0 +1,768 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006, 2009 INRIA + * Copyright (c) 2009 MIRKO BANCHI + * + * 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 + * Author: Mirko Banchi + */ +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/string.h" +#include "ns3/pointer.h" + +#include "qos-tag.h" +#include "edca-txop-n.h" +#include "qsta-wifi-mac.h" +#include "mac-low.h" +#include "dcf-manager.h" +#include "mac-rx-middle.h" +#include "mac-tx-middle.h" +#include "wifi-mac-header.h" +#include "msdu-aggregator.h" +#include "amsdu-subframe-header.h" +#include "mgt-headers.h" + +NS_LOG_COMPONENT_DEFINE ("QstaWifiMac"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (QstaWifiMac); + +TypeId +QstaWifiMac::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::QstaWifiMac") + .SetParent () + .AddConstructor () + .AddAttribute ("ProbeRequestTimeout", "The interval between two consecutive probe request attempts.", + TimeValue (Seconds (0.05)), + MakeTimeAccessor (&QstaWifiMac::m_probeRequestTimeout), + MakeTimeChecker ()) + .AddAttribute ("AssocRequestTimeout", "The interval between two consecutive assoc request attempts.", + TimeValue (Seconds (0.5)), + MakeTimeAccessor (&QstaWifiMac::m_assocRequestTimeout), + MakeTimeChecker ()) + .AddAttribute ("MaxMissedBeacons", + "Number of beacons which much be consecutively missed before " + "we attempt to restart association.", + UintegerValue (10), + MakeUintegerAccessor (&QstaWifiMac::m_maxMissedBeacons), + MakeUintegerChecker ()) + .AddAttribute ("ActiveProbing", "If true, we send probe requests. If false, we don't.", + BooleanValue (false), + MakeBooleanAccessor (&QstaWifiMac::SetActiveProbing), + MakeBooleanChecker ()) + .AddAttribute ("VO_EdcaTxopN", + "Queue that manages packets belonging to AC_VO access class", + PointerValue (), + MakePointerAccessor(&QstaWifiMac::GetVOQueue, + &QstaWifiMac::SetVOQueue), + MakePointerChecker ()) + .AddAttribute ("VI_EdcaTxopN", + "Queue that manages packets belonging to AC_VI access class", + PointerValue (), + MakePointerAccessor(&QstaWifiMac::GetVIQueue, + &QstaWifiMac::SetVIQueue), + MakePointerChecker ()) + .AddAttribute ("BE_EdcaTxopN", + "Queue that manages packets belonging to AC_BE access class", + PointerValue (), + MakePointerAccessor(&QstaWifiMac::GetBEQueue, + &QstaWifiMac::SetBEQueue), + MakePointerChecker ()) + .AddAttribute ("BK_EdcaTxopN", + "Queue that manages packets belonging to AC_BK access class", + PointerValue (), + MakePointerAccessor(&QstaWifiMac::GetBKQueue, + &QstaWifiMac::SetBKQueue), + MakePointerChecker ()) + ; + return tid; +} + +QstaWifiMac::QstaWifiMac () + : m_state (BEACON_MISSED), + m_probeRequestEvent (), + m_assocRequestEvent (), + m_beaconWatchdogEnd (Seconds (0.0)) +{ + NS_LOG_FUNCTION (this); + m_rxMiddle = new MacRxMiddle (); + m_rxMiddle->SetForwardCallback (MakeCallback (&QstaWifiMac::Receive, this)); + /*TxMiddle can be shared between all queues */ + m_txMiddle= new MacTxMiddle (); + + m_low = CreateObject (); + m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle)); + + m_dcfManager = new DcfManager (); + m_dcfManager->SetupLowListener (m_low); +} + +QstaWifiMac::~QstaWifiMac () +{ + NS_LOG_FUNCTION (this); +} + +void +QstaWifiMac::DoDispose () +{ + NS_LOG_FUNCTION (this); + delete m_rxMiddle; + delete m_txMiddle; + delete m_dcfManager; + m_rxMiddle = 0; + m_txMiddle = 0; + m_low = 0; + m_phy = 0; + m_dcfManager = 0; + m_voEdca = 0; + m_viEdca = 0; + m_beEdca = 0; + m_bkEdca = 0; + m_stationManager = 0; + std::map >::iterator it = m_queues.begin (); + for (;it != m_queues.end (); it++) + { + it->second = 0; + } + WifiMac::DoDispose (); +} + +void +QstaWifiMac::SetSlot (Time slotTime) +{ + NS_LOG_FUNCTION (this << slotTime); + m_dcfManager->SetSlot (slotTime); + m_low->SetSlotTime (slotTime); +} + +void +QstaWifiMac::SetSifs (Time sifs) +{ + NS_LOG_FUNCTION (this << sifs); + m_dcfManager->SetSifs (sifs); + m_low->SetSifs (sifs); +} + +void +QstaWifiMac::SetEifsNoDifs (Time eifsNoDifs) +{ + NS_LOG_FUNCTION (this << eifsNoDifs); + m_dcfManager->SetEifsNoDifs (eifsNoDifs); + m_eifsNoDifs = eifsNoDifs; +} + +void +QstaWifiMac::SetAckTimeout (Time ackTimeout) +{ + m_low->SetAckTimeout (ackTimeout); +} + +void +QstaWifiMac::SetCtsTimeout (Time ctsTimeout) +{ + m_low->SetCtsTimeout (ctsTimeout); +} + +void +QstaWifiMac::SetPifs (Time pifs) +{ + m_low->SetPifs (pifs); +} + +Time +QstaWifiMac::GetSlot (void) const +{ + return m_low->GetSlotTime (); +} + +Time +QstaWifiMac::GetSifs (void) const +{ + return m_low->GetSifs (); +} + +Time +QstaWifiMac::GetEifsNoDifs (void) const +{ + return m_eifsNoDifs; +} + +Time +QstaWifiMac::GetAckTimeout (void) const +{ + return m_low->GetAckTimeout (); +} + +Time +QstaWifiMac::GetCtsTimeout (void) const +{ + return m_low->GetCtsTimeout (); +} + +Time +QstaWifiMac::GetPifs (void) const +{ + return m_low->GetPifs (); +} + +void +QstaWifiMac::SetWifiPhy (Ptr phy) +{ + m_phy = phy; + m_dcfManager->SetupPhyListener (phy); + m_low->SetPhy (phy); +} + +void +QstaWifiMac::SetWifiRemoteStationManager (Ptr stationManager) +{ + m_stationManager = stationManager; + m_queues[AC_VO]->SetWifiRemoteStationManager (stationManager); + m_queues[AC_VI]->SetWifiRemoteStationManager (stationManager); + m_queues[AC_BE]->SetWifiRemoteStationManager (stationManager); + m_queues[AC_BK]->SetWifiRemoteStationManager (stationManager); + m_low->SetWifiRemoteStationManager (stationManager); +} + +void +QstaWifiMac::SetForwardUpCallback (Callback, Mac48Address, Mac48Address> upCallback) +{ + m_forwardUp = upCallback; +} + +void +QstaWifiMac::SetLinkUpCallback (Callback linkUp) +{ + m_linkUp = linkUp; +} + +void +QstaWifiMac::SetLinkDownCallback (Callback linkDown) +{ + m_linkDown = linkDown; +} + +Mac48Address +QstaWifiMac::GetAddress (void) const +{ + return m_low->GetAddress (); +} + +Ssid +QstaWifiMac::GetSsid (void) const +{ + return m_ssid; +} + +Mac48Address +QstaWifiMac::GetBssid () const +{ + return m_low->GetBssid (); +} + +void +QstaWifiMac::SetAddress (Mac48Address address) +{ + NS_LOG_FUNCTION (this << address); + m_low->SetAddress (address); +} + +void +QstaWifiMac::SetSsid (Ssid ssid) +{ + NS_LOG_FUNCTION (this << ssid); + m_ssid = ssid; +} + +void +QstaWifiMac::SetMaxMissedBeacons (uint32_t missed) +{ + NS_LOG_FUNCTION (this << missed); + m_maxMissedBeacons = missed; +} + +void +QstaWifiMac::SetProbeRequestTimeout (Time timeout) +{ + NS_LOG_FUNCTION (this << timeout); + m_probeRequestTimeout = timeout; +} + +void +QstaWifiMac::SetAssocRequestTimeout (Time timeout) +{ + NS_LOG_FUNCTION (this << timeout); + m_assocRequestTimeout = timeout; +} + +void +QstaWifiMac::StartActiveAssociation (void) +{ + NS_LOG_FUNCTION (this); + TryToEnsureAssociated (); +} + +Mac48Address +QstaWifiMac::GetBroadcastBssid (void) +{ + return Mac48Address::GetBroadcast (); +} + +void +QstaWifiMac::SetBssid (Mac48Address bssid) +{ + NS_LOG_FUNCTION (this << bssid); + m_low->SetBssid (bssid); +} + +void +QstaWifiMac::SetActiveProbing (bool enable) +{ + NS_LOG_FUNCTION (this << enable); + if (enable) + { + TryToEnsureAssociated (); + } + else + { + m_probeRequestEvent.Cancel (); + } +} + +void +QstaWifiMac::ForwardUp (Ptr packet, Mac48Address from, Mac48Address to) +{ + NS_LOG_FUNCTION (this << packet << from << to); + m_forwardUp (packet, from, to); +} + +void +QstaWifiMac::SendProbeRequest (void) +{ + NS_LOG_FUNCTION (this); + WifiMacHeader hdr; + hdr.SetProbeReq (); + hdr.SetAddr1 (GetBroadcastBssid ()); + hdr.SetAddr2 (GetAddress ()); + hdr.SetAddr3 (GetBroadcastBssid ()); + hdr.SetDsNotFrom (); + hdr.SetDsNotTo (); + Ptr packet = Create (); + MgtProbeRequestHeader probe; + probe.SetSsid (GetSsid ()); + probe.SetSupportedRates (GetSupportedRates ()); + packet->AddHeader (probe); + + /* Which is correct queue for management frames ? */ + m_queues[AC_VO]->Queue (packet, hdr); + + m_probeRequestEvent = Simulator::Schedule (m_probeRequestTimeout, + &QstaWifiMac::ProbeRequestTimeout, this); +} + +void +QstaWifiMac::SendAssociationRequest (void) +{ + NS_LOG_FUNCTION (this << GetBssid ()); + WifiMacHeader hdr; + hdr.SetAssocReq (); + hdr.SetAddr1 (GetBssid ()); + hdr.SetAddr2 (GetAddress ()); + hdr.SetAddr3 (GetBssid ()); + hdr.SetDsNotFrom (); + hdr.SetDsNotTo (); + Ptr packet = Create (); + MgtAssocRequestHeader assoc; + assoc.SetSsid (GetSsid ()); + assoc.SetSupportedRates (GetSupportedRates ()); + packet->AddHeader (assoc); + + /* Which is correct queue for management frames ? */ + m_queues[AC_VO]->Queue (packet, hdr); + + m_assocRequestEvent = Simulator::Schedule (m_assocRequestTimeout, + &QstaWifiMac::AssocRequestTimeout, this); +} + +void +QstaWifiMac::TryToEnsureAssociated (void) +{ + NS_LOG_FUNCTION (this); + switch (m_state) { + case ASSOCIATED: + return; + break; + case WAIT_PROBE_RESP: + /* we have sent a probe request earlier so we + do not need to re-send a probe request immediately. + We just need to wait until probe-request-timeout + or until we get a probe response + */ + break; + case BEACON_MISSED: + /* we were associated but we missed a bunch of beacons + * so we should assume we are not associated anymore. + * We try to initiate a probe request now. + */ + m_linkDown (); + m_state = WAIT_PROBE_RESP; + SendProbeRequest (); + break; + case WAIT_ASSOC_RESP: + /* we have sent an assoc request so we do not need to + re-send an assoc request right now. We just need to + wait until either assoc-request-timeout or until + we get an assoc response. + */ + break; + case REFUSED: + /* we have sent an assoc request and received a negative + assoc resp. We wait until someone restarts an + association with a given ssid. + */ + break; + } +} + +void +QstaWifiMac::AssocRequestTimeout (void) +{ + NS_LOG_FUNCTION (this); + m_state = WAIT_ASSOC_RESP; + SendAssociationRequest (); +} + +void +QstaWifiMac::ProbeRequestTimeout (void) +{ + NS_LOG_FUNCTION (this); + m_state = WAIT_PROBE_RESP; + SendProbeRequest (); +} + +void +QstaWifiMac::MissedBeacons (void) +{ + NS_LOG_FUNCTION (this); + if (m_beaconWatchdogEnd > Simulator::Now ()) + { + m_beaconWatchdog = Simulator::Schedule (m_beaconWatchdogEnd - Simulator::Now (), + &QstaWifiMac::MissedBeacons, this); + return; + } + NS_LOG_DEBUG ("beacon missed"); + m_state = BEACON_MISSED; + TryToEnsureAssociated (); +} + +void +QstaWifiMac::RestartBeaconWatchdog (Time delay) +{ + NS_LOG_FUNCTION (this << delay); + m_beaconWatchdogEnd = std::max (Simulator::Now () + delay, m_beaconWatchdogEnd); + if (Simulator::GetDelayLeft (m_beaconWatchdog) < delay && + m_beaconWatchdog.IsExpired ()) + { + NS_LOG_DEBUG ("really restart watchdog."); + m_beaconWatchdog = Simulator::Schedule (delay, &QstaWifiMac::MissedBeacons, this); + } +} + +bool +QstaWifiMac::IsAssociated () +{ + return (m_state == ASSOCIATED)?true:false; +} + +void +QstaWifiMac::Enqueue (Ptr packet, Mac48Address to) +{ + NS_LOG_FUNCTION (this << packet << to); + if (!IsAssociated ()) + { + TryToEnsureAssociated (); + return; + } + WifiMacHeader hdr; + + hdr.SetType (WIFI_MAC_QOSDATA); + hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK); + hdr.SetQosNoAmsdu (); + hdr.SetQosNoEosp (); + /* Transmission of multiple frames in the same + Txop is not supported for now */ + hdr.SetQosTxopLimit (0); + + hdr.SetAddr1 (GetBssid ()); + hdr.SetAddr2 (m_low->GetAddress ()); + hdr.SetAddr3 (to); + hdr.SetDsNotFrom (); + hdr.SetDsTo (); + + uint8_t tid = QosUtilsGetTidForPacket (packet); + if (tid < 8) + { + hdr.SetQosTid (tid); + AccessClass ac = QosUtilsMapTidToAc (tid); + m_queues[ac]->Queue (packet, hdr); + } + else + { + //packet is considerated belonging to BestEffort Access Class (AC_BE) + hdr.SetQosTid (0); + m_queues[AC_BE]->Queue (packet, hdr); + } +} + +bool +QstaWifiMac::SupportsSendFrom (void) const +{ + return true; +} + +void +QstaWifiMac::Receive (Ptr packet, const WifiMacHeader *hdr) +{ + NS_LOG_FUNCTION (this); + NS_ASSERT (!hdr->IsCtl ()); + if (hdr->GetAddr1 () != GetAddress () && + !hdr->GetAddr1 ().IsBroadcast ()) + { + NS_LOG_LOGIC ("packet is not for us"); + } + else if (hdr->IsData ()) + { + if (!IsAssociated ()) + { + NS_LOG_LOGIC ("Received data frame while not associated: ignore"); + return; + } + if (!(hdr->IsFromDs () && !hdr->IsToDs ())) + { + NS_LOG_LOGIC ("Received data frame not from the DS: ignore"); + return; + } + if (hdr->GetAddr2 () != GetBssid ()) + { + NS_LOG_LOGIC ("Received data frame not from the BSS we are associated with: ignore"); + return; + } + if (hdr->GetAddr3 () != GetAddress ()) + { + if (hdr->IsQosData ()) + { + if (hdr->IsQosAmsdu ()) + { + NS_ASSERT (hdr->GetAddr3 () == GetBssid ()); + DeaggregateAmsduAndForward (packet, hdr); + packet = 0; + } + else + { + ForwardUp (packet, hdr->GetAddr3 (), hdr->GetAddr1 ()); + } + } + else + { + ForwardUp (packet, hdr->GetAddr3 (), hdr->GetAddr1 ()); + } + } + } + else if (hdr->IsBeacon ()) + { + MgtBeaconHeader beacon; + packet->RemoveHeader (beacon); + bool goodBeacon = false; + if (GetSsid ().IsBroadcast () || + beacon.GetSsid ().IsEqual (GetSsid ())) + { + goodBeacon = true; + } + if (IsAssociated () && hdr->GetAddr3 () != GetBssid ()) + { + goodBeacon = false; + } + if (goodBeacon) + { + Time delay = MicroSeconds (beacon.GetBeaconIntervalUs () * m_maxMissedBeacons); + RestartBeaconWatchdog (delay); + SetBssid (hdr->GetAddr3 ()); + } + if (goodBeacon && m_state == BEACON_MISSED) + { + m_state = WAIT_ASSOC_RESP; + SendAssociationRequest (); + } + } + else if (hdr->IsProbeResp ()) + { + if (m_state == WAIT_PROBE_RESP) + { + MgtProbeResponseHeader probeResp; + packet->RemoveHeader (probeResp); + if (!probeResp.GetSsid ().IsEqual (GetSsid ())) + { + //not a probe resp for our ssid. + return; + } + SetBssid (hdr->GetAddr3 ()); + Time delay = MicroSeconds (probeResp.GetBeaconIntervalUs () * m_maxMissedBeacons); + RestartBeaconWatchdog (delay); + if (m_probeRequestEvent.IsRunning ()) + { + m_probeRequestEvent.Cancel (); + } + m_state = WAIT_ASSOC_RESP; + SendAssociationRequest (); + } + } + else if (hdr->IsAssocResp ()) + { + if (m_state == WAIT_ASSOC_RESP) + { + MgtAssocResponseHeader assocResp; + packet->RemoveHeader (assocResp); + if (m_assocRequestEvent.IsRunning ()) + { + m_assocRequestEvent.Cancel (); + } + if (assocResp.GetStatusCode ().IsSuccess ()) + { + m_state = ASSOCIATED; + NS_LOG_DEBUG ("assoc completed"); + SupportedRates rates = assocResp.GetSupportedRates (); + WifiRemoteStation *ap = m_stationManager->Lookup (hdr->GetAddr2 ()); + for (uint32_t i = 0; i < m_phy->GetNModes (); i++) + { + WifiMode mode = m_phy->GetMode (i); + if (rates.IsSupportedRate (mode.GetDataRate ())) + { + ap->AddSupportedMode (mode); + if (rates.IsBasicRate (mode.GetDataRate ())) + { + m_stationManager->AddBasicMode (mode); + } + } + } + if (!m_linkUp.IsNull ()) + { + m_linkUp (); + } + } + else + { + NS_LOG_DEBUG ("assoc refused"); + m_state = REFUSED; + } + } + } +} + +SupportedRates +QstaWifiMac::GetSupportedRates (void) const +{ + SupportedRates rates; + for (uint32_t i = 0; i < m_phy->GetNModes (); i++) + { + WifiMode mode = m_phy->GetMode (i); + rates.AddSupportedRate (mode.GetDataRate ()); + } + return rates; +} + +void +QstaWifiMac::DeaggregateAmsduAndForward (Ptr aggregatedPacket, WifiMacHeader const *hdr) +{ + DeaggregatedMsdus packets = MsduAggregator::Deaggregate (aggregatedPacket); + for (DeaggregatedMsdusCI i = packets.begin (); i != packets.end (); ++i) + { + ForwardUp ((*i).first, (*i).second.GetSourceAddr (), + (*i).second.GetDestinationAddr ()); + } +} + +Ptr +QstaWifiMac::GetVOQueue (void) const +{ + return m_voEdca; +} + +Ptr +QstaWifiMac::GetVIQueue (void) const +{ + return m_viEdca; +} + +Ptr +QstaWifiMac::GetBEQueue (void) const +{ + return m_beEdca; +} + +Ptr +QstaWifiMac::GetBKQueue (void) const +{ + return m_bkEdca; +} + +void +QstaWifiMac::SetVOQueue (Ptr voQueue) +{ + m_voEdca = voQueue; + m_queues.insert (std::make_pair(AC_VO, m_voEdca)); + m_queues[AC_VO]->SetLow (m_low); + m_queues[AC_VO]->SetManager (m_dcfManager); + m_queues[AC_VO]->SetTypeOfStation (STA); + m_queues[AC_VO]->SetTxMiddle (m_txMiddle); +} + +void +QstaWifiMac::SetVIQueue (Ptr viQueue) +{ + m_viEdca = viQueue; + m_queues.insert (std::make_pair(AC_VI, m_viEdca)); + m_queues[AC_VI]->SetLow (m_low); + m_queues[AC_VI]->SetManager (m_dcfManager); + m_queues[AC_VI]->SetTypeOfStation (STA); + m_queues[AC_VI]->SetTxMiddle (m_txMiddle); +} + +void +QstaWifiMac::SetBEQueue (Ptr beQueue) +{ + m_beEdca = beQueue; + m_queues.insert (std::make_pair(AC_BE, m_beEdca)); + m_queues[AC_BE]->SetLow (m_low); + m_queues[AC_BE]->SetManager (m_dcfManager); + m_queues[AC_BE]->SetTypeOfStation (STA); + m_queues[AC_BE]->SetTxMiddle (m_txMiddle); +} + +void +QstaWifiMac::SetBKQueue (Ptr bkQueue) +{ + m_bkEdca = bkQueue; + m_queues.insert (std::make_pair(AC_BK, m_bkEdca)); + m_queues[AC_BK]->SetLow (m_low); + m_queues[AC_BK]->SetManager (m_dcfManager); + m_queues[AC_BK]->SetTypeOfStation (STA); + m_queues[AC_BK]->SetTxMiddle (m_txMiddle); +} + +} //namespace ns3 diff --git a/src/devices/wifi/qsta-wifi-mac.h b/src/devices/wifi/qsta-wifi-mac.h new file mode 100644 index 000000000..68edb913d --- /dev/null +++ b/src/devices/wifi/qsta-wifi-mac.h @@ -0,0 +1,168 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006, 2009 INRIA + * Copyright (c) 2009 MIRKO BANCHI + * + * 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 + * Author: Mirko Banchi + */ +#ifndef QSTA_WIFI_MAC_H +#define QSTA_WIFI_MAC_H + +#include "ns3/callback.h" +#include "ns3/packet.h" +#include "ns3/event-id.h" + +#include "wifi-mac.h" +#include "supported-rates.h" +#include "qos-utils.h" + +#include +#include +#include +#include + +namespace ns3 { + +class DcfManager; +class EdcaTxopN; +class MacRxMiddle; +class MacTxMiddle; +class MacLow; +class WifiMacHeader; +class AmsduSubframeHeader; +class MsduAggregator; + +class QstaWifiMac : public WifiMac +{ +public: + static TypeId GetTypeId (void); + + QstaWifiMac (); + virtual ~QstaWifiMac (); + + // inherited from WifiMac. + virtual void SetSlot (Time slotTime); + virtual void SetSifs (Time sifs); + virtual void SetEifsNoDifs (Time eifsNoDifs); + virtual void SetAckTimeout (Time ackTimeout); + virtual void SetCtsTimeout (Time ctsTimeout); + virtual void SetPifs (Time pifs); + virtual Time GetSlot (void) const; + virtual Time GetSifs (void) const; + virtual Time GetEifsNoDifs (void) const; + virtual Time GetAckTimeout (void) const; + virtual Time GetCtsTimeout (void) const; + virtual Time GetPifs (void) const; + virtual void SetWifiPhy (Ptr phy); + virtual void SetWifiRemoteStationManager (Ptr stationManager); + virtual void Enqueue (Ptr packet, Mac48Address to, Mac48Address from){}; + virtual void Enqueue (Ptr packet, Mac48Address to); + virtual bool SupportsSendFrom (void) const; + virtual void SetForwardUpCallback (Callback, Mac48Address, Mac48Address> upCallback); + virtual void SetLinkUpCallback (Callback linkUp); + virtual void SetLinkDownCallback (Callback linkDown); + virtual Mac48Address GetAddress (void) const; + virtual Ssid GetSsid (void) const; + virtual void SetAddress (Mac48Address address); + virtual void SetSsid (Ssid ssid); + virtual Mac48Address GetBssid (void) const; + + void SetMaxMissedBeacons (uint32_t missed); + void SetProbeRequestTimeout (Time timeout); + void SetAssocRequestTimeout (Time timeout); + void StartActiveAssociation (void); + +private: + void SetBssid (Mac48Address bssid); + Mac48Address GetBroadcastBssid (void); + void Receive (Ptr p, const WifiMacHeader *hdr); + void ForwardUp (Ptr packet, Mac48Address from, Mac48Address to); + void SetActiveProbing (bool enable); + bool GetActiveProbing (void) const; + void MissedBeacons (void); + SupportedRates GetSupportedRates (void) const; + void RestartBeaconWatchdog (Time delay); + void AssocRequestTimeout (void); + void ProbeRequestTimeout (void); + void SendAssociationRequest (void); + void SendProbeRequest (void); + void TryToEnsureAssociated (void); + bool IsAssociated (void); + virtual void DoDispose (void); + + /** + * When an A-MSDU is received, is deaggregated by this method and all extracted packets are + * forwarded up. + */ + void DeaggregateAmsduAndForward (Ptr aggregatedPacket, WifiMacHeader const *hdr); + + Ptr GetVOQueue (void) const; + Ptr GetVIQueue (void) const; + Ptr GetBEQueue (void) const; + Ptr GetBKQueue (void) const; + + void SetVOQueue (Ptr voQueue); + void SetVIQueue (Ptr viQueue); + void SetBEQueue (Ptr beQueue); + void SetBKQueue (Ptr bkQueue); + + typedef std::map > Queues; + typedef std::list, AmsduSubframeHeader> > DeaggregatedMsdus; + typedef std::list, AmsduSubframeHeader> >::const_iterator DeaggregatedMsdusCI; + + enum { + ASSOCIATED, + WAIT_PROBE_RESP, + WAIT_ASSOC_RESP, + BEACON_MISSED, + REFUSED + } m_state; + + /*Next map is used only for an esay access to a specific queue*/ + Queues m_queues; + Ptr m_voEdca; + Ptr m_viEdca; + Ptr m_beEdca; + Ptr m_bkEdca; + + Ptr m_low; + Ptr m_phy; + Ptr m_stationManager; + DcfManager *m_dcfManager; + MacRxMiddle *m_rxMiddle; + MacTxMiddle *m_txMiddle; + Ssid m_ssid; + + Callback, Mac48Address, Mac48Address> m_forwardUp; + Callback m_linkUp; + Callback m_linkDown; + + Time m_probeRequestTimeout; + Time m_assocRequestTimeout; + EventId m_probeRequestEvent; + EventId m_assocRequestEvent; + + Time m_beaconWatchdogEnd; + EventId m_beaconWatchdog; + + uint32_t m_maxMissedBeacons; + Time m_eifsNoDifs; +}; + +} //namespace ns3 + +#endif /* QSTA_WIFI_MAC_H */ diff --git a/src/devices/wifi/wscript b/src/devices/wifi/wscript index 7d91299a3..58a5dc08c 100644 --- a/src/devices/wifi/wscript +++ b/src/devices/wifi/wscript @@ -48,6 +48,13 @@ def build(bld): 'wifi-test.cc', 'qos-tag.cc', 'qos-utils.cc', + 'qadhoc-wifi-mac.cc', + 'qap-wifi-mac.cc', + 'qsta-wifi-mac.cc', + 'edca-txop-n.cc', + 'msdu-aggregator.cc', + 'amsdu-subframe-header.cc', + 'msdu-standard-aggregator.cc', ] headers = bld.new_task_gen('ns3header') headers.module = 'wifi' @@ -82,7 +89,14 @@ def build(bld): 'error-rate-model.h', 'yans-error-rate-model.h', 'dca-txop.h', - 'wifi-mac-header.h' + 'wifi-mac-header.h', + 'qadhoc-wifi-mac.h', + 'qap-wifi-mac.h', + 'qsta-wifi-mac.h', + 'qos-utils.h', + 'edca-txop-n.h', + 'msdu-aggregator.h', + 'amsdu-subframe-header.h', ] obj = bld.create_ns3_program('wifi-phy-test', diff --git a/src/helper/qos-wifi-mac-helper.cc b/src/helper/qos-wifi-mac-helper.cc new file mode 100644 index 000000000..634c80cd0 --- /dev/null +++ b/src/helper/qos-wifi-mac-helper.cc @@ -0,0 +1,191 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 MIRKO BANCHI + * + * 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: Mirko Banchi + */ +#include "qos-wifi-mac-helper.h" +#include "ns3/msdu-aggregator.h" +#include "ns3/wifi-mac.h" +#include "ns3/edca-txop-n.h" +#include "ns3/pointer.h" +#include "ns3/uinteger.h" + +namespace ns3 { + +QosWifiMacHelper::QosWifiMacHelper () +{ + m_aggregators.insert (std::make_pair (AC_VO, ObjectFactory ())); + m_aggregators.insert (std::make_pair (AC_VI, ObjectFactory ())); + m_aggregators.insert (std::make_pair (AC_BE, ObjectFactory ())); + m_aggregators.insert (std::make_pair (AC_BK, ObjectFactory ())); + + m_queues.insert (std::make_pair (AC_VO, ObjectFactory ())); + m_queues.insert (std::make_pair (AC_VI, ObjectFactory ())); + m_queues.insert (std::make_pair (AC_BE, ObjectFactory ())); + m_queues.insert (std::make_pair (AC_BK, ObjectFactory ())); + + m_queues[AC_VO].SetTypeId ("ns3::EdcaTxopN"); + m_queues[AC_VI].SetTypeId ("ns3::EdcaTxopN"); + m_queues[AC_BE].SetTypeId ("ns3::EdcaTxopN"); + m_queues[AC_BK].SetTypeId ("ns3::EdcaTxopN"); +} + +QosWifiMacHelper::~QosWifiMacHelper () +{} + +QosWifiMacHelper +QosWifiMacHelper::Default (void) +{ + QosWifiMacHelper helper; + helper.SetType ("ns3::QstaWifiMac"); + /* For more details about this default parameters see IEE802.11 section 7.3.2.29 */ + helper.SetEdcaParametersForAc (AC_VO,"MinCw", UintegerValue (3), + "MaxCw", UintegerValue (7), + "Aifsn", UintegerValue (2)); + helper.SetEdcaParametersForAc (AC_VI,"MinCw", UintegerValue (7), + "MaxCw", UintegerValue (15), + "Aifsn", UintegerValue (2)); + helper.SetEdcaParametersForAc (AC_BE,"MinCw", UintegerValue (15), + "MaxCw", UintegerValue (1023), + "Aifsn", UintegerValue (3)); + helper.SetEdcaParametersForAc (AC_BK,"MinCw", UintegerValue (15), + "MaxCw", UintegerValue (1023), + "Aifsn", UintegerValue (7)); + return helper; +} + +void +QosWifiMacHelper::SetType (std::string type, + std::string n0, const AttributeValue &v0, + std::string n1, const AttributeValue &v1, + std::string n2, const AttributeValue &v2, + std::string n3, const AttributeValue &v3, + std::string n4, const AttributeValue &v4, + std::string n5, const AttributeValue &v5, + std::string n6, const AttributeValue &v6, + std::string n7, const AttributeValue &v7) +{ + m_mac.SetTypeId (type); + m_mac.Set (n0, v0); + m_mac.Set (n1, v1); + m_mac.Set (n2, v2); + m_mac.Set (n3, v3); + m_mac.Set (n4, v4); + m_mac.Set (n5, v5); + m_mac.Set (n6, v6); + m_mac.Set (n7, v7); +} + +void +QosWifiMacHelper::SetMsduAggregatorForAc (AccessClass accessClass, std::string type, + std::string n0, const AttributeValue &v0, + std::string n1, const AttributeValue &v1, + std::string n2, const AttributeValue &v2, + std::string n3, const AttributeValue &v3) +{ + std::map::iterator it; + it = m_aggregators.find (accessClass); + if (it != m_aggregators.end ()) + { + it->second.SetTypeId (type); + it->second.Set (n0, v0); + it->second.Set (n1, v1); + it->second.Set (n2, v2); + it->second.Set (n3, v3); + } +} + +void +QosWifiMacHelper::SetEdcaParametersForAc (AccessClass accessClass, + std::string n0, const AttributeValue &v0, + std::string n1, const AttributeValue &v1, + std::string n2, const AttributeValue &v2, + std::string n3, const AttributeValue &v3) +{ + std::map::iterator it; + it = m_queues.find (accessClass); + if (it != m_queues.end ()) + { + it->second.Set (n0, v0); + it->second.Set (n1, v1); + it->second.Set (n2, v2); + it->second.Set (n3, v3); + } +} + +Ptr +QosWifiMacHelper::Create (void) const +{ + Ptr mac = m_mac.Create (); + + Ptr edcaQueue; + Ptr aggregator; + std::map::const_iterator itQueue; + std::map::const_iterator itAggr; + + /* Setting for VO queue */ + itQueue = m_queues.find (AC_VO); + itAggr = m_aggregators.find (AC_VO); + + edcaQueue = itQueue->second.Create (); + if (itAggr->second.GetTypeId ().GetUid () != 0) + { + aggregator = itAggr->second.Create (); + edcaQueue->SetMsduAggregator (aggregator); + } + mac->SetAttribute ("VO_EdcaTxopN", PointerValue (edcaQueue)); + + /* Setting for VI queue */ + itQueue = m_queues.find (AC_VI); + itAggr = m_aggregators.find (AC_VI); + + edcaQueue = itQueue->second.Create (); + if (itAggr->second.GetTypeId ().GetUid () != 0) + { + aggregator = itAggr->second.Create (); + edcaQueue->SetMsduAggregator (aggregator); + } + mac->SetAttribute ("VI_EdcaTxopN", PointerValue (edcaQueue)); + + /* Setting for BE queue */ + itQueue = m_queues.find (AC_BE); + itAggr = m_aggregators.find (AC_BE); + + edcaQueue = itQueue->second.Create (); + if (itAggr->second.GetTypeId ().GetUid () != 0) + { + aggregator = itAggr->second.Create (); + edcaQueue->SetMsduAggregator (aggregator); + } + mac->SetAttribute ("BE_EdcaTxopN", PointerValue (edcaQueue)); + + /* Setting for BK queue */ + itQueue = m_queues.find (AC_BK); + itAggr = m_aggregators.find (AC_BK); + + edcaQueue = itQueue->second.Create (); + if (itAggr->second.GetTypeId ().GetUid () != 0) + { + aggregator = itAggr->second.Create (); + edcaQueue->SetMsduAggregator (aggregator); + } + mac->SetAttribute ("BK_EdcaTxopN", PointerValue (edcaQueue)); + + return mac; +} + +} //namespace ns3 diff --git a/src/helper/qos-wifi-mac-helper.h b/src/helper/qos-wifi-mac-helper.h new file mode 100644 index 000000000..ea2c6fdcc --- /dev/null +++ b/src/helper/qos-wifi-mac-helper.h @@ -0,0 +1,123 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 MIRKO BANCHI + * + * 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: Mirko Banchi + */ +#ifndef QOS_WIFI_MAC_HELPER_H +#define QOS_WIFI_MAC_HELPER_H + +#include "wifi-helper.h" +#include "ns3/qos-utils.h" + +#include + +namespace ns3 { + +class QosWifiMacHelper : public WifiMacHelper +{ +public: + QosWifiMacHelper (); + virtual ~QosWifiMacHelper (); + /** + * Create a mac helper in a default working state. + */ + static QosWifiMacHelper Default (void); + /** + * \param type the type of ns3::WifiMac to create. + * \param n0 the name of the attribute to set + * \param v0 the value of the attribute to set + * \param n1 the name of the attribute to set + * \param v1 the value of the attribute to set + * \param n2 the name of the attribute to set + * \param v2 the value of the attribute to set + * \param n3 the name of the attribute to set + * \param v3 the value of the attribute to set + * \param n4 the name of the attribute to set + * \param v4 the value of the attribute to set + * \param n5 the name of the attribute to set + * \param v5 the value of the attribute to set + * \param n6 the name of the attribute to set + * \param v6 the value of the attribute to set + * \param n7 the name of the attribute to set + * \param v7 the value of the attribute to set + * + * All the attributes specified in this method should exist + * in the requested mac. + */ + void SetType (std::string type, + std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (), + std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (), + std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (), + std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (), + std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (), + std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (), + std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (), + std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ()); + /** + * \param accessClass access class for which we are setting aggregator. Possibilities + * are: AC_BK, AC_BE, AC_VI, AC_VO. + * \param aggregatorType type of aggregator. + * \param n0 the name of the attribute to set + * \param v0 the value of the attribute to set + * \param n1 the name of the attribute to set + * \param v1 the value of the attribute to set + * \param n2 the name of the attribute to set + * \param v2 the value of the attribute to set + * \param n3 the name of the attribute to set + * \param v3 the value of the attribute to set + * + * All the attributes specified in this method should exist + * in the requested aggregator. + */ + void SetMsduAggregatorForAc (AccessClass accessClass, std::string type, + std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (), + std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (), + std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (), + std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue ()); + /** + * \param accessClass access class for which we are setting edca params. Possibilities + * are: AC_BK, AC_BE, AC_VI, AC_VO. + * \param n0 the name of the attribute to set + * \param v0 the value of the attribute to set + * \param n1 the name of the attribute to set + * \param v1 the value of the attribute to set + * \param n2 the name of the attribute to set + * \param v2 the value of the attribute to set + * \param n3 the name of the attribute to set + * \param v3 the value of the attribute to set + */ + void SetEdcaParametersForAc (AccessClass accessClass, + std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (), + std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (), + std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (), + std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue ()); +private: + /** + * \returns a newly-created MAC object. + * + * This method implements the pure virtual method defined in \ref ns3::WifiMacHelper. + */ + virtual Ptr Create (void) const; + + ObjectFactory m_mac; + std::map m_queues; + std::map m_aggregators; +}; + +} //namespace ns3 + +#endif /* QOS_WIFI_MAC_HELPER_H */ diff --git a/src/helper/wscript b/src/helper/wscript index 46203b155..97825f307 100644 --- a/src/helper/wscript +++ b/src/helper/wscript @@ -24,6 +24,7 @@ def build(bld): 'yans-wifi-helper.cc', 'v4ping-helper.cc', 'nqos-wifi-mac-helper.cc', + 'qos-wifi-mac-helper.cc', ] headers = bld.new_task_gen('ns3header') @@ -50,6 +51,7 @@ def build(bld): 'yans-wifi-helper.h', 'v4ping-helper.h', 'nqos-wifi-mac-helper.h', + 'qos-wifi-mac-helper.h', ] env = bld.env_of_name('default')