diff --git a/src/devices/mesh/802.11s/dot11s.h b/src/devices/mesh/802.11s/dot11s.h new file mode 100644 index 000000000..004395650 --- /dev/null +++ b/src/devices/mesh/802.11s/dot11s.h @@ -0,0 +1,29 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * 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: Pavel Boyko + * + * This is doxygen module description, don't include + */ +/** + * \ingroup mesh + * \defgroup dot11s IEEE 802.11s draft + * + * \brief IEEE 802.11s (mesh) draft standard implementation + * + * TODO: add documentation on 802.11s implementation here + */ \ No newline at end of file diff --git a/src/devices/mesh/mesh-wifi-beacon.cc b/src/devices/mesh/mesh-wifi-beacon.cc index b6a97701f..e0c8eadc4 100644 --- a/src/devices/mesh/mesh-wifi-beacon.cc +++ b/src/devices/mesh/mesh-wifi-beacon.cc @@ -30,18 +30,18 @@ MeshWifiBeacon::MeshWifiBeacon(Ssid ssid, SupportedRates rates, uint64_t us) m_header.SetBeaconIntervalUs (us); } -void MeshWifiBeacon::AddInformationElement(const WifiInformationElement * ie) +void MeshWifiBeacon::AddInformationElement(Ptr ie) { m_elements.push_back(ie); } namespace { -/// aux sorter -struct IEComparator +/// aux sorter for Ptr +struct PIEComparator { - bool operator()(const WifiInformationElement * a, const WifiInformationElement * b) const + bool operator() (Ptr a, Ptr b) const { - return (*a < *b); + return ((*PeekPointer(a)) < (*PeekPointer(b))); } }; } @@ -50,18 +50,32 @@ Ptr MeshWifiBeacon::CreatePacket() { Ptr packet = Create (); - std::sort(m_elements.begin(), m_elements.end(), IEComparator()); + std::sort(m_elements.begin(), m_elements.end(), PIEComparator()); - std::vector::const_reverse_iterator i; + std::vector< Ptr >::const_reverse_iterator i; for(i = m_elements.rbegin(); i != m_elements.rend(); ++i) { packet->AddHeader(**i); } - packet->AddHeader(Header()); + packet->AddHeader(BeaconHeader()); return packet; } + +WifiMacHeader MeshWifiBeacon::CreateHeader (Mac48Address address) +{ + WifiMacHeader hdr; + + hdr.SetBeacon (); + hdr.SetAddr1 (Mac48Address::GetBroadcast ()); + hdr.SetAddr2 (address); + hdr.SetAddr3 (address); + hdr.SetDsNotFrom (); + hdr.SetDsNotTo (); + + return hdr; +} } // namespace diff --git a/src/devices/mesh/mesh-wifi-beacon.h b/src/devices/mesh/mesh-wifi-beacon.h index 07dfeedc1..bd147424d 100644 --- a/src/devices/mesh/mesh-wifi-beacon.h +++ b/src/devices/mesh/mesh-wifi-beacon.h @@ -25,7 +25,7 @@ #include "ns3/packet.h" #include "ns3/wifi-information-element.h" #include "ns3/mgt-headers.h" // from wifi module -#include "ns3/ssid.h" +#include "ns3/wifi-mac-header.h" #include @@ -49,17 +49,20 @@ public: */ MeshWifiBeacon(Ssid ssid, SupportedRates rates, uint64_t us); /// Read standard Wifi beacon header - MgtBeaconHeader Header () const { return m_header; } + MgtBeaconHeader BeaconHeader () const { return m_header; } /// Add information element - void AddInformationElement (const WifiInformationElement * ie); - /// Create frame = { header + all information elements sorted by ElementId() } - Ptr CreatePacket (); + void AddInformationElement (Ptr ie); + + /// Create wifi header for beacon frame. \param address is sender address + WifiMacHeader CreateHeader (Mac48Address address); + /// Create frame = { beacon header + all information elements sorted by ElementId() } + Ptr CreatePacket (); private: /// Beacon header MgtBeaconHeader m_header; /// List of information elements added - std::vector m_elements; + std::vector< Ptr > m_elements; }; } diff --git a/src/devices/mesh/mesh-wifi-interface-mac-plugin.h b/src/devices/mesh/mesh-wifi-interface-mac-plugin.h new file mode 100644 index 000000000..c7ecb10ae --- /dev/null +++ b/src/devices/mesh/mesh-wifi-interface-mac-plugin.h @@ -0,0 +1,74 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * 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: Pavel Boyko + */ + +#ifndef MESHWIFIINTERFACEMACPLUGIN_H_ +#define MESHWIFIINTERFACEMACPLUGIN_H_ + +#include "ns3/wifi-mac-header.h" +#include "ns3/packet.h" +#include "ns3/mac48-address.h" +#include "ns3/mesh-wifi-beacon.h" +#include "ns3/ref-count-base.h" + +namespace ns3 { + +class MeshWifiInterfaceMac; + +/** + * \ingroup mesh + * + * \brief Common interface for mesh point interface MAC plugins + * + * TODO: plugins description + */ +class MeshWifiInterfaceMacPlugin : public RefCountBase +{ +public: + /// C-tor creates unplugged plugin + MeshWifiInterfaceMacPlugin() { /*do nothing*/} + /// This is for subclasses + virtual ~MeshWifiInterfaceMacPlugin() { /*do nothing*/ } + + /// Each plugin must be installed on interface to work + virtual void SetParent(MeshWifiInterfaceMac * parent) = 0; + /** + * \brief Process received frame + * + * \return false if (and only if) frame should be dropped + * TODO define when MAC call this + */ + virtual bool Receive(Ptr packet, const WifiMacHeader & header) = 0; + /** + * \brief Update frame before it will be forwarded down + * + * \return false if (and only if) frame should be dropped + * TODO define when MAC call this, preconditions & postconditions + */ + virtual bool UpdateOutcomingFrame(Ptr packet, WifiMacHeader & header, Mac48Address from, Mac48Address to) const = 0; + /** + * \brief Update beacon before it will be formed and sent + * + * TODO define when MAC call this + */ + virtual void UpdateBeacon(MeshWifiBeacon & beacon) const; +}; + +} // namespace ns3 +#endif /* MESHWIFIINTERFACEMACPLUGIN_H_ */ diff --git a/src/devices/mesh/mesh-wifi-interface-mac.cc b/src/devices/mesh/mesh-wifi-interface-mac.cc new file mode 100644 index 000000000..14cf9900d --- /dev/null +++ b/src/devices/mesh/mesh-wifi-interface-mac.cc @@ -0,0 +1,549 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * 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 + * + * Authors: Kirill Andreev + * Pavel Boyko + */ + +#include "ns3/mesh-wifi-interface-mac.h" +#include "ns3/mesh-wifi-beacon.h" +#include "ns3/log.h" +#include "ns3/wifi-phy.h" +#include "ns3/dcf-manager.h" +#include "ns3/mac-rx-middle.h" +#include "ns3/mac-low.h" +#include "ns3/dca-txop.h" +#include "ns3/mesh-wifi-mac-header.h" +#include "ns3/random-variable.h" +#include "ns3/simulator.h" + +NS_LOG_COMPONENT_DEFINE ("MeshWifiInterfaceMac"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (MeshWifiInterfaceMac); + +TypeId +MeshWifiInterfaceMac::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::MeshWifiInterfaceMac") + .SetParent () + .AddConstructor () + .AddAttribute ("BeaconInterval", "Beacon Interval", + TimeValue (Seconds (1.0)), + MakeTimeAccessor (&MeshWifiInterfaceMac::m_beaconInterval), + MakeTimeChecker () + ) + .AddAttribute ("RandomStart", "Window when beacon generating starts (uniform random) in seconds", + TimeValue (Seconds (0.1)), + MakeTimeAccessor (&MeshWifiInterfaceMac::m_randomStart), + MakeTimeChecker () + ) + .AddAttribute ("SoftwareDelay", "Window of uniformely distributed random software handling delay", + TimeValue (MicroSeconds (500)), + MakeTimeAccessor (&MeshWifiInterfaceMac::m_softwareDelay), + MakeTimeChecker () + ) + .AddAttribute ("BeaconGeneration", "Enable/Disable Beaconing.", + BooleanValue (true), + MakeBooleanAccessor ( + &MeshWifiInterfaceMac::SetBeaconGeneration, + &MeshWifiInterfaceMac::GetBeaconGeneration + ), + MakeBooleanChecker () + ); + return tid; +} + +MeshWifiInterfaceMac::MeshWifiInterfaceMac () +{ + NS_LOG_FUNCTION (this); + + m_rxMiddle = new MacRxMiddle (); + m_rxMiddle->SetForwardCallback (MakeCallback (&MeshWifiInterfaceMac::Receive, this)); + + 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->SetLow (m_low); + m_beaconDca->SetMinCw (0); + m_beaconDca->SetMaxCw (0); + m_beaconDca->SetAifsn(1); + m_beaconDca->SetManager (m_dcfManager); + + m_VO = CreateObject (); + m_VO->SetLow (m_low); + m_VO->SetMinCw (3); + m_VO->SetMaxCw (7); + m_VO->SetManager (m_dcfManager); + + m_BE = CreateObject (); + m_BE->SetLow (m_low); + m_BE->SetManager (m_dcfManager); +} + +MeshWifiInterfaceMac::~MeshWifiInterfaceMac () +{ + NS_LOG_FUNCTION (this); +} + +//----------------------------------------------------------------------------- +// WifiMac inherited +//----------------------------------------------------------------------------- +void +MeshWifiInterfaceMac::SetSlot (Time slotTime) +{ + NS_LOG_FUNCTION (this << slotTime); + m_dcfManager->SetSlot (slotTime); + m_slot = slotTime; +} + +void +MeshWifiInterfaceMac::SetSifs (Time sifs) +{ + NS_LOG_FUNCTION (this << sifs); + m_dcfManager->SetSifs (sifs); + m_sifs = sifs; +} +void +MeshWifiInterfaceMac::SetAckTimeout (Time ackTimeout) +{ + m_low->SetAckTimeout (ackTimeout); +} + +void +MeshWifiInterfaceMac::SetCtsTimeout (Time ctsTimeout) +{ + m_low->SetCtsTimeout (ctsTimeout); +} + +void +MeshWifiInterfaceMac::SetPifs (Time pifs) +{ + NS_LOG_FUNCTION (this << pifs); + m_pifs = pifs; +} +void +MeshWifiInterfaceMac::SetEifsNoDifs (Time eifsNoDifs) +{ + NS_LOG_FUNCTION (this << eifsNoDifs); + m_dcfManager->SetEifsNoDifs (eifsNoDifs); + m_eifsNoDifs = eifsNoDifs; +} + +Time +MeshWifiInterfaceMac::GetSlot () const + { + return m_slot; + } + +Time +MeshWifiInterfaceMac::GetSifs () const + { + return m_sifs; + } + +Time +MeshWifiInterfaceMac::GetEifsNoDifs () const + { + return m_eifsNoDifs; + } + +Time +MeshWifiInterfaceMac::GetAckTimeout () const + { + return m_low->GetAckTimeout (); + } + +Time +MeshWifiInterfaceMac::GetCtsTimeout () const + { + return m_low->GetCtsTimeout (); + } + +Time +MeshWifiInterfaceMac::GetPifs () const + { + return m_low->GetPifs (); + } + +void +MeshWifiInterfaceMac::SetWifiPhy (Ptr phy) +{ + NS_LOG_FUNCTION (this << phy); + m_phy = phy; + m_dcfManager->SetupPhyListener (phy); + m_low->SetPhy (phy); +} + +void +MeshWifiInterfaceMac::SetWifiRemoteStationManager (Ptr stationManager) +{ + NS_LOG_FUNCTION (this << stationManager); + m_stationManager = stationManager; + m_BE->SetWifiRemoteStationManager (stationManager); + m_VO->SetWifiRemoteStationManager (stationManager); + m_beaconDca->SetWifiRemoteStationManager (stationManager); + m_low->SetWifiRemoteStationManager (stationManager); +} + +void +MeshWifiInterfaceMac::Enqueue (Ptr packet, Mac48Address to, Mac48Address from) +{ + NS_LOG_FUNCTION (this << packet << to << from); + ForwardDown (packet, from, to); +} + +void +MeshWifiInterfaceMac::Enqueue (Ptr packet, Mac48Address to) +{ + NS_LOG_FUNCTION (this << packet << to); + ForwardDown (packet, m_low->GetAddress (), to); +} + +bool +MeshWifiInterfaceMac::SupportsSendFrom () const + { + return true; + } + +void +MeshWifiInterfaceMac::SetForwardUpCallback (Callback, Mac48Address, Mac48Address> upCallback) +{ + NS_LOG_FUNCTION (this); + m_upCallback = upCallback; +} + +void +MeshWifiInterfaceMac::SetLinkUpCallback (Callback linkUp) +{ + NS_LOG_FUNCTION (this); + if (!linkUp.IsNull ()) + { + linkUp (); + } +} + +void +MeshWifiInterfaceMac::SetLinkDownCallback (Callback linkDown) +{ + NS_LOG_FUNCTION (this); +} + +Mac48Address +MeshWifiInterfaceMac::GetAddress () const + { + return m_address; + } +Mac48Address +MeshWifiInterfaceMac::GetBssid () const + { + return m_address; + } + +Ssid +MeshWifiInterfaceMac::GetSsid () const + { + return m_MeshId; + } + +void +MeshWifiInterfaceMac::SetAddress (Mac48Address address) +{ + NS_LOG_FUNCTION (address); + m_low->SetAddress(address); + m_address = address; +} + +void +MeshWifiInterfaceMac::SetSsid (Ssid ssid) +{ + NS_LOG_FUNCTION (ssid); + m_MeshId = ssid; +} + +void +MeshWifiInterfaceMac::DoDispose () +{ + NS_LOG_FUNCTION (this); + delete m_rxMiddle; + delete m_dcfManager; + //Delete smart pointers: + m_rxMiddle = 0; + m_low = 0; + m_dcfManager = 0; + m_phy = 0; + m_BE = 0; + m_VO = 0; + m_beaconSendEvent.Cancel (); + m_beaconDca = 0; + + WifiMac::DoDispose (); +} + +//----------------------------------------------------------------------------- +// Plugins +//----------------------------------------------------------------------------- +void +MeshWifiInterfaceMac::InstallPlugin( Ptr plugin) +{ + plugin->SetParent(this); + m_plugins.push_back(plugin); +} + +//----------------------------------------------------------------------------- +// Forward frame up/down +//----------------------------------------------------------------------------- +void +MeshWifiInterfaceMac::ForwardUp (Ptr packet, Mac48Address src, Mac48Address dst) +{ + NS_LOG_FUNCTION (this << packet << src); + m_upCallback (packet, src, dst); +} + +void +MeshWifiInterfaceMac::ForwardDown (Ptr const_packet, Mac48Address from, Mac48Address to) +{ + // copy packet to allow modifications + Ptr packet = const_packet->Copy(); + + WifiMacHeader hdr; + hdr.SetTypeData (); + hdr.SetAddr2 (GetAddress ()); + hdr.SetAddr3 (to); + hdr.SetAddr4 (from); + hdr.SetDsFrom (); + hdr.SetDsTo (); + + // Address 1 is unknwon here. Routing plugin is responsible to correctly set it. + hdr.SetAddr1 (Mac48Address ()); + + // Filter packet through all installed plugins + for(PluginList::const_iterator i = m_plugins.begin(); i != m_plugins.end(); ++i) + { + bool drop = !((*i)->UpdateOutcomingFrame(packet, hdr, from, to)); + if (drop) return; // plugin drops frame + } + + // Assert that address1 is set. Assert will fail e.g. if there is no installed routing plugin. + NS_ASSERT(hdr.GetAddr1() != Mac48Address() ); + + // Queue frame + 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 (); + } + m_BE->Queue (packet, hdr); +} + +SupportedRates +MeshWifiInterfaceMac::GetSupportedRates () const +{ + // set 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; +} + +//----------------------------------------------------------------------------- +// Beacons +//----------------------------------------------------------------------------- +void +MeshWifiInterfaceMac::SetSoftwareDelay(Time delay) +{ + NS_ASSERT(delay < m_beaconInterval); + m_softwareDelay = delay; +} + +Time +MeshWifiInterfaceMac::GetSoftwareDelay() +{ + return m_softwareDelay; +} + +Time +MeshWifiInterfaceMac::CalcSwDelay() +{ + UniformVariable coefficient(0.0, m_softwareDelay.GetSeconds()); + + // Be sure that frames don't change order due to different software delays + Time delay = Seconds(coefficient.GetValue()); + if (delay.GetSeconds() + Simulator::Now().GetSeconds() < m_lastMgtFrame.GetSeconds()) + delay = Seconds(m_lastMgtFrame.GetSeconds() - Simulator::Now().GetSeconds()); + m_lastMgtFrame = Seconds(Simulator::Now().GetSeconds() + delay.GetSeconds()); + + NS_ASSERT(delay.GetSeconds() >= 0); + return delay; +} + +void +MeshWifiInterfaceMac::SetBeaconInterval (Time interval) +{ + NS_LOG_FUNCTION (this << interval); + m_beaconInterval = interval; + + NS_ASSERT(m_beaconInterval > m_softwareDelay); +} + +Time +MeshWifiInterfaceMac::GetBeaconInterval() const +{ + return m_beaconInterval; +} + +void +MeshWifiInterfaceMac::SetBeaconGeneration (bool enable) +{ + NS_LOG_FUNCTION (this << enable); + if (enable) + { + // Now start sending beacons after some random delay (to avoid collisions) + UniformVariable coefficient(0.0, m_randomStart.GetSeconds()); + Time randomStart = Seconds(coefficient.GetValue()); + + m_beaconSendEvent = Simulator::Schedule (randomStart, &MeshWifiInterfaceMac::SendBeacon, this); + } + else + // stop sending beacons + m_beaconSendEvent.Cancel (); +} + +bool +MeshWifiInterfaceMac::GetBeaconGeneration () const +{ + return m_beaconSendEvent.IsRunning (); +} + +Time +MeshWifiInterfaceMac::GetTBTT() const +{ + return m_tbtt; +} + +void MeshWifiInterfaceMac::ShiftTBTT(Time shift) +{ + // User of ShiftTBTT() must take care don't shift it to the past + NS_ASSERT(GetTBTT() + shift > Simulator::Now()); + + m_tbtt += shift; + // Shift scheduled event + Simulator::Cancel (m_beaconSendEvent); + m_beaconSendEvent = Simulator::Schedule (GetTBTT(), &MeshWifiInterfaceMac::SendBeacon, this); +} + +void +MeshWifiInterfaceMac::ScheduleNextBeacon() +{ + m_tbtt += GetBeaconInterval(); + m_beaconSendEvent = Simulator::Schedule (GetTBTT(), &MeshWifiInterfaceMac::SendBeacon, this); +} + +void +MeshWifiInterfaceMac::SendBeacon () +{ + NS_LOG_FUNCTION (this); + NS_LOG_DEBUG(GetAddress() <<" is sending beacon"); + + NS_ASSERT(! m_beaconSendEvent.IsRunning()); + NS_ASSERT(Simulator::Now() == GetTBTT()); // assert that beacon is just on time + + // Form & send beacon + MeshWifiBeacon beacon(GetSsid (), GetSupportedRates (), m_beaconInterval.GetMicroSeconds ()); + + // Ask all plugins to add their specific information elements to beacon + for(PluginList::const_iterator i = m_plugins.begin(); i != m_plugins.end(); ++i) + (*i)->UpdateBeacon(beacon); + + m_beaconDca->Queue(beacon.CreatePacket(), beacon.CreateHeader(GetAddress())); + + ScheduleNextBeacon(); +} + +void +MeshWifiInterfaceMac::Receive (Ptr packet, WifiMacHeader const *hdr) +{ + // Process beacon + if (hdr->IsBeacon ()) + { + MgtBeaconHeader beacon_hdr; + Mac48Address from = hdr->GetAddr2(); + + packet->PeekHeader (beacon_hdr); + + NS_LOG_DEBUG("Beacon received from "<GetAddr2()<< + " to "<Lookup (hdr->GetAddr2 ()); + + for (uint32_t i = 0; i < m_phy->GetNModes (); i++) + { + WifiMode mode = m_phy->GetMode (i); + if (rates.IsSupportedRate (mode.GetDataRate ())) + { + peerSta->AddSupportedMode (mode); + if (rates.IsBasicRate (mode.GetDataRate ())) + m_stationManager->AddBasicMode (mode); + } + } + } + } + + // Filter frame through all installed plugins + for (PluginList::iterator i = m_plugins.begin(); i != m_plugins.end(); ++i) + { + bool drop = !((*i)->Receive(packet, *hdr)); + if (drop) return; // plugin drops frame + } + + // Forward data up + if (hdr->IsData()) + ForwardUp(packet, hdr->GetAddr4(), hdr->GetAddr3()); +} + +} // namespace ns3 + + + diff --git a/src/devices/mesh/mesh-wifi-interface-mac.h b/src/devices/mesh/mesh-wifi-interface-mac.h new file mode 100644 index 000000000..8a99ce22d --- /dev/null +++ b/src/devices/mesh/mesh-wifi-interface-mac.h @@ -0,0 +1,227 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * 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 + * + * Authors: Kirill Andreev + * Pavel Boyko + */ + +#ifndef MESHWIFIINTERFACEMAC_H_ +#define MESHWIFIINTERFACEMAC_H_ + +#include +#include +#include "ns3/mac48-address.h" +#include "ns3/mac48-address-comparator.h" +#include "ns3/mgt-headers.h" +#include "ns3/mesh-mgt-headers.h" +#include "ns3/callback.h" +#include "ns3/packet.h" +#include "ns3/nstime.h" +#include "ns3/mesh-wifi-beacon-timing-element.h" +#include "ns3/wifi-remote-station-manager.h" +#include "ns3/mesh-wifi-peer-manager.h" +#include "ns3/wifi-mac.h" +#include "ns3/mesh-wifi-interface-mac-plugin.h" + +namespace ns3 { + +class WifiMacHeader; +class DcaTxop; +class WifiPhy; +class DcfManager; +class MacRxMiddle; +class MacLow; +/** + * \ingroup mesh + * + * \brief Basic MAC of mesh point Wi-Fi interface. Its function is extendable through plugins mechanism. + * + * Now only three output queues are used: + * - beacons (PIFS and no backoff), + * - background traffic, + * - management and priority traffic. + * + */ +class MeshWifiInterfaceMac : public WifiMac +{ +public: + /// Never forget to support typeid + static TypeId GetTypeId (); + /// C-tor + MeshWifiInterfaceMac(); + /// D-tor + virtual ~MeshWifiInterfaceMac(); + + ///\name Inherited from WifiMac + //\{ + virtual void SetSlot (Time slotTime); + virtual void SetSifs (Time sifs); + virtual void SetPifs (Time pifs); + virtual void SetCtsTimeout (Time ctsTimeout); + virtual void SetAckTimeout (Time ackTimeout); + virtual void SetEifsNoDifs (Time eifsNoDifs); + virtual Time GetSlot () const; + virtual Time GetSifs () const; + virtual Time GetPifs () const; + virtual Time GetCtsTimeout () const; + virtual Time GetAckTimeout () const; + virtual Time GetEifsNoDifs () 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 () const; + virtual void SetForwardUpCallback (Callback, Mac48Address, Mac48Address> upCallback); + virtual void SetLinkUpCallback (Callback linkUp); + virtual void SetLinkDownCallback (Callback linkDown); + virtual Mac48Address GetAddress () const; + virtual Mac48Address GetBssid () const; + virtual Ssid GetSsid () const; + virtual void SetAddress (Mac48Address address); + virtual void SetSsid (Ssid ssid); + //\} + + ///\name Beacons + //\{ + + /// Set interval between two successive beacons + void SetBeaconInterval (Time interval); + /// \return interval between two beacons + Time GetBeaconInterval () const; + /** + * \brief Next beacon frame time + * + * This is supposed to be used by any entity managing beacon collision avoidance (e.g. Peer management protocol in 802.11s) + */ + Time GetTBTT() const; + /** + * \brief Shift TBTT. + * + * This is supposed to be used by any entity managing beacon collision avoidance (e.g. Peer management protocol in 802.11s) + * + * \attention User of ShiftTBTT() must take care to not shift it to the past. + */ + void ShiftTBTT(Time shift); + /** + * \brief Set maximum software delay. Maximum software delay must be smaller than beacon interval. + * + * Software delay models random small internal delay to avoid simultaneous operation of + * different mesh points (e.g. on power on). + * + * Software delay is calculated as uniformely distributed random value between zero and + * given parameter. All management frames are sent after software delay is passed, + * for example, beacon is formed at software delay before putting it to the queue. + * + * \attention The software delay is supposed to be independent from traffic intensity. + * + * \param delay is the maximum software delay. + */ + void SetSoftwareDelay(Time delay); + /// \return Maximum software delay + Time GetSoftwareDelay(); + + //\} + + ///\name Plugins + //\{ + /// Install plugin. TODO return unique ID to allow unregister plugins + void InstallPlugin(Ptr plugin); + //\} + +private: + /// Frame receive handler + void Receive (Ptr packet, WifiMacHeader const *hdr); + /// Forward frame to mesh point + virtual void ForwardUp (Ptr packet, Mac48Address src, Mac48Address dst); + /// Send frame. Frame is supposed to be tagged by routing information. TODO: clarify this point + void ForwardDown(Ptr packet, Mac48Address from, Mac48Address to); + /// Calc software delay value uniformely distributed between 0 and m_softwareDealy, see SetSoftwareDelay(). + Time CalcSwDelay(); + /// Send beacon + void SendBeacon (); + /// Schedule next beacon + void ScheduleNextBeacon (); + /// Enable/disable beacons + void SetBeaconGeneration (bool enable); + /// Get current beaconing status + bool GetBeaconGeneration () const; + /// Get list of supported bitrates + SupportedRates GetSupportedRates () const; + /// Real d-tor + virtual void DoDispose (); + +private: + ///\name Wifi MAC internals + //\{ + Ptr m_BE; + Ptr m_BK; + Ptr m_VI; + Ptr m_VO; + Ptr m_beaconDca; + Ptr m_stationManager; + Ptr m_phy; + Callback, Mac48Address, Mac48Address> m_upCallback; + //\} + + ///\name Wifi timing intervals + //\{ + Time m_slot; + Time m_sifs; + Time m_pifs; + Time m_ackTimeout; + Time m_ctsTimeout; + Time m_eifsNoDifs; + //\} + + ///\name Mesh timing intervals + //\{ + /// Beaconing interval. + Time m_beaconInterval; + /// Maximum delay before first beacon + Time m_randomStart; + /// Maximum software delay + Time m_softwareDelay; + /// Send time of the last management frame, used to ensure correct frame order + Time m_lastMgtFrame; + /// Time for the next frame + Time m_tbtt; + //\} + + /// DCF implementation + DcfManager* m_dcfManager; + /// Middle MAC sublayer + MacRxMiddle* m_rxMiddle; + /// Low MAX sublayer + Ptr m_low; + /// My address + Mac48Address m_address; + /// SSID + Ssid m_MeshId; + + /// "Timer" for the next beacon + EventId m_beaconSendEvent; + + typedef std::vector< Ptr > PluginList; + /// List of all installed plugins + PluginList m_plugins; +}; + +} // namespace ns3 + + + +#endif /* MESHWIFIINTERFACEMAC_H_ */ diff --git a/src/devices/mesh/wifi-information-element.h b/src/devices/mesh/wifi-information-element.h index 3c2cc1d7a..a989e43a0 100644 --- a/src/devices/mesh/wifi-information-element.h +++ b/src/devices/mesh/wifi-information-element.h @@ -22,6 +22,7 @@ #define WIFIINFORMATIONELEMENT_H_ #include "ns3/header.h" +#include "ns3/ref-count-base.h" namespace ns3 { @@ -70,7 +71,8 @@ enum WifiElementId { * Element ID as defined in this standard. The Length field specifies the number of octets in the Information * field. */ -class WifiInformationElement : public Header +class WifiInformationElement : public Header, + public RefCountBase // need this to use Ptr { public: /// Support object system diff --git a/src/devices/mesh/wscript b/src/devices/mesh/wscript index d48ebec79..89e8daf9a 100644 --- a/src/devices/mesh/wscript +++ b/src/devices/mesh/wscript @@ -4,10 +4,11 @@ def build(bld): obj = bld.create_ns3_module('mesh', ['wifi', '802.11s']) obj.source = [ # Refactored + 'wifi-information-element.cc', 'mesh-point-device.cc', 'mesh-l2-routing-protocol.cc', 'mesh-wifi-beacon.cc', - 'wifi-information-element.cc', + 'mesh-wifi-interface-mac.cc', # Not refactored 'mesh-wifi-helper.cc', 'mesh-wifi-mac-header.cc', @@ -24,10 +25,12 @@ def build(bld): headers.module = 'mesh' headers.source = [ # Refactored + 'wifi-information-element.h', 'mesh-point-device.h', 'mesh-l2-routing-protocol.h', 'mesh-wifi-beacon.h', - 'wifi-information-element.h', + 'mesh-wifi-interface-mac.h', + 'mesh-wifi-interface-mac-plugin.h', # Dirty 'dot11s-codes.h', 'hwmp-state.h',