MeshWifiInterfaceMac just added and beacon generation refactored
authorPavel Boyko <boyko@iitp.ru>
Wed, 18 Mar 2009 16:08:49 +0300
changeset 4843 f65f22ef327e
parent 4842 605a2680b56b
child 4844 3c38e23fa821
MeshWifiInterfaceMac just added and beacon generation refactored
src/devices/mesh/mesh-wifi-beacon.cc
src/devices/mesh/mesh-wifi-beacon.h
src/devices/mesh/mesh-wifi-interface-mac.cc
src/devices/mesh/mesh-wifi-interface-mac.h
src/devices/mesh/wscript
--- a/src/devices/mesh/mesh-wifi-beacon.cc	Wed Mar 18 14:37:29 2009 +0300
+++ b/src/devices/mesh/mesh-wifi-beacon.cc	Wed Mar 18 16:08:49 2009 +0300
@@ -58,10 +58,24 @@
     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 
 
--- a/src/devices/mesh/mesh-wifi-beacon.h	Wed Mar 18 14:37:29 2009 +0300
+++ b/src/devices/mesh/mesh-wifi-beacon.h	Wed Mar 18 16:08:49 2009 +0300
@@ -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 <vector>
 
@@ -49,11 +49,14 @@
    */
   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 (Ptr<WifiInformationElement> ie);
-  /// Create frame = { header + all information elements sorted by ElementId() }
-  Ptr<Packet> CreatePacket (); 
+  
+  /// 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<Packet> CreatePacket ();
   
 private:
   /// Beacon header
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-interface-mac.cc	Wed Mar 18 16:08:49 2009 +0300
@@ -0,0 +1,703 @@
+/* -*- 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 <andreev@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+
+#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<WifiMac> ()
+                      .AddConstructor<MeshWifiInterfaceMac> ()
+                      .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<MacLow> ();
+  m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle));
+
+  m_dcfManager = new DcfManager ();
+  m_dcfManager->SetupLowListener (m_low);
+
+  m_beaconDca = CreateObject<DcaTxop> ();
+  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<DcaTxop> ();
+  m_VO->SetLow (m_low);
+  m_VO->SetMinCw (3);
+  m_VO->SetMaxCw (7);
+  m_VO->SetManager (m_dcfManager);
+
+  m_BE = CreateObject<DcaTxop> ();
+  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<WifiPhy> phy)
+{
+  NS_LOG_FUNCTION (this << phy);
+  m_phy = phy;
+  m_dcfManager->SetupPhyListener (phy);
+  m_low->SetPhy (phy);
+}
+
+void
+MeshWifiInterfaceMac::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> 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<const Packet> packet, Mac48Address to, Mac48Address from)
+{
+  NS_LOG_FUNCTION (this << packet << to << from);
+  ForwardDown (packet, from, to);
+}
+
+void
+MeshWifiInterfaceMac::Enqueue (Ptr<const Packet> 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<void,Ptr<Packet>, Mac48Address, Mac48Address> upCallback)
+{
+  NS_LOG_FUNCTION (this);
+  m_upCallback = upCallback;
+}
+
+void
+MeshWifiInterfaceMac::SetLinkUpCallback (Callback<void> linkUp)
+{
+  NS_LOG_FUNCTION (this);
+  if (!linkUp.IsNull ())
+    {
+      linkUp ();
+    }
+}
+
+void
+MeshWifiInterfaceMac::SetLinkDownCallback (Callback<void> 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 ();
+}
+
+//-----------------------------------------------------------------------------
+// Forward frame up/down
+//-----------------------------------------------------------------------------
+void
+MeshWifiInterfaceMac::ForwardUp (Ptr<Packet> packet, Mac48Address src, Mac48Address dst)
+{
+  NS_LOG_FUNCTION (this << packet << src);
+  m_upCallback (packet, src, dst);
+}
+
+void
+MeshWifiInterfaceMac::ForwardDown (Ptr<const Packet> packet, Mac48Address from, Mac48Address to)
+{
+  // 1. Create and add mesh header using routing information
+  WifiMacHeader hdr;
+  Ptr<Packet> packet_to_send = packet->Copy();
+  
+  /*
+   TODO:
+  for all plugins {
+    plugin.UpdateOutcomingPacket....(packet, from, to);
+  }
+  */
+  
+  /*
+  WifiMeshHeader meshHdr;
+  
+  // TODO: Address 1 we receive from HWMP tag
+  HwmpTag tag;
+  NS_ASSERT(packet->FindFirstMatchingTag(tag));
+  meshHdr.SetMeshTtl(tag.GetTtl());
+  meshHdr.SetMeshSeqno(tag.GetSeqno());
+#if 0
+  NS_LOG_DEBUG(
+    "TX Packet sa = "<<from<<
+    ", da = "<<to<<
+    ", ra = "<<tag.GetAddress()<<
+    ", I am "<<GetAddress()<<
+    ", ttl = "<<(int)meshHdr.GetMeshTtl()
+  );
+#endif
+  if (to!= Mac48Address::GetBroadcast())
+    NS_ASSERT(tag.GetAddress()!=Mac48Address::GetBroadcast());
+  
+  hdr.SetTypeData ();
+  hdr.SetAddr1 (tag.GetAddress());
+  hdr.SetAddr2 (GetAddress ());
+  hdr.SetAddr3 (to);
+  hdr.SetAddr4 (from);
+  hdr.SetDsFrom ();
+  hdr.SetDsTo ();
+  
+  packet_to_send->AddHeader(meshHdr);
+  */
+  
+  // 2. 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_to_send, 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 ());
+  
+  /*
+    TODO ask all plugins to add smth. to beacon
+   for all plugins {
+     plugin.UpdateBeacon(beacon);
+   }
+  */
+  
+  m_beaconDca->Queue(beacon.CreatePacket(), beacon.CreateHeader(GetAddress()));
+  
+  ScheduleNextBeacon();
+}
+
+
+void
+MeshWifiInterfaceMac::Receive (Ptr<Packet> packet, WifiMacHeader const *hdr)
+{
+  /* TODO
+  if (hdr->IsBeacon ())
+    {
+      MgtMeshBeaconHeader beacon;
+      Mac48Address from = hdr->GetAddr2();
+      packet->RemoveHeader (beacon);
+      NS_LOG_DEBUG("Beacon received from "<<hdr->GetAddr2()<<
+                   " to "<<GetAddress()<<
+                   " at "<<Simulator::Now ().GetMicroSeconds ()<<
+                   " microseconds");
+#if 0
+      NeighboursTimingUnitsList neighbours;
+      neighbours = beacon.GetWifiBeaconTimingElement().GetNeighboursTimingElementsList();
+      for (NeighboursTimingUnitsList::const_iterator j = neighbours.begin(); j!= neighbours.end(); j++)
+        fprintf(
+          stderr,
+          "neigbours:\nAID=%u, last_beacon=%u ,beacon_interval=%u\n",
+          (*j)->GetAID(),
+          (*j)->GetLastBeacon(),
+          (*j)->GetBeaconInterval()
+        );
+#endif
+      m_peerManager->SetReceivedBeaconTimers(
+        GetAddress(),
+        from,
+        Simulator::Now (),
+        MicroSeconds(beacon.GetBeaconIntervalUs()),
+        beacon.GetWifiBeaconTimingElement()
+      );
+      if (!beacon.GetSsid().IsEqual(GetSsid()))
+        return;
+      SupportedRates rates = beacon.GetSupportedRates ();
+      WifiRemoteStation *peerSta = 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 ()))
+            {
+              peerSta->AddSupportedMode (mode);
+              if (rates.IsBasicRate (mode.GetDataRate ()))
+                {
+                  m_stationManager->AddBasicMode (mode);
+                }
+            }
+        }
+      // TODO:Chack MeshConfigurationElement(now is nothing
+      // to be checked)
+      m_peerManager->AskIfOpenNeeded(GetAddress(), from);
+      return;
+    }
+  if (hdr->IsMultihopAction())
+    {
+      WifiMeshHeader meshHdr;
+      //no mesh header parameters are needed here:
+      //TODO: check TTL
+      packet->RemoveHeader(meshHdr);
+      WifiMeshMultihopActionHeader multihopHdr;
+      //parse multihop action header:
+      packet->RemoveHeader(multihopHdr);
+      WifiMeshMultihopActionHeader::ACTION_VALUE
+      actionValue = multihopHdr.GetAction();
+      switch (multihopHdr.GetCategory())
+        {
+        case WifiMeshMultihopActionHeader::MESH_PEER_LINK_MGT:
+        {
+          Mac48Address peerAddress;
+          MeshMgtPeerLinkManFrame peer_frame;
+          if (hdr->GetAddr1 () != GetAddress ())
+            return;
+          peerAddress = hdr->GetAddr2();
+          packet->RemoveHeader (peer_frame);
+          if (actionValue.peerLink != WifiMeshMultihopActionHeader::PEER_LINK_CLOSE)
+            {
+              //check Supported Rates
+              SupportedRates rates = peer_frame.GetSupportedRates();
+              for (uint32_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
+                {
+                  WifiMode mode = m_stationManager->GetBasicMode (i);
+                  if (!rates.IsSupportedRate (mode.GetDataRate ()))
+                    {
+                      m_peerManager->ConfigurationMismatch(GetAddress(), peerAddress);
+                      return;
+                    }
+                }
+              //Check SSID
+              if (!peer_frame.GetMeshId().IsEqual(GetSsid()))
+                {
+                  m_peerManager->ConfigurationMismatch(GetAddress(), peerAddress);
+                  return;
+                }
+            }
+          switch (actionValue.peerLink)
+            {
+            case WifiMeshMultihopActionHeader::PEER_LINK_CONFIRM:
+              m_peerManager->SetConfirmReceived(
+                GetAddress(),
+                peerAddress,
+                peer_frame.GetAid(),
+                peer_frame.GetPeerLinkManagementElement(),
+                m_meshConfig
+              );
+              return;
+            case WifiMeshMultihopActionHeader::PEER_LINK_OPEN:
+              m_peerManager->SetOpenReceived(
+                GetAddress(),
+                peerAddress,
+                peer_frame.GetPeerLinkManagementElement(),
+                m_meshConfig
+              );
+              return;
+            case WifiMeshMultihopActionHeader::PEER_LINK_CLOSE:
+              m_peerManager->SetCloseReceived(
+                GetAddress(),
+                peerAddress,
+                peer_frame.GetPeerLinkManagementElement()
+              );
+              return;
+            default:
+              return;
+            }
+          break;
+        }
+        case WifiMeshMultihopActionHeader::MESH_PATH_SELECTION:
+        {
+          if (!m_peerManager->IsActiveLink(GetAddress(), hdr->GetAddr2()))
+            return;
+          switch (actionValue.pathSelection)
+            {
+            case WifiMeshMultihopActionHeader::PATH_REQUEST:
+            {
+              WifiPreqInformationElement preq;
+              packet->RemoveHeader(preq);
+              //TODO:recalculate
+              //metric
+              m_preqReceived(preq, hdr->GetAddr2(), CalculateMetric(hdr->GetAddr2()));
+              return;
+            }
+            case WifiMeshMultihopActionHeader::PATH_REPLY:
+            {
+              WifiPrepInformationElement prep;
+              packet->RemoveHeader(prep);
+              m_prepReceived(prep, hdr->GetAddr2(), CalculateMetric(hdr->GetAddr2()));
+            }
+            return;
+            case WifiMeshMultihopActionHeader::PATH_ERROR:
+            {
+              WifiPerrInformationElement perr;
+              packet->RemoveHeader(perr);
+              m_perrReceived(perr, hdr->GetAddr2());
+            }
+            return;
+            case WifiMeshMultihopActionHeader::ROOT_ANNOUNCEMENT:
+              return;
+            }
+        }
+        default:
+          break;
+        }
+    }
+  if (hdr->IsData())
+    {
+      NS_ASSERT((hdr->IsFromDs()) && (hdr->IsToDs()));
+      NS_ASSERT(hdr->GetAddr4()!=Mac48Address::GetBroadcast());
+      //check seqno
+      WifiMeshHeader meshHdr;
+      packet->RemoveHeader(meshHdr);
+      NS_LOG_DEBUG(
+        "DATA TA="<< hdr->GetAddr2()<<
+        ", da="<<hdr->GetAddr3()<<
+        ", sa="<<hdr->GetAddr4()<<
+        ", TTL="<<(int)meshHdr.GetMeshTtl());
+      HwmpTag tag;
+      //mesh header is present within DATA and multihop action frames, so it must be done within MAC
+      tag.SetSeqno(meshHdr.GetMeshSeqno());
+      tag.SetAddress(hdr->GetAddr2());
+      tag.SetTtl(meshHdr.GetMeshTtl());
+      //metric should be later
+      packet->RemoveAllTags();
+      packet->AddTag(tag);
+      if (m_peerManager->IsActiveLink(GetAddress(), hdr->GetAddr2()))
+        ForwardUp(packet, hdr->GetAddr4(), hdr->GetAddr3());
+    }
+    */
+}
+  
+} // namespace ns3
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-interface-mac.h	Wed Mar 18 16:08:49 2009 +0300
@@ -0,0 +1,221 @@
+/* -*- 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 <andreev@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef MESHWIFIINTERFACEMAC_H_
+#define MESHWIFIINTERFACEMAC_H_
+
+#include <stdint.h>
+#include <map>
+#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"
+
+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<WifiPhy> phy);
+  virtual void  SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager);
+  virtual void  Enqueue (Ptr<const Packet> packet, Mac48Address to, Mac48Address from);
+  virtual void  Enqueue (Ptr<const Packet> packet, Mac48Address to);
+  virtual bool  SupportsSendFrom () const;
+  virtual void  SetForwardUpCallback (Callback<void,Ptr<Packet>, Mac48Address, Mac48Address> upCallback);
+  virtual void  SetLinkUpCallback (Callback<void> linkUp);
+  virtual void  SetLinkDownCallback (Callback<void> 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
+  //\{
+  // TODO
+  //\}
+  
+private:
+  /// Frame receive handler
+  void  Receive (Ptr<Packet> packet, WifiMacHeader const *hdr);
+  /// Forward frame to mesh point
+  virtual void ForwardUp (Ptr<Packet> packet, Mac48Address src, Mac48Address dst);
+  /// Send frame. Frame is supposed to be tagged by routing information. TODO: clarify this point 
+  void  ForwardDown(Ptr<const Packet> 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<DcaTxop>   m_BE;
+  Ptr<DcaTxop>   m_BK;
+  Ptr<DcaTxop>   m_VI;
+  Ptr<DcaTxop>   m_VO;
+  Ptr<DcaTxop>   m_beaconDca;
+  Ptr<WifiRemoteStationManager> m_stationManager;
+  Ptr<WifiPhy>   m_phy;
+  Callback<void, Ptr<Packet>, 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<MacLow> m_low;
+  /// My address
+  Mac48Address m_address;
+  /// SSID
+  Ssid m_MeshId;
+  
+  /// "Timer" for the next beacon 
+  EventId m_beaconSendEvent;
+};
+
+} // namespace ns3
+
+
+
+#endif /* MESHWIFIINTERFACEMAC_H_ */
--- a/src/devices/mesh/wscript	Wed Mar 18 14:37:29 2009 +0300
+++ b/src/devices/mesh/wscript	Wed Mar 18 16:08:49 2009 +0300
@@ -4,10 +4,11 @@
     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',
@@ -25,10 +26,11 @@
     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',
         # Dirty
         'dot11s-codes.h',
         'hwmp-state.h',