bug 602
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Wed, 06 Jan 2010 16:26:07 +0100
changeset 6065 0f012e7d9128
parent 6064 ddec96840ebd
child 6066 7464beb31586
bug 602
src/devices/mesh/mesh-wifi-interface-mac.cc
src/devices/wifi/aarf-wifi-manager.cc
src/devices/wifi/aarf-wifi-manager.h
src/devices/wifi/aarfcd-wifi-manager.cc
src/devices/wifi/aarfcd-wifi-manager.h
src/devices/wifi/adhoc-wifi-mac.cc
src/devices/wifi/amrr-wifi-manager.cc
src/devices/wifi/amrr-wifi-manager.h
src/devices/wifi/arf-wifi-manager.cc
src/devices/wifi/arf-wifi-manager.h
src/devices/wifi/cara-wifi-manager.cc
src/devices/wifi/cara-wifi-manager.h
src/devices/wifi/constant-rate-wifi-manager.cc
src/devices/wifi/constant-rate-wifi-manager.h
src/devices/wifi/dca-txop.cc
src/devices/wifi/dca-txop.h
src/devices/wifi/edca-txop-n.cc
src/devices/wifi/edca-txop-n.h
src/devices/wifi/ideal-wifi-manager.cc
src/devices/wifi/ideal-wifi-manager.h
src/devices/wifi/mac-low.cc
src/devices/wifi/mac-low.h
src/devices/wifi/minstrel-wifi-manager.cc
src/devices/wifi/minstrel-wifi-manager.h
src/devices/wifi/nqap-wifi-mac.cc
src/devices/wifi/nqsta-wifi-mac.cc
src/devices/wifi/onoe-wifi-manager.cc
src/devices/wifi/onoe-wifi-manager.h
src/devices/wifi/propagation-loss-model-test-suite.cc
src/devices/wifi/qadhoc-wifi-mac.cc
src/devices/wifi/qap-wifi-mac.cc
src/devices/wifi/qsta-wifi-mac.cc
src/devices/wifi/rraa-wifi-manager.cc
src/devices/wifi/rraa-wifi-manager.h
src/devices/wifi/wifi-remote-station-manager.cc
src/devices/wifi/wifi-remote-station-manager.h
src/devices/wifi/wscript
src/routing/aodv/aodv-routing-protocol.cc
src/test/ns3wifi/wifi-interference-test-suite.cc
--- a/src/devices/mesh/mesh-wifi-interface-mac.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/mesh/mesh-wifi-interface-mac.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -22,6 +22,7 @@
 #include "ns3/mesh-wifi-interface-mac.h"
 #include "ns3/mesh-wifi-beacon.h"
 #include "ns3/log.h"
+#include "ns3/boolean.h"
 #include "ns3/wifi-phy.h"
 #include "ns3/dcf-manager.h"
 #include "ns3/mac-rx-middle.h"
@@ -384,16 +385,15 @@
   // 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 ())
+  if (m_stationManager->IsBrandNew (to))
     {
       // 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));
+          m_stationManager->AddSupportedMode (to, m_phy->GetMode (i));
         }
-      destination->RecordDisassociated ();
+      m_stationManager->RecordDisassociated (to);
     }
   //Classify: application sets a tag, which is removed here
   // Get Qos tag:
@@ -592,14 +592,13 @@
       if (beacon_hdr.GetSsid ().IsEqual (GetSsid ()))
         {
           SupportedRates rates = beacon_hdr.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);
+                  m_stationManager->AddSupportedMode (hdr->GetAddr2 (), mode);
                   if (rates.IsBasicRate (mode.GetDataRate ()))
                     {
                       m_stationManager->AddBasicMode (mode);
--- a/src/devices/wifi/aarf-wifi-manager.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/aarf-wifi-manager.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -22,19 +22,37 @@
 
 #include "ns3/double.h"
 #include "ns3/uinteger.h"
+#include "ns3/log.h"
 
 #define Min(a,b) ((a<b)?a:b)
 #define Max(a,b) ((a>b)?a:b)
 
+NS_LOG_COMPONENT_DEFINE ("ns3::AarfWifiManager");
+
 namespace ns3 {
 
+struct AarfWifiRemoteStation : public WifiRemoteStation
+{
+  uint32_t m_timer;
+  uint32_t m_success;
+  uint32_t m_failed;
+  bool m_recovery;
+  uint32_t m_retry;
+  
+  uint32_t m_timerTimeout;
+  uint32_t m_successThreshold;
+
+  uint32_t m_rate;
+};
+
+
 NS_OBJECT_ENSURE_REGISTERED (AarfWifiManager);
 
 TypeId 
 AarfWifiManager::GetTypeId (void)
 {
   static TypeId tid = TypeId ("ns3::AarfWifiManager")
-    .SetParent<ArfWifiManager> ()
+    .SetParent<WifiRemoteStationManager> ()
     .AddConstructor<AarfWifiManager> ()
     .AddAttribute ("SuccessK", "Multiplication factor for the success threshold in the AARF algorithm.",
                    DoubleValue (2.0),
@@ -68,44 +86,139 @@
 {}
 AarfWifiManager::~AarfWifiManager ()
 {}
+
 WifiRemoteStation *
-AarfWifiManager::CreateStation (void)
+AarfWifiManager::DoCreateStation (void) const
 {
-  return new AarfWifiRemoteStation (this);
-}
-
-
-
+  AarfWifiRemoteStation *station = new AarfWifiRemoteStation ();
 
-AarfWifiRemoteStation::AarfWifiRemoteStation (Ptr<AarfWifiManager> manager)
-  : ArfWifiRemoteStation (manager),
-    m_manager (manager)
-{}
-
+  station->m_successThreshold = m_minSuccessThreshold;
+  station->m_timerTimeout = m_minTimerThreshold;
+  station->m_rate = 0;
+  station->m_success = 0;
+  station->m_failed = 0;
+  station->m_recovery = false;
+  station->m_retry = 0;
+  station->m_timer = 0;
 
-AarfWifiRemoteStation::~AarfWifiRemoteStation ()
-{}
-
-Ptr<WifiRemoteStationManager> 
-AarfWifiRemoteStation::GetManager (void) const
-{
-  return m_manager;
+  return station;
 }
 
 void 
-AarfWifiRemoteStation::ReportRecoveryFailure (void)
+AarfWifiManager::DoReportRtsFailed (WifiRemoteStation *station)
+{}
+/**
+ * It is important to realize that "recovery" mode starts after failure of
+ * the first transmission after a rate increase and ends at the first successful
+ * transmission. Specifically, recovery mode transcends retransmissions boundaries.
+ * Fundamentally, ARF handles each data transmission independently, whether it
+ * is the initial transmission of a packet or the retransmission of a packet.
+ * The fundamental reason for this is that there is a backoff between each data
+ * transmission, be it an initial transmission or a retransmission.
+ */
+void 
+AarfWifiManager::DoReportDataFailed (WifiRemoteStation *st)
 {
-  SetSuccessThreshold ((int)(Min (GetSuccessThreshold () * m_manager->m_successK,
-                                  m_manager->m_maxSuccessThreshold)));
-  SetTimerTimeout ((int)(Max (GetMinTimerTimeout (),
-                              GetSuccessThreshold () * m_manager->m_timerK)));
+  AarfWifiRemoteStation *station = (AarfWifiRemoteStation *)st;
+  station->m_timer++;
+  station->m_failed++;
+  station->m_retry++;
+  station->m_success = 0;
+
+  if (station->m_recovery) 
+    {
+      NS_ASSERT (station->m_retry >= 1);
+      if (station->m_retry == 1)
+        {
+          // need recovery fallback
+          station->m_successThreshold = (int)(Min (station->m_successThreshold * m_successK,
+                                                   m_maxSuccessThreshold));
+          station->m_timerTimeout = (int)(Max (station->m_timerTimeout * m_timerK,
+                                               m_minSuccessThreshold));
+          if (station->m_rate != 0)
+            {
+              station->m_rate--;
+            }
+        }
+      station->m_timer = 0;
+    } 
+  else 
+    {
+      NS_ASSERT (station->m_retry >= 1);
+      if (((station->m_retry - 1) % 2) == 1)
+        {
+          // need normal fallback
+          station->m_timerTimeout = m_minTimerThreshold;
+          station->m_successThreshold = m_minSuccessThreshold;
+          if (station->m_rate != 0)
+            {
+              station->m_rate--;
+            }
+        }
+      if (station->m_retry >= 2) 
+        {
+          station->m_timer = 0;
+        }
+    }
+}
+void 
+AarfWifiManager::DoReportRxOk (WifiRemoteStation *station,
+                              double rxSnr, WifiMode txMode)
+{}
+void 
+AarfWifiManager::DoReportRtsOk (WifiRemoteStation *station,
+                                double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+  NS_LOG_DEBUG ("station=" << station << " rts ok");
+}
+void 
+AarfWifiManager::DoReportDataOk (WifiRemoteStation *st,
+                                 double ackSnr, WifiMode ackMode, double dataSnr)
+{
+  AarfWifiRemoteStation *station = (AarfWifiRemoteStation *) st;
+  station->m_timer++;
+  station->m_success++;
+  station->m_failed = 0;
+  station->m_recovery = false;
+  station->m_retry = 0;
+  NS_LOG_DEBUG ("station=" << station << " data ok success=" << station->m_success << ", timer=" << station->m_timer);
+  if ((station->m_success == station->m_successThreshold ||
+       station->m_timer == station->m_timerTimeout) &&
+      (station->m_rate < (GetNSupported (station) - 1))) 
+    {
+      NS_LOG_DEBUG ("station="<<station<<" inc rate");
+      station->m_rate++;
+      station->m_timer = 0;
+      station->m_success = 0;
+      station->m_recovery = true;
+    }
+}
+void 
+AarfWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *station)
+{}
+void 
+AarfWifiManager::DoReportFinalDataFailed (WifiRemoteStation *station)
+{}
+
+WifiMode
+AarfWifiManager::DoGetDataMode (WifiRemoteStation *st, uint32_t size)
+{
+  AarfWifiRemoteStation *station = (AarfWifiRemoteStation *) st;
+  return GetSupported (station, station->m_rate);
+}
+WifiMode
+AarfWifiManager::DoGetRtsMode (WifiRemoteStation *st)
+{
+  // XXX: we could/should implement the Aarf algorithm for
+  // RTS only by picking a single rate within the BasicRateSet.
+  AarfWifiRemoteStation *station = (AarfWifiRemoteStation *) st;
+  return GetSupported (station, 0);
 }
 
-void 
-AarfWifiRemoteStation::ReportFailure (void)
+bool 
+AarfWifiManager::IsLowLatency (void) const
 {
-  SetTimerTimeout (GetMinTimerTimeout ());
-  SetSuccessThreshold (GetMinSuccessThreshold ());
+  return true;
 }
 
 } // namespace ns3
--- a/src/devices/wifi/aarf-wifi-manager.h	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/aarf-wifi-manager.h	Wed Jan 06 16:26:07 2010 +0100
@@ -32,15 +32,29 @@
  * A Practical Approach</i>, by M. Lacage, M.H. Manshaei, and 
  * T. Turletti.
  */
-class AarfWifiManager : public ArfWifiManager 
+class AarfWifiManager : public WifiRemoteStationManager 
 {
 public:
   static TypeId GetTypeId (void);
   AarfWifiManager ();
   virtual ~AarfWifiManager ();
 private:
-  friend class AarfWifiRemoteStation;
-  virtual class WifiRemoteStation *CreateStation (void);
+  // overriden from base class
+  virtual class WifiRemoteStation *DoCreateStation (void) const;
+  virtual void DoReportRxOk (WifiRemoteStation *station, 
+                             double rxSnr, WifiMode txMode);
+  virtual void DoReportRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportDataFailed (WifiRemoteStation *station);
+  virtual void DoReportRtsOk (WifiRemoteStation *station,
+                              double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void DoReportDataOk (WifiRemoteStation *station,
+                               double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual void DoReportFinalRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportFinalDataFailed (WifiRemoteStation *station);
+  virtual WifiMode DoGetDataMode (WifiRemoteStation *station, uint32_t size);
+  virtual WifiMode DoGetRtsMode (WifiRemoteStation *station);
+  virtual bool IsLowLatency (void) const;
+
   uint32_t m_minTimerThreshold;
   uint32_t m_minSuccessThreshold;
   double m_successK;
@@ -48,20 +62,6 @@
   double m_timerK;
 };
 
-class AarfWifiRemoteStation : public ArfWifiRemoteStation
-{
-public:
-  AarfWifiRemoteStation (Ptr<AarfWifiManager> stations);
-  virtual ~AarfWifiRemoteStation ();
-
-private:
-  virtual void ReportRecoveryFailure (void);
-  virtual void ReportFailure (void);
-  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
-
-  Ptr<AarfWifiManager> m_manager;
-};
-
 } // namespace ns3
 
 
--- a/src/devices/wifi/aarfcd-wifi-manager.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/aarfcd-wifi-manager.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -23,320 +23,37 @@
 #include "ns3/log.h"
 #include "ns3/simulator.h"
 #include "ns3/boolean.h"
+#include "ns3/double.h"
+#include "ns3/uinteger.h"
 #include <algorithm>
 
+#define Min(a,b) ((a<b)?a:b)
+#define Max(a,b) ((a>b)?a:b)
+
 NS_LOG_COMPONENT_DEFINE ("Aarfcd");
 
 namespace ns3 {
 
-NS_OBJECT_ENSURE_REGISTERED(AarfcdWifiManager);
-
-AarfcdWifiRemoteStation::AarfcdWifiRemoteStation (Ptr<AarfcdWifiManager> manager)
-  : m_manager (manager)
-{
-  m_timerTimeout = m_manager->m_minTimerThreshold;
-  m_successThreshold = m_manager->m_minSuccessThreshold;
-  m_rate = GetMinRate ();
-
-  m_success = 0;
-  m_failed = 0;
-  m_recovery = false;
-  m_retry = 0;
-  m_timer = 0;
-  m_rtsOn = false;
-  m_rtsWnd = m_manager->m_minRtsWnd;
-  m_rtsCounter = 0;
-  m_justModifyRate = true;
-  m_haveASuccess = false;
-}
-AarfcdWifiRemoteStation::~AarfcdWifiRemoteStation ()
-{}
-
-uint32_t
-AarfcdWifiRemoteStation::GetMaxRate (void)
-{
-  return GetNSupportedModes () - 1;
-}
-uint32_t
-AarfcdWifiRemoteStation::GetMinRate (void)
-{
-  return 0;
-}
-
-void
-AarfcdWifiRemoteStation::ReportRecoveryFailure (void)
-{
-  m_successThreshold = (int)(std::min ((uint32_t)(m_successThreshold * m_manager->m_successK),
-                                       m_manager->m_maxSuccessThreshold));
-  m_timerTimeout = (int)(std::max (m_manager->m_minTimerThreshold,
-                                   (uint32_t)(m_successThreshold * m_manager->m_timerK)));
-}
-
-void
-AarfcdWifiRemoteStation::ReportFailure (void)
-{
-  m_timerTimeout = m_manager->m_minTimerThreshold;
-  m_successThreshold = m_manager->m_minSuccessThreshold;
-}
-
-bool 
-AarfcdWifiRemoteStation::NeedRecoveryFallback (void)
-{
-  if (m_retry >= 1) 
-    {
-      return true;
-    } 
-  else 
-    {
-      return false;
-    }
-}
-bool 
-AarfcdWifiRemoteStation::NeedNormalFallback (void)
-{
-  int retryMod = (m_retry - 1) % 2;
-  if (retryMod == 1) 
-    {
-      return true;
-    } 
-  else 
-    {
-      return false;
-    }
-}
-
-
-
-void 
-AarfcdWifiRemoteStation::DoReportRtsFailed (void)
-{
-  //printf ("%.9f %p RtsFail %d %d %d\n",Simulator::Now ().GetSeconds (),this,m_rate,m_timer,m_retry);
-  NS_LOG_INFO ("" << this << " RtsFail rate=" << m_rate);
-  if (m_manager->m_rtsFailsAsDataFails)
-    {
-      m_rtsCounter--;
-      ReportDataFailed ();
-    }
-}
-/**
- * It is important to realize that "recovery" mode starts after failure of
- * the first transmission after a rate increase and ends at the first successful
- * transmission. Specifically, recovery mode transcends retransmissions boundaries.
- * Fundamentally, ARF handles each data transmission independently, whether it
- * is the initial transmission of a packet or the retransmission of a packet.
- * The fundamental reason for this is that there is a backoff between each data
- * transmission, be it an initial transmission or a retransmission.
- */
-void 
-AarfcdWifiRemoteStation::DoReportDataFailed (void)
+struct AarfcdWifiRemoteStation : public WifiRemoteStation
 {
-  NS_LOG_INFO ("" << this << " TxFail rate=" << m_rate);
-  m_timer++;
-  m_failed++;
-  m_retry++;
-  m_success = 0;
-  //printf ("%.9f %p Fail %d %d %d\n",Simulator::Now ().GetSeconds (),this,m_rate,m_timer,m_retry);
-  if (!m_rtsOn) 
-    {
-      TurnOnRts ();
-      if (!m_justModifyRate && !m_haveASuccess) 
-        {
-          //printf ("%p Increase RTS Windows\n",this);
-          IncreaseRtsWnd ();
-        }
-      else 
-        {
-          //printf ("%p Reset RTS Window\n",this);
-          ResetRtsWnd ();
-        }
-      m_rtsCounter = m_rtsWnd;
-      if (m_retry >= 2) 
-        {
-          m_timer = 0;
-        }
-      //printf ("%.9f %p AtcivateRTS %d %d\n",Simulator::Now ().GetSeconds (),this, m_rate, m_rtsCounter);
-    }
-  else if (m_recovery) 
-    {
-      NS_ASSERT (m_retry >= 1);
-      m_justModifyRate = false;
-      m_rtsCounter = m_rtsWnd;
-      if (NeedRecoveryFallback ()) 
-        {
-          if (m_manager->m_turnOffRtsAfterRateDecrease) 
-            {
-              TurnOffRts ();
-            }
-          m_justModifyRate = true;
-          ReportRecoveryFailure ();
-          if (m_rate != GetMinRate ()) 
-            {
-              m_rate--;
-            }
-          NS_LOG_INFO ("" << this << " JD rate=" << m_rate << " Sthr=" << m_successThreshold);
-          //printf ("%.9f %p DecreaseRateRecovery %d\n", Simulator::Now ().GetSeconds (),this, m_rate);
-        }
-      m_timer = 0;
-    } 
-  else 
-    {
-      NS_ASSERT (m_retry >= 1);
-      m_justModifyRate = false;
-      m_rtsCounter = m_rtsWnd;
-      if (NeedNormalFallback ()) 
-        {
-          if (m_manager->m_turnOffRtsAfterRateDecrease) 
-            {
-              TurnOffRts ();
-            }
-          m_justModifyRate = true;
-          ReportFailure ();
-          if (m_rate != GetMinRate ()) 
-            {
-              m_rate--;
-            }
-          NS_LOG_INFO ("" << this << " JD rate=" << m_rate << " Sthr=" << m_successThreshold);
-          //printf ("%.9f %p DecreaseRate %d\n", Simulator::Now ().GetSeconds (),this,m_rate);
-        }
-      if (m_retry >= 2) 
-        {
-          m_timer = 0;
-        }
-    }
-  CheckRts ();
-}
-void 
-AarfcdWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
-{}
-void 
-AarfcdWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
-{
-  NS_LOG_INFO ("" << this << " RtsOk rate=" << m_rate);
-  NS_LOG_DEBUG ("self="<<this<<" rts ok");
-  m_rtsCounter--;
-}
-void 
-AarfcdWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
-{
-  NS_LOG_INFO ("" << this << " TxOk rate=" << m_rate);
-  m_timer++;
-  m_success++;
-  m_failed = 0;
-  m_recovery = false;
-  m_retry = 0;
-  m_justModifyRate = false;
-  m_haveASuccess = true;
-  //printf ("%.9f %p Ok %d %d %d\n",Simulator::Now ().GetSeconds (),this,m_rate,m_timer,m_retry);
-  //printf ("%p OK (m_success=%d, th=%d, m_rate=%d, maxRate=%d)\n",this,m_success,GetSuccessThreshold (), m_rate, GetMaxRate ());
-  NS_LOG_DEBUG ("self="<<this<<" data ok success="<<m_success<<", timer="<<m_timer);
-  if ((m_success == m_successThreshold ||
-       m_timer >= m_timerTimeout) &&
-      (m_rate < GetMaxRate ())) 
-    {
-      NS_LOG_DEBUG ("self="<<this<<" inc rate");
-      m_rate++;
-      NS_LOG_INFO ("" << this << " JI rate=" << m_rate << " Sthr=" << m_successThreshold);
-      m_timer = 0;
-      m_success = 0;
-      m_recovery = true;
-      m_justModifyRate = true;
-      if (m_manager->m_turnOnRtsAfterRateIncrease) 
-        {
-          TurnOnRts ();
-          ResetRtsWnd ();
-          m_rtsCounter = m_rtsWnd;
-        }
-      //printf ("%.9f %p IncreaseRate %d %d\n", Simulator::Now ().GetSeconds (),this,m_rate,(m_rtsOn?1:0));
-    }
-  else if (m_success == m_successThreshold ||
-           m_timer >= m_timerTimeout) 
-    {
-      NS_LOG_INFO ("" << this << " JI rate=" << m_rate << " Sthr=" << m_successThreshold);
-    }
-  CheckRts ();
-}
-void 
-AarfcdWifiRemoteStation::DoReportFinalRtsFailed (void)
-{}
-void 
-AarfcdWifiRemoteStation::DoReportFinalDataFailed (void)
-{}
+  uint32_t m_timer;
+  uint32_t m_success;
+  uint32_t m_failed;
+  bool m_recovery;
+  bool m_justModifyRate;
+  uint32_t m_retry;
+  
+  uint32_t m_successThreshold;
+  uint32_t m_timerTimeout;
 
-WifiMode
-AarfcdWifiRemoteStation::DoGetDataMode (uint32_t size)
-{
-  return GetSupportedMode (m_rate);
-}
-WifiMode
-AarfcdWifiRemoteStation::DoGetRtsMode (void)
-{
-  // XXX: we could/should implement the Arf algorithm for
-  // RTS only by picking a single rate within the BasicRateSet.
-  return GetSupportedMode (0);
-}
-
-Ptr<WifiRemoteStationManager>
-AarfcdWifiRemoteStation::GetManager (void) const
-{
-  return m_manager;
-}
-
-void
-AarfcdWifiRemoteStation::CheckRts (void)
-{
-  if (m_rtsCounter == 0 && m_rtsOn) 
-    {
-      //printf ("%p Turn off RTS\n",this);
-      TurnOffRts ();
-    }
-}
-
-void
-AarfcdWifiRemoteStation::TurnOffRts (void)
-{
-  //printf ("%.9f %p DeatcivateRTS %d %d\n",Simulator::Now ().GetSeconds (),this, m_rate, m_rtsCounter);
-  m_rtsOn = false;
-  m_haveASuccess = false;
-}
+  uint32_t m_rate;
+  bool m_rtsOn;
+  uint32_t m_rtsWnd;
+  uint32_t m_rtsCounter;
+  bool m_haveASuccess;
+};
 
-void
-AarfcdWifiRemoteStation::TurnOnRts (void)
-{
-  m_rtsOn = true;
-}
-
-void
-AarfcdWifiRemoteStation::IncreaseRtsWnd (void)
-{
-  if (m_rtsWnd == m_manager->m_maxRtsWnd)
-    {
-      return;
-    }
-
-  m_rtsWnd *= 2;
-  if (m_rtsWnd > m_manager->m_maxRtsWnd)
-    {
-      m_rtsWnd = m_manager->m_maxRtsWnd;
-    }
-}
-
-void
-AarfcdWifiRemoteStation::ResetRtsWnd (void)
-{
-  m_rtsWnd = m_manager->m_minRtsWnd;
-}
-
-bool
-AarfcdWifiRemoteStation::NeedRts (Ptr<const Packet> packet)
-{
-  //printf ("%.9f %p NeedRts %d %d\n",Simulator::Now ().GetSeconds (),this,m_rate,(m_rtsOn?1:0));
-  NS_LOG_INFO ("" << this << " rate=" << m_rate << " rts=" << (m_rtsOn?"RTS":"BASIC") << " rtsCounter=" << m_rtsCounter);
-  return m_rtsOn;
-}
-
-
-
-
+NS_OBJECT_ENSURE_REGISTERED(AarfcdWifiManager);
 
 TypeId 
 AarfcdWifiManager::GetTypeId (void)
@@ -378,11 +95,6 @@
                    UintegerValue (40),
                    MakeUintegerAccessor (&AarfcdWifiManager::m_maxRtsWnd),
                    MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("RtsFailsAsDataFails",
-                   "If true the RTS failures will be treated by Aarf-CD as Data failures",
-                   BooleanValue (false),
-                   MakeBooleanAccessor (&AarfcdWifiManager::m_rtsFailsAsDataFails),
-                   MakeBooleanChecker ())
     .AddAttribute ("TurnOffRtsAfterRateDecrease",
                    "If true the RTS mechanism will be turned off when the rate will be decreased",
                    BooleanValue (true),
@@ -402,9 +114,244 @@
 AarfcdWifiManager::~AarfcdWifiManager ()
 {}
 WifiRemoteStation *
-AarfcdWifiManager::CreateStation (void)
+AarfcdWifiManager::DoCreateStation (void) const
 {
-  return new AarfcdWifiRemoteStation (this);
+  AarfcdWifiRemoteStation *station = new AarfcdWifiRemoteStation ();
+
+  // aarf fields below
+  station->m_successThreshold = m_minSuccessThreshold;
+  station->m_timerTimeout = m_minTimerThreshold;
+  station->m_rate = 0;
+  station->m_success = 0;
+  station->m_failed = 0;
+  station->m_recovery = false;
+  station->m_retry = 0;
+  station->m_timer = 0;
+
+  // aarf-cd specific fields below
+  station->m_rtsOn = false;
+  station->m_rtsWnd = m_minRtsWnd;
+  station->m_rtsCounter = 0;
+  station->m_justModifyRate = true;
+  station->m_haveASuccess = false;
+
+  return station;
 }
 
+void 
+AarfcdWifiManager::DoReportRtsFailed (WifiRemoteStation *station)
+{}
+/**
+ * It is important to realize that "recovery" mode starts after failure of
+ * the first transmission after a rate increase and ends at the first successful
+ * transmission. Specifically, recovery mode transcends retransmissions boundaries.
+ * Fundamentally, ARF handles each data transmission independently, whether it
+ * is the initial transmission of a packet or the retransmission of a packet.
+ * The fundamental reason for this is that there is a backoff between each data
+ * transmission, be it an initial transmission or a retransmission.
+ */
+void 
+AarfcdWifiManager::DoReportDataFailed (WifiRemoteStation *st)
+{
+
+  AarfcdWifiRemoteStation *station = (AarfcdWifiRemoteStation *)st;
+  station->m_timer++;
+  station->m_failed++;
+  station->m_retry++;
+  station->m_success = 0;
+
+  if (!station->m_rtsOn) 
+    {
+      TurnOnRts (station);
+      if (!station->m_justModifyRate && !station->m_haveASuccess) 
+        {
+          IncreaseRtsWnd (station);
+        }
+      else 
+        {
+          ResetRtsWnd (station);
+        }
+      station->m_rtsCounter = station->m_rtsWnd;
+      if (station->m_retry >= 2) 
+        {
+          station->m_timer = 0;
+        }
+    }
+  else if (station->m_recovery) 
+    {
+      NS_ASSERT (station->m_retry >= 1);
+      station->m_justModifyRate = false;
+      station->m_rtsCounter = station->m_rtsWnd;
+      if (station->m_retry == 1)
+        {
+          // need recovery fallback
+          if (m_turnOffRtsAfterRateDecrease) 
+            {
+              TurnOffRts (station);
+            }
+          station->m_justModifyRate = true;
+          station->m_successThreshold = (int)(Min (station->m_successThreshold * m_successK,
+                                                   m_maxSuccessThreshold));
+          station->m_timerTimeout = (int)(Max (station->m_timerTimeout * m_timerK,
+                                               m_minSuccessThreshold));
+          if (station->m_rate != 0)
+            {
+              station->m_rate--;
+            }
+        }
+      station->m_timer = 0;
+    } 
+  else 
+    {
+      NS_ASSERT (station->m_retry >= 1);
+      station->m_justModifyRate = false;
+      station->m_rtsCounter = station->m_rtsWnd;
+      if (((station->m_retry - 1) % 2) == 1)
+        {
+          // need normal fallback
+          if (m_turnOffRtsAfterRateDecrease) 
+            {
+              TurnOffRts (station);
+            }
+          station->m_justModifyRate = true;
+          station->m_timerTimeout = m_minTimerThreshold;
+          station->m_successThreshold = m_minSuccessThreshold;
+          if (station->m_rate != 0)
+            {
+              station->m_rate--;
+            }
+        }
+      if (station->m_retry >= 2) 
+        {
+          station->m_timer = 0;
+        }
+    }
+  CheckRts (station);
+}
+void 
+AarfcdWifiManager::DoReportRxOk (WifiRemoteStation *station,
+                              double rxSnr, WifiMode txMode)
+{}
+void 
+AarfcdWifiManager::DoReportRtsOk (WifiRemoteStation *st,
+                                double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+  AarfcdWifiRemoteStation *station = (AarfcdWifiRemoteStation *) st;
+  NS_LOG_DEBUG ("station=" << station << " rts ok");
+  station->m_rtsCounter--;
+}
+void 
+AarfcdWifiManager::DoReportDataOk (WifiRemoteStation *st,
+                                 double ackSnr, WifiMode ackMode, double dataSnr)
+{
+  AarfcdWifiRemoteStation *station = (AarfcdWifiRemoteStation *) st;
+  station->m_timer++;
+  station->m_success++;
+  station->m_failed = 0;
+  station->m_recovery = false;
+  station->m_retry = 0;
+  station->m_justModifyRate = false;
+  station->m_haveASuccess = true;
+  NS_LOG_DEBUG ("station=" << station << " data ok success=" << station->m_success << ", timer=" << station->m_timer);
+  if ((station->m_success == station->m_successThreshold ||
+       station->m_timer == station->m_timerTimeout) &&
+      (station->m_rate < (GetNSupported (station) - 1))) 
+    {
+      NS_LOG_DEBUG ("station="<<station<<" inc rate");
+      station->m_rate++;
+      station->m_timer = 0;
+      station->m_success = 0;
+      station->m_recovery = true;
+      station->m_justModifyRate = true;
+      if (m_turnOnRtsAfterRateIncrease) 
+        {
+          TurnOnRts (station);
+          ResetRtsWnd (station);
+          station->m_rtsCounter = station->m_rtsWnd;
+        }
+    }
+  CheckRts (station);
+}
+void 
+AarfcdWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *station)
+{}
+void 
+AarfcdWifiManager::DoReportFinalDataFailed (WifiRemoteStation *station)
+{}
+
+WifiMode
+AarfcdWifiManager::DoGetDataMode (WifiRemoteStation *st, uint32_t size)
+{
+  AarfcdWifiRemoteStation *station = (AarfcdWifiRemoteStation *) st;
+  return GetSupported (station, station->m_rate);
+}
+WifiMode
+AarfcdWifiManager::DoGetRtsMode (WifiRemoteStation *st)
+{
+  // XXX: we could/should implement the Aarf algorithm for
+  // RTS only by picking a single rate within the BasicRateSet.
+  AarfcdWifiRemoteStation *station = (AarfcdWifiRemoteStation *) st;
+  return GetSupported (station, 0);
+}
+
+bool
+AarfcdWifiManager::DoNeedRts (WifiRemoteStation *st,
+                              Ptr<const Packet> packet, bool normally)
+{
+  AarfcdWifiRemoteStation *station = (AarfcdWifiRemoteStation *) st;
+  NS_LOG_INFO ("" << station << " rate=" << station->m_rate << " rts=" << (station->m_rtsOn?"RTS":"BASIC") << 
+               " rtsCounter=" << station->m_rtsCounter);
+  return station->m_rtsOn;
+}
+
+bool 
+AarfcdWifiManager::IsLowLatency (void) const
+{
+  return true;
+}
+
+void
+AarfcdWifiManager::CheckRts (AarfcdWifiRemoteStation *station)
+{
+  if (station->m_rtsCounter == 0 && station->m_rtsOn) 
+    {
+      TurnOffRts (station);
+    }
+}
+
+void
+AarfcdWifiManager::TurnOffRts (AarfcdWifiRemoteStation *station)
+{
+  station->m_rtsOn = false;
+  station->m_haveASuccess = false;
+}
+
+void
+AarfcdWifiManager::TurnOnRts (AarfcdWifiRemoteStation *station)
+{
+  station->m_rtsOn = true;
+}
+
+void
+AarfcdWifiManager::IncreaseRtsWnd (AarfcdWifiRemoteStation *station)
+{
+  if (station->m_rtsWnd == m_maxRtsWnd)
+    {
+      return;
+    }
+
+  station->m_rtsWnd *= 2;
+  if (station->m_rtsWnd > m_maxRtsWnd)
+    {
+      station->m_rtsWnd = m_maxRtsWnd;
+    }
+}
+
+void
+AarfcdWifiManager::ResetRtsWnd (AarfcdWifiRemoteStation *station)
+{
+  station->m_rtsWnd = m_minRtsWnd;
+}
+
+
 } // namespace ns3
--- a/src/devices/wifi/aarfcd-wifi-manager.h	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/aarfcd-wifi-manager.h	Wed Jan 06 16:26:07 2010 +0100
@@ -24,6 +24,8 @@
 
 namespace ns3 {
 
+class AarfcdWifiRemoteStation;
+
 /**
  * \brief an implementation of the AARF-CD algorithm
  *
@@ -40,13 +42,38 @@
   virtual ~AarfcdWifiManager ();
 
 private:
-  friend class AarfcdWifiRemoteStation;
-  virtual WifiRemoteStation *CreateStation (void);
+  // overriden from base class
+  virtual class WifiRemoteStation *DoCreateStation (void) const;
+  virtual void DoReportRxOk (WifiRemoteStation *station, 
+                             double rxSnr, WifiMode txMode);
+  virtual void DoReportRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportDataFailed (WifiRemoteStation *station);
+  virtual void DoReportRtsOk (WifiRemoteStation *station,
+                              double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void DoReportDataOk (WifiRemoteStation *station,
+                               double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual void DoReportFinalRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportFinalDataFailed (WifiRemoteStation *station);
+  virtual WifiMode DoGetDataMode (WifiRemoteStation *station, uint32_t size);
+  virtual WifiMode DoGetRtsMode (WifiRemoteStation *station);
+  virtual bool DoNeedRts (WifiRemoteStation *station, 
+                          Ptr<const Packet> packet, bool normally);
+  virtual bool IsLowLatency (void) const;
+
+  void CheckRts (AarfcdWifiRemoteStation *station);
+  void IncreaseRtsWnd (AarfcdWifiRemoteStation *station);
+  void ResetRtsWnd (AarfcdWifiRemoteStation *station);
+  void TurnOffRts (AarfcdWifiRemoteStation *station);
+  void TurnOnRts (AarfcdWifiRemoteStation *station);
+
+  // aarf fields below
   uint32_t m_minTimerThreshold;
   uint32_t m_minSuccessThreshold;
   double m_successK;
   uint32_t m_maxSuccessThreshold;
   double m_timerK;
+
+  // aarf-cd fields below
   uint32_t m_minRtsWnd;
   uint32_t m_maxRtsWnd;
   bool m_rtsFailsAsDataFails;
@@ -54,59 +81,6 @@
   bool m_turnOnRtsAfterRateIncrease;
 };
 
-
-class AarfcdWifiRemoteStation : public WifiRemoteStation
-{
-public:
-  AarfcdWifiRemoteStation (Ptr<AarfcdWifiManager> manager);
-  virtual ~AarfcdWifiRemoteStation ();
-
-
-private:
-  virtual void DoReportRxOk (double rxSnr, WifiMode txMode);
-  virtual void DoReportRtsFailed (void);
-  virtual void DoReportDataFailed (void);
-  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
-  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
-  virtual void DoReportFinalRtsFailed (void);
-  virtual void DoReportFinalDataFailed (void);
-  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
-  virtual WifiMode DoGetDataMode (uint32_t size);
-  virtual WifiMode DoGetRtsMode (void);
-  virtual bool NeedRts (Ptr<const Packet> packet);
-
-  void ReportRecoveryFailure (void);
-  void ReportFailure (void);
-  uint32_t GetMaxRate (void);
-  uint32_t GetMinRate (void);
-  void CheckRts (void);
-  void IncreaseRtsWnd (void);
-  void ResetRtsWnd (void);
-  void TurnOffRts (void);
-  void TurnOnRts (void);
-
-  bool NeedRecoveryFallback (void);
-  bool NeedNormalFallback (void);
-
-  uint32_t m_timer;
-  uint32_t m_success;
-  uint32_t m_failed;
-  bool m_recovery;
-  bool m_justModifyRate;
-  uint32_t m_retry;
-  
-  uint32_t m_successThreshold;
-  uint32_t m_timerTimeout;
-
-  uint32_t m_rate;
-  bool m_rtsOn;
-  uint32_t m_rtsWnd;
-  uint32_t m_rtsCounter;
-  bool m_haveASuccess;
-  
-  Ptr<AarfcdWifiManager> m_manager;
-};
-
 } // namespace ns3
 
-#endif /* MAARF_MAC_STATIONS_H */
+#endif /* AARFCD_WIFI_MANAGER_H */
--- a/src/devices/wifi/adhoc-wifi-mac.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/adhoc-wifi-mac.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -234,16 +234,15 @@
   hdr.SetDsNotFrom ();
   hdr.SetDsNotTo ();
 
-  WifiRemoteStation *destination = m_stationManager->Lookup (to);
-  if (destination->IsBrandNew ())
+  if (m_stationManager->IsBrandNew (to))
     {
       // 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));
+          m_stationManager->AddSupportedMode (to, m_phy->GetMode (i));
         }
-      destination->RecordDisassociated ();
+      m_stationManager->RecordDisassociated (to);
     }
 
   m_dca->Queue (packet, hdr);
--- a/src/devices/wifi/amrr-wifi-manager.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/amrr-wifi-manager.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -28,6 +28,20 @@
 
 namespace ns3 {
 
+struct AmrrWifiRemoteStation : public WifiRemoteStation
+{
+  Time m_nextModeUpdate;
+  uint32_t m_tx_ok;
+  uint32_t m_tx_err;
+  uint32_t m_tx_retr;
+  uint32_t m_retry;
+  uint32_t m_txrate;
+  uint32_t m_successThreshold;
+  uint32_t m_success;
+  bool m_recovery;
+};
+
+
 NS_OBJECT_ENSURE_REGISTERED (AmrrWifiManager);
 
 TypeId
@@ -67,224 +81,231 @@
 
 AmrrWifiManager::AmrrWifiManager ()
 {}
+
 WifiRemoteStation *
-AmrrWifiManager::CreateStation (void)
+AmrrWifiManager::DoCreateStation (void) const
 {
-  return new AmrrWifiRemoteStation (this);
+  AmrrWifiRemoteStation *station = new AmrrWifiRemoteStation ();
+  station->m_nextModeUpdate = Simulator::Now () + m_updatePeriod;
+  station->m_tx_ok = 0;
+  station->m_tx_err = 0;
+  station->m_tx_retr = 0;
+  station->m_retry = 0;
+  station->m_txrate = 0;
+  station->m_successThreshold = m_minSuccessThreshold;
+  station->m_success = 0;
+  station->m_recovery = false;
+  return station;
 }
 
-AmrrWifiRemoteStation::AmrrWifiRemoteStation (Ptr<AmrrWifiManager> stations)
-  : m_stations (stations),
-    m_nextModeUpdate (Simulator::Now () + stations->m_updatePeriod),
-    m_tx_ok (0),
-    m_tx_err (0),
-    m_tx_retr (0),
-    m_retry (0),
-    m_txrate (0),
-    m_successThreshold (m_stations->m_minSuccessThreshold),
-    m_success (0),
-    m_recovery (false)
-{}
-AmrrWifiRemoteStation::~AmrrWifiRemoteStation ()
-{}
 
 void 
-AmrrWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
+AmrrWifiManager::DoReportRxOk (WifiRemoteStation *station,
+                                double rxSnr, WifiMode txMode)
 {}
 void 
-AmrrWifiRemoteStation::DoReportRtsFailed (void)
+AmrrWifiManager::DoReportRtsFailed (WifiRemoteStation *station)
 {}
 void 
-AmrrWifiRemoteStation::DoReportDataFailed (void)
+AmrrWifiManager::DoReportDataFailed (WifiRemoteStation *st)
 {
-  m_retry++;
-  m_tx_retr++;
+  AmrrWifiRemoteStation *station = (AmrrWifiRemoteStation *)st;
+  station->m_retry++;
+  station->m_tx_retr++;
 }
 void 
-AmrrWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
-{}
-void 
-AmrrWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+AmrrWifiManager::DoReportRtsOk (WifiRemoteStation *st,
+                                 double ctsSnr, WifiMode ctsMode, double rtsSnr)
 {
-  m_retry = 0;
-  m_tx_ok++;
 }
 void 
-AmrrWifiRemoteStation::DoReportFinalRtsFailed (void)
+AmrrWifiManager::DoReportDataOk (WifiRemoteStation *st,
+                                  double ackSnr, WifiMode ackMode, double dataSnr)
+{
+  AmrrWifiRemoteStation *station = (AmrrWifiRemoteStation *)st;
+  station->m_retry = 0;
+  station->m_tx_ok++;
+}
+void 
+AmrrWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *station)
 {}
 void 
-AmrrWifiRemoteStation::DoReportFinalDataFailed (void)
+AmrrWifiManager::DoReportFinalDataFailed (WifiRemoteStation *st)
 {
-  m_retry = 0;
-  m_tx_err++;
+  AmrrWifiRemoteStation *station = (AmrrWifiRemoteStation *)st;
+  station->m_retry = 0;
+  station->m_tx_err++;
 }
 bool
-AmrrWifiRemoteStation::IsMinRate (void) const
+AmrrWifiManager::IsMinRate (AmrrWifiRemoteStation *station) const
 {
-  return (m_txrate == 0);
+  return (station->m_txrate == 0);
 }
 bool
-AmrrWifiRemoteStation::IsMaxRate (void) const
+AmrrWifiManager::IsMaxRate (AmrrWifiRemoteStation *station) const
 {
-  NS_ASSERT (m_txrate + 1 <= GetNSupportedModes ());
-  return (m_txrate + 1 == GetNSupportedModes ());
+  NS_ASSERT (station->m_txrate + 1 <= GetNSupported (station));
+  return (station->m_txrate + 1 == GetNSupported (station));
 }
 bool
-AmrrWifiRemoteStation::IsSuccess (void) const
+AmrrWifiManager::IsSuccess (AmrrWifiRemoteStation *station) const
 {
-  return (m_tx_retr + m_tx_err) < m_tx_ok * m_stations->m_successRatio;
+  return (station->m_tx_retr + station->m_tx_err) < station->m_tx_ok * m_successRatio;
 }
 bool
-AmrrWifiRemoteStation::IsFailure (void) const
+AmrrWifiManager::IsFailure (AmrrWifiRemoteStation *station) const
 {
-  return (m_tx_retr + m_tx_err) > m_tx_ok * m_stations->m_failureRatio;
+  return (station->m_tx_retr + station->m_tx_err) > station->m_tx_ok * m_failureRatio;
 }
 bool
-AmrrWifiRemoteStation::IsEnough (void) const
+AmrrWifiManager::IsEnough (AmrrWifiRemoteStation *station) const
 {
-  return (m_tx_retr + m_tx_err + m_tx_ok) > 10;
+  return (station->m_tx_retr + station->m_tx_err + station->m_tx_ok) > 10;
 }
 void 
-AmrrWifiRemoteStation::ResetCnt (void)
+AmrrWifiManager::ResetCnt (AmrrWifiRemoteStation *station)
 {
-  m_tx_ok = 0;
-  m_tx_err = 0;
-  m_tx_retr = 0;
+  station->m_tx_ok = 0;
+  station->m_tx_err = 0;
+  station->m_tx_retr = 0;
 }
 void 
-AmrrWifiRemoteStation::IncreaseRate (void)
+AmrrWifiManager::IncreaseRate (AmrrWifiRemoteStation *station)
 {
-  m_txrate++;
-  NS_ASSERT (m_txrate < GetNSupportedModes ());
+  station->m_txrate++;
+  NS_ASSERT (station->m_txrate < GetNSupported (station));
 }
 void 
-AmrrWifiRemoteStation::DecreaseRate (void)
+AmrrWifiManager::DecreaseRate (AmrrWifiRemoteStation *station)
 {
-  m_txrate--;
+  station->m_txrate--;
 }
 
 void
-AmrrWifiRemoteStation::UpdateMode (void)
+AmrrWifiManager::UpdateMode (AmrrWifiRemoteStation *station)
 {
-  if (Simulator::Now () < m_nextModeUpdate)
+  if (Simulator::Now () < station->m_nextModeUpdate)
     {
       return;
     }
-  m_nextModeUpdate = Simulator::Now () + m_stations->m_updatePeriod;
+  station->m_nextModeUpdate = Simulator::Now () + m_updatePeriod;
   NS_LOG_DEBUG ("Update");
 
   bool needChange = false;
 
-  if (IsSuccess () && IsEnough ()) 
+  if (IsSuccess (station) && IsEnough (station)) 
     {
-      m_success++;
-      NS_LOG_DEBUG ("++ success="<<m_success<<" successThreshold="<<m_successThreshold<<
-                    " tx_ok="<<m_tx_ok<<" tx_err="<<m_tx_err<<" tx_retr="<<m_tx_retr<<
-                    " rate="<<m_txrate<<" n-supported-rates="<<GetNSupportedModes ());
-      if (m_success >= m_successThreshold &&
-          !IsMaxRate ()) 
+      station->m_success++;
+      NS_LOG_DEBUG ("++ success="<<station->m_success<<" successThreshold="<<station->m_successThreshold<<
+                    " tx_ok="<<station->m_tx_ok<<" tx_err="<<station->m_tx_err<<" tx_retr="<<station->m_tx_retr<<
+                    " rate="<<station->m_txrate<<" n-supported-rates="<<GetNSupported (station));
+      if (station->m_success >= station->m_successThreshold &&
+          !IsMaxRate (station)) 
         {
-          m_recovery = true;
-          m_success = 0;
-          IncreaseRate ();
+          station->m_recovery = true;
+          station->m_success = 0;
+          IncreaseRate (station);
           needChange = true;
         } 
       else 
         {
-          m_recovery = false;
+          station->m_recovery = false;
         }
     } 
-  else if (IsFailure ()) 
+  else if (IsFailure (station)) 
     {
-      m_success = 0;
-      NS_LOG_DEBUG ("-- success="<<m_success<<" successThreshold="<<m_successThreshold<<
-                    " tx_ok="<<m_tx_ok<<" tx_err="<<m_tx_err<<" tx_retr="<<m_tx_retr<<
-                    " rate="<<m_txrate<<" n-supported-rates="<<GetNSupportedModes ());
-      if (!IsMinRate ()) 
+      station->m_success = 0;
+      NS_LOG_DEBUG ("-- success="<<station->m_success<<" successThreshold="<<station->m_successThreshold<<
+                    " tx_ok="<<station->m_tx_ok<<" tx_err="<<station->m_tx_err<<" tx_retr="<<station->m_tx_retr<<
+                    " rate="<<station->m_txrate<<" n-supported-rates="<<GetNSupported (station));
+      if (!IsMinRate (station)) 
         {
-          if (m_recovery) 
+          if (station->m_recovery) 
             {
-              m_successThreshold *= 2;
-              m_successThreshold = std::min (m_successThreshold,
-                                             m_stations->m_maxSuccessThreshold);
+              station->m_successThreshold *= 2;
+              station->m_successThreshold = std::min (station->m_successThreshold,
+                                                      m_maxSuccessThreshold);
             } 
           else 
             {
-              m_successThreshold = m_stations->m_minSuccessThreshold;
+              station->m_successThreshold = m_minSuccessThreshold;
             }
-          m_recovery = false;
-          DecreaseRate ();
+          station->m_recovery = false;
+          DecreaseRate (station);
           needChange = true;
         } 
       else 
         {
-          m_recovery = false;
+          station->m_recovery = false;
         }
     }
-  if (IsEnough () || needChange) 
+  if (IsEnough (station) || needChange) 
     {
       NS_LOG_DEBUG ("Reset");
-      ResetCnt ();
+      ResetCnt (station);
     }
 }
-
-Ptr<WifiRemoteStationManager>
-AmrrWifiRemoteStation::GetManager (void) const
-{
-  return m_stations;
-}
 WifiMode 
-AmrrWifiRemoteStation::DoGetDataMode (uint32_t size)
+AmrrWifiManager::DoGetDataMode (WifiRemoteStation *st, uint32_t size)
 {
-  UpdateMode ();
-  NS_ASSERT (m_txrate < GetNSupportedModes ());
+  AmrrWifiRemoteStation *station = (AmrrWifiRemoteStation *)st;
+  UpdateMode (station);
+  NS_ASSERT (station->m_txrate < GetNSupported (station));
   uint32_t rateIndex;
-  if (m_retry < 1)
+  if (station->m_retry < 1)
     {
-      rateIndex = m_txrate;
+      rateIndex = station->m_txrate;
     }
-  else if (m_retry < 2)
+  else if (station->m_retry < 2)
     {
-      if (m_txrate > 0)
+      if (station->m_txrate > 0)
         {
-          rateIndex = m_txrate - 1;
+          rateIndex = station->m_txrate - 1;
         }
       else
         {
-          rateIndex = m_txrate;
+          rateIndex = station->m_txrate;
         }
     }
-  else if (m_retry < 3)
+  else if (station->m_retry < 3)
     {
-      if (m_txrate > 1)
+      if (station->m_txrate > 1)
         {
-          rateIndex = m_txrate - 2;
+          rateIndex = station->m_txrate - 2;
         }
       else
         {
-          rateIndex = m_txrate;
+          rateIndex = station->m_txrate;
         }
     }
   else
     {
-      if (m_txrate > 2)
+      if (station->m_txrate > 2)
         {
-          rateIndex = m_txrate - 3;
+          rateIndex = station->m_txrate - 3;
         }
       else
         {
-          rateIndex = m_txrate;
+          rateIndex = station->m_txrate;
         }
     }
 
-  return GetSupportedMode (rateIndex);
+  return GetSupported (station, rateIndex);
 }
 WifiMode 
-AmrrWifiRemoteStation::DoGetRtsMode (void)
+AmrrWifiManager::DoGetRtsMode (WifiRemoteStation *st)
 {
-  UpdateMode ();
+  AmrrWifiRemoteStation *station = (AmrrWifiRemoteStation *)st;
+  UpdateMode (station);
   // XXX: can we implement something smarter ?
-  return GetSupportedMode (0);
+  return GetSupported (station, 0);
+}
+
+
+bool 
+AmrrWifiManager::IsLowLatency (void) const
+{
+  return true;
 }
 
 } // namespace ns3
--- a/src/devices/wifi/amrr-wifi-manager.h	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/amrr-wifi-manager.h	Wed Jan 06 16:26:07 2010 +0100
@@ -25,6 +25,8 @@
 
 namespace ns3 {
 
+class AmrrWifiRemoteStation;
+
 /**
  * \brief AMRR Rate control algorithm
  *
@@ -41,8 +43,32 @@
   AmrrWifiManager ();
 
 private:
-  friend class AmrrWifiRemoteStation;
-  virtual WifiRemoteStation *CreateStation (void);
+  // overriden from base class
+  virtual class WifiRemoteStation *DoCreateStation (void) const;
+  virtual void DoReportRxOk (WifiRemoteStation *station, 
+                             double rxSnr, WifiMode txMode);
+  virtual void DoReportRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportDataFailed (WifiRemoteStation *station);
+  virtual void DoReportRtsOk (WifiRemoteStation *station,
+                              double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void DoReportDataOk (WifiRemoteStation *station,
+                               double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual void DoReportFinalRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportFinalDataFailed (WifiRemoteStation *station);
+  virtual WifiMode DoGetDataMode (WifiRemoteStation *station, uint32_t size);
+  virtual WifiMode DoGetRtsMode (WifiRemoteStation *station);
+  virtual bool IsLowLatency (void) const;
+
+  void UpdateRetry (AmrrWifiRemoteStation *station);
+  void UpdateMode (AmrrWifiRemoteStation *station);
+  void ResetCnt (AmrrWifiRemoteStation *station);
+  void IncreaseRate (AmrrWifiRemoteStation *station);
+  void DecreaseRate (AmrrWifiRemoteStation *station);
+  bool IsMinRate (AmrrWifiRemoteStation *station) const;
+  bool IsMaxRate (AmrrWifiRemoteStation *station) const;
+  bool IsSuccess (AmrrWifiRemoteStation *station) const;
+  bool IsFailure (AmrrWifiRemoteStation *station) const;
+  bool IsEnough (AmrrWifiRemoteStation *station) const;
 
   Time m_updatePeriod;
   double m_failureRatio;
@@ -51,52 +77,6 @@
   uint32_t m_minSuccessThreshold;
 };
 
-/**
- */
-class AmrrWifiRemoteStation : public WifiRemoteStation
-{
-public:
-  AmrrWifiRemoteStation (Ptr<AmrrWifiManager> stations);
-
-  virtual ~AmrrWifiRemoteStation ();
-
-protected:
-  virtual void DoReportRxOk (double rxSnr, WifiMode txMode);
-  virtual void DoReportRtsFailed (void);
-  virtual void DoReportDataFailed (void);
-  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
-  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
-  virtual void DoReportFinalRtsFailed (void);
-  virtual void DoReportFinalDataFailed (void);
-
-private:
-  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
-  virtual WifiMode DoGetDataMode (uint32_t size);
-  virtual WifiMode DoGetRtsMode (void);
-
-  void UpdateRetry (void);
-  void UpdateMode (void);
-  void ResetCnt (void);
-  void IncreaseRate (void);
-  void DecreaseRate (void);
-  bool IsMinRate (void) const;
-  bool IsMaxRate (void) const;
-  bool IsSuccess (void) const;
-  bool IsFailure (void) const;
-  bool IsEnough (void) const;
-
-  Ptr<AmrrWifiManager> m_stations;
-  Time m_nextModeUpdate;
-  uint32_t m_tx_ok;
-  uint32_t m_tx_err;
-  uint32_t m_tx_retr;
-  uint32_t m_retry;
-  uint32_t m_txrate;
-  uint32_t m_successThreshold;
-  uint32_t m_success;
-  bool m_recovery;
-};
-
 } // namespace ns3
 
 #endif /* AMRR_WIFI_MANAGER_H */
--- a/src/devices/wifi/arf-wifi-manager.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/arf-wifi-manager.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -27,193 +27,20 @@
 
 
 namespace ns3 {
-  
-ArfWifiRemoteStation::ArfWifiRemoteStation (Ptr<ArfWifiManager> manager)
-  : m_manager (manager)
-{
-  m_successThreshold = m_manager->m_successThreshold;
-  m_timerTimeout = m_manager->m_timerThreshold;
-  m_rate = GetMinRate ();
-
-  m_success = 0;
-  m_failed = 0;
-  m_recovery = false;
-  m_retry = 0;
-  m_timer = 0;
-}
-ArfWifiRemoteStation::~ArfWifiRemoteStation ()
-{}
-
-uint32_t
-ArfWifiRemoteStation::GetMaxRate (void)
-{
-  return GetNSupportedModes ();
-}
-uint32_t
-ArfWifiRemoteStation::GetMinRate (void)
-{
-  return 0;
-}
-
-bool 
-ArfWifiRemoteStation::NeedRecoveryFallback (void)
-{
-  if (m_retry == 1) 
-    {
-      return true;
-    } 
-  else 
-    {
-      return false;
-    }
-}
-bool 
-ArfWifiRemoteStation::NeedNormalFallback (void)
-{
-  int retryMod = (m_retry - 1) % 2;
-  if (retryMod == 1) 
-    {
-      return true;
-    } 
-  else 
-    {
-      return false;
-    }
-}
-
-
-
-void 
-ArfWifiRemoteStation::DoReportRtsFailed (void)
-{}
-/**
- * It is important to realize that "recovery" mode starts after failure of
- * the first transmission after a rate increase and ends at the first successful
- * transmission. Specifically, recovery mode transcends retransmissions boundaries.
- * Fundamentally, ARF handles each data transmission independently, whether it
- * is the initial transmission of a packet or the retransmission of a packet.
- * The fundamental reason for this is that there is a backoff between each data
- * transmission, be it an initial transmission or a retransmission.
- */
-void 
-ArfWifiRemoteStation::DoReportDataFailed (void)
-{
-  m_timer++;
-  m_failed++;
-  m_retry++;
-  m_success = 0;
 
-  if (m_recovery) 
-    {
-      NS_ASSERT (m_retry >= 1);
-      if (NeedRecoveryFallback ()) 
-        {
-          ReportRecoveryFailure ();
-          if (m_rate != GetMinRate ()) 
-            {
-              m_rate--;
-            }
-        }
-      m_timer = 0;
-    } 
-  else 
-    {
-      NS_ASSERT (m_retry >= 1);
-      if (NeedNormalFallback ()) 
-        {
-          ReportFailure ();
-          if (m_rate != GetMinRate ()) 
-            {
-              m_rate--;
-            }
-        }
-      if (m_retry >= 2) 
-        {
-          m_timer = 0;
-        }
-    }
-}
-void 
-ArfWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
-{}
-void ArfWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
-{
-  NS_LOG_DEBUG ("self="<<this<<" rts ok");
-}
-void ArfWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+struct ArfWifiRemoteStation : public WifiRemoteStation
 {
-  m_timer++;
-  m_success++;
-  m_failed = 0;
-  m_recovery = false;
-  m_retry = 0;
-  NS_LOG_DEBUG ("self="<<this<<" data ok success="<<m_success<<", timer="<<m_timer);
-  if ((m_success == GetSuccessThreshold () ||
-       m_timer == GetTimerTimeout ()) &&
-      (m_rate < (GetMaxRate () - 1))) 
-    {
-      NS_LOG_DEBUG ("self="<<this<<" inc rate");
-      m_rate++;
-      m_timer = 0;
-      m_success = 0;
-      m_recovery = true;
-    }
-}
-void 
-ArfWifiRemoteStation::DoReportFinalRtsFailed (void)
-{}
-void 
-ArfWifiRemoteStation::DoReportFinalDataFailed (void)
-{}
+  uint32_t m_timer;
+  uint32_t m_success;
+  uint32_t m_failed;
+  bool m_recovery;
+  uint32_t m_retry;
+  
+  uint32_t m_timerTimeout;
+  uint32_t m_successThreshold;
 
-WifiMode
-ArfWifiRemoteStation::DoGetDataMode (uint32_t size)
-{
-  return GetSupportedMode (m_rate);
-}
-WifiMode
-ArfWifiRemoteStation::DoGetRtsMode (void)
-{
-  // XXX: we could/should implement the Arf algorithm for
-  // RTS only by picking a single rate within the BasicRateSet.
-  return GetSupportedMode (0);
-}
-
-void ArfWifiRemoteStation::ReportRecoveryFailure (void)
-{}
-void ArfWifiRemoteStation::ReportFailure (void)
-{}
-uint32_t ArfWifiRemoteStation::GetMinTimerTimeout (void)
-{
-  return m_manager->m_timerThreshold;
-}
-uint32_t ArfWifiRemoteStation::GetMinSuccessThreshold (void)
-{
-  return m_manager->m_successThreshold;
-}
-uint32_t ArfWifiRemoteStation::GetTimerTimeout (void)
-{
-  return m_timerTimeout;
-}
-uint32_t ArfWifiRemoteStation::GetSuccessThreshold (void)
-{
-  return m_successThreshold;
-}
-void ArfWifiRemoteStation::SetTimerTimeout (uint32_t timerTimeout)
-{
-  NS_ASSERT (timerTimeout >= m_manager->m_timerThreshold);
-  m_timerTimeout = timerTimeout;
-}
-void ArfWifiRemoteStation::SetSuccessThreshold (uint32_t successThreshold)
-{
-  NS_ASSERT (successThreshold >= m_manager->m_successThreshold);
-  m_successThreshold = successThreshold;
-}
-Ptr<WifiRemoteStationManager>
-ArfWifiRemoteStation::GetManager (void) const
-{
-  return m_manager;
-}
+  uint32_t m_rate;
+};
 
 NS_OBJECT_ENSURE_REGISTERED (ArfWifiManager);
 
@@ -241,9 +68,129 @@
 ArfWifiManager::~ArfWifiManager ()
 {}
 WifiRemoteStation *
-ArfWifiManager::CreateStation (void)
+ArfWifiManager::DoCreateStation (void) const
+{
+  ArfWifiRemoteStation *station = new ArfWifiRemoteStation ();
+
+  station->m_successThreshold = m_successThreshold;
+  station->m_timerTimeout = m_timerThreshold;
+  station->m_rate = 0;
+  station->m_success = 0;
+  station->m_failed = 0;
+  station->m_recovery = false;
+  station->m_retry = 0;
+  station->m_timer = 0;
+
+  return station;
+}
+
+void 
+ArfWifiManager::DoReportRtsFailed (WifiRemoteStation *station)
+{}
+/**
+ * It is important to realize that "recovery" mode starts after failure of
+ * the first transmission after a rate increase and ends at the first successful
+ * transmission. Specifically, recovery mode transcends retransmissions boundaries.
+ * Fundamentally, ARF handles each data transmission independently, whether it
+ * is the initial transmission of a packet or the retransmission of a packet.
+ * The fundamental reason for this is that there is a backoff between each data
+ * transmission, be it an initial transmission or a retransmission.
+ */
+void 
+ArfWifiManager::DoReportDataFailed (WifiRemoteStation *st)
 {
-  return new ArfWifiRemoteStation (this);
+  ArfWifiRemoteStation *station = (ArfWifiRemoteStation *)st;
+  station->m_timer++;
+  station->m_failed++;
+  station->m_retry++;
+  station->m_success = 0;
+
+  if (station->m_recovery) 
+    {
+      NS_ASSERT (station->m_retry >= 1);
+      if (station->m_retry == 1)
+        {
+          // need recovery fallback
+          if (station->m_rate != 0)
+            {
+              station->m_rate--;
+            }
+        }
+      station->m_timer = 0;
+    } 
+  else 
+    {
+      NS_ASSERT (station->m_retry >= 1);
+      if (((station->m_retry - 1) % 2) == 1)
+        {
+          // need normal fallback
+          if (station->m_rate != 0)
+            {
+              station->m_rate--;
+            }
+        }
+      if (station->m_retry >= 2) 
+        {
+          station->m_timer = 0;
+        }
+    }
+}
+void 
+ArfWifiManager::DoReportRxOk (WifiRemoteStation *station,
+                              double rxSnr, WifiMode txMode)
+{}
+void ArfWifiManager::DoReportRtsOk (WifiRemoteStation *station,
+                                    double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+  NS_LOG_DEBUG ("station="<<station<<" rts ok");
+}
+void ArfWifiManager::DoReportDataOk (WifiRemoteStation *st,
+                                     double ackSnr, WifiMode ackMode, double dataSnr)
+{
+  ArfWifiRemoteStation *station = (ArfWifiRemoteStation *) st;
+  station->m_timer++;
+  station->m_success++;
+  station->m_failed = 0;
+  station->m_recovery = false;
+  station->m_retry = 0;
+  NS_LOG_DEBUG ("station=" << station << " data ok success=" << station->m_success << ", timer=" << station->m_timer);
+  if ((station->m_success == m_successThreshold ||
+       station->m_timer == m_timerThreshold) &&
+      (station->m_rate < (station->m_state->m_modes.size () - 1))) 
+    {
+      NS_LOG_DEBUG ("station="<<station<<" inc rate");
+      station->m_rate++;
+      station->m_timer = 0;
+      station->m_success = 0;
+      station->m_recovery = true;
+    }
+}
+void 
+ArfWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *station)
+{}
+void 
+ArfWifiManager::DoReportFinalDataFailed (WifiRemoteStation *station)
+{}
+
+WifiMode
+ArfWifiManager::DoGetDataMode (WifiRemoteStation *st, uint32_t size)
+{
+  ArfWifiRemoteStation *station = (ArfWifiRemoteStation *) st;
+  return GetSupported (station, station->m_rate);
+}
+WifiMode
+ArfWifiManager::DoGetRtsMode (WifiRemoteStation *st)
+{
+  // XXX: we could/should implement the Arf algorithm for
+  // RTS only by picking a single rate within the BasicRateSet.
+  ArfWifiRemoteStation *station = (ArfWifiRemoteStation *) st;
+  return GetSupported (station, 0);
+}
+
+bool 
+ArfWifiManager::IsLowLatency (void) const
+{
+  return true;
 }
 
 } // namespace ns3
--- a/src/devices/wifi/arf-wifi-manager.h	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/arf-wifi-manager.h	Wed Jan 06 16:26:07 2010 +0100
@@ -46,69 +46,26 @@
   virtual ~ArfWifiManager ();
 
 private:
-  friend class ArfWifiRemoteStation;
-  virtual class WifiRemoteStation *CreateStation (void);
+  // overriden from base class
+  virtual class WifiRemoteStation *DoCreateStation (void) const;
+  virtual void DoReportRxOk (WifiRemoteStation *station, 
+                             double rxSnr, WifiMode txMode);
+  virtual void DoReportRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportDataFailed (WifiRemoteStation *station);
+  virtual void DoReportRtsOk (WifiRemoteStation *station,
+                              double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void DoReportDataOk (WifiRemoteStation *station,
+                               double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual void DoReportFinalRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportFinalDataFailed (WifiRemoteStation *station);
+  virtual WifiMode DoGetDataMode (WifiRemoteStation *station, uint32_t size);
+  virtual WifiMode DoGetRtsMode (WifiRemoteStation *station);
+  virtual bool IsLowLatency (void) const;
+
   uint32_t m_timerThreshold;
   uint32_t m_successThreshold;
 };
 
-
-class ArfWifiRemoteStation : public WifiRemoteStation
-{
-public:
-  ArfWifiRemoteStation (Ptr<ArfWifiManager> manager);
-  virtual ~ArfWifiRemoteStation ();
-
-protected:
-  virtual void DoReportRxOk (double rxSnr, WifiMode txMode);
-  virtual void DoReportRtsFailed (void);
-  virtual void DoReportDataFailed (void);
-  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
-  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
-  virtual void DoReportFinalRtsFailed (void);
-  virtual void DoReportFinalDataFailed (void);
-
-private:
-  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
-  virtual WifiMode DoGetDataMode (uint32_t size);
-  virtual WifiMode DoGetRtsMode (void);
-
-  uint32_t m_timer;
-  uint32_t m_success;
-  uint32_t m_failed;
-  bool m_recovery;
-  uint32_t m_retry;
-  
-  uint32_t m_timerTimeout;
-  uint32_t m_successThreshold;
-
-  uint32_t m_rate;
-  
-  Ptr<ArfWifiManager> m_manager;
-  
-private:
-  // overriden by AarfMacStation.
-  virtual void ReportRecoveryFailure (void);
-  virtual void ReportFailure (void);
-
-  uint32_t GetMaxRate (void);
-  uint32_t GetMinRate (void);
-
-  bool NeedRecoveryFallback (void);
-  bool NeedNormalFallback (void);
-  
-protected:
-  // called by AarfMacStation.
-  uint32_t GetMinTimerTimeout (void);
-  uint32_t GetMinSuccessThreshold (void);
-  
-  uint32_t GetTimerTimeout (void);
-  uint32_t GetSuccessThreshold (void);
-  
-  void SetTimerTimeout (uint32_t timerTimeout);
-  void SetSuccessThreshold (uint32_t successThreshold);
-};
-
 } // namespace ns3
 
 #endif /* ARF_WIFI_MANAGER_H */
--- a/src/devices/wifi/cara-wifi-manager.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/cara-wifi-manager.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -21,6 +21,8 @@
 #include "cara-wifi-manager.h"
 #include "ns3/assert.h"
 #include "ns3/log.h"
+#include "ns3/double.h"
+#include "ns3/uinteger.h"
 #include "ns3/simulator.h"
 
 NS_LOG_COMPONENT_DEFINE ("Cara");
@@ -28,125 +30,15 @@
 
 namespace ns3 {
 
-NS_OBJECT_ENSURE_REGISTERED(CaraWifiManager);
-
-CaraWifiRemoteStation::CaraWifiRemoteStation (Ptr<CaraWifiManager> manager)
-  : m_manager (manager)
-{
-  m_rate = GetMinRate ();
-
-  m_success = 0;
-  m_failed = 0;
-  m_timer = 0;
-}
-CaraWifiRemoteStation::~CaraWifiRemoteStation ()
-{}
-
-uint32_t
-CaraWifiRemoteStation::GetMaxRate (void)
-{
-  return GetNSupportedModes () - 1;
-}
-uint32_t
-CaraWifiRemoteStation::GetMinRate (void)
-{
-  return 0;
-}
-
-bool 
-CaraWifiRemoteStation::NeedNormalFallback (void)
-{
-  return (m_failed >= m_manager->m_failureThreshold);
-}
-
-void 
-CaraWifiRemoteStation::DoReportRtsFailed (void) 
-{}
-
-void 
-CaraWifiRemoteStation::DoReportDataFailed (void)
-{
-  NS_LOG_FUNCTION (this);
-  m_timer++;
-  m_failed++;
-  m_success = 0;
-  if (NeedNormalFallback ()) 
-    {
-      NS_LOG_DEBUG ("self="<<this<<" dec rate");
-      if (m_rate != GetMinRate ())
-        {
-          m_rate--;
-        }
-      m_failed = 0;
-      m_timer = 0;
-    }
-}
-void 
-CaraWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
-{}
-void 
-CaraWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
+struct CaraWifiRemoteStation : public WifiRemoteStation
 {
-  NS_LOG_DEBUG ("self="<<this<<" rts ok");
-}
-void 
-CaraWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
-{
-  m_timer++;
-  m_success++;
-  m_failed = 0;
-  NS_LOG_DEBUG ("self="<<this<<" data ok success="<<m_success<<", timer="<<m_timer);
-  if ((m_success == m_manager->m_successThreshold ||
-       m_timer >= m_manager->m_timerTimeout))
-    {
-      if (m_rate < GetMaxRate ())
-        {
-          m_rate++;
-        }
-      NS_LOG_DEBUG ("self="<<this<<" inc rate=" << m_rate);
-      m_timer = 0;
-      m_success = 0;
-    }
-}
-void 
-CaraWifiRemoteStation::DoReportFinalRtsFailed (void)
-{}
-void 
-CaraWifiRemoteStation::DoReportFinalDataFailed (void)
-{}
+  uint32_t m_timer;
+  uint32_t m_success;
+  uint32_t m_failed;  
+  uint32_t m_rate;
+};
 
-WifiMode
-CaraWifiRemoteStation::DoGetDataMode (uint32_t size)
-{
-  return GetSupportedMode (m_rate);
-}
-WifiMode
-CaraWifiRemoteStation::DoGetRtsMode (void)
-{
-  // XXX: we could/should implement the Arf algorithm for
-  // RTS only by picking a single rate within the BasicRateSet.
-  return GetSupportedMode (0);
-}
-
-Ptr<WifiRemoteStationManager>
-CaraWifiRemoteStation::GetManager (void) const
-{
-  return m_manager;
-}
-
-bool
-CaraWifiRemoteStation::NeedRts (Ptr<const Packet> packet)
-{
-  bool rts = WifiRemoteStation::NeedRts (packet);
-  if (rts || m_failed >= m_manager->m_probeThreshold)
-    {
-      return true;
-    }
-
-  return false;
-}
-
-
+NS_OBJECT_ENSURE_REGISTERED(CaraWifiManager);
 
 TypeId 
 CaraWifiManager::GetTypeId (void)
@@ -185,9 +77,104 @@
 {}
 
 WifiRemoteStation *
-CaraWifiManager::CreateStation (void)
+CaraWifiManager::DoCreateStation (void) const
+{
+  CaraWifiRemoteStation *station = new CaraWifiRemoteStation ();
+  station->m_rate = 0;
+  station->m_success = 0;
+  station->m_failed = 0;
+  station->m_timer = 0;
+  return station;
+}
+
+void 
+CaraWifiManager::DoReportRtsFailed (WifiRemoteStation *st)
+{}
+
+void 
+CaraWifiManager::DoReportDataFailed (WifiRemoteStation *st)
+{
+  CaraWifiRemoteStation *station = (CaraWifiRemoteStation *) st;
+  NS_LOG_FUNCTION (station);
+  station->m_timer++;
+  station->m_failed++;
+  station->m_success = 0;
+  if (station->m_failed >= m_failureThreshold) 
+    {
+      NS_LOG_DEBUG ("self="<<station<<" dec rate");
+      if (station->m_rate != 0)
+        {
+          station->m_rate--;
+        }
+      station->m_failed = 0;
+      station->m_timer = 0;
+    }
+}
+void 
+CaraWifiManager::DoReportRxOk (WifiRemoteStation *st,
+                                     double rxSnr, WifiMode txMode)
+{}
+void 
+CaraWifiManager::DoReportRtsOk (WifiRemoteStation *st,
+                                      double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+  NS_LOG_DEBUG ("self="<<st<<" rts ok");
+}
+void 
+CaraWifiManager::DoReportDataOk (WifiRemoteStation *st,
+                                       double ackSnr, WifiMode ackMode, double dataSnr)
 {
-  return new CaraWifiRemoteStation (this);
+  CaraWifiRemoteStation *station = (CaraWifiRemoteStation *) st;
+  station->m_timer++;
+  station->m_success++;
+  station->m_failed = 0;
+  NS_LOG_DEBUG ("self="<<station<<" data ok success="<<station->m_success<<", timer="<<station->m_timer);
+  if ((station->m_success == m_successThreshold ||
+       station->m_timer >= m_timerTimeout))
+    {
+      if (station->m_rate < GetNSupported (station) - 1)
+        {
+          station->m_rate++;
+        }
+      NS_LOG_DEBUG ("self="<<station<<" inc rate=" << station->m_rate);
+      station->m_timer = 0;
+      station->m_success = 0;
+    }
+}
+void 
+CaraWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *st)
+{}
+void 
+CaraWifiManager::DoReportFinalDataFailed (WifiRemoteStation *st)
+{}
+
+WifiMode
+CaraWifiManager::DoGetDataMode (WifiRemoteStation *st,
+                                      uint32_t size)
+{
+  CaraWifiRemoteStation *station = (CaraWifiRemoteStation *) st;
+  return GetSupported (station, station->m_rate);
+}
+WifiMode
+CaraWifiManager::DoGetRtsMode (WifiRemoteStation *st)
+{
+  // XXX: we could/should implement the Arf algorithm for
+  // RTS only by picking a single rate within the BasicRateSet.
+  return GetSupported (st, 0);
+}
+
+bool
+CaraWifiManager::DoNeedRts (WifiRemoteStation *st,
+                                  Ptr<const Packet> packet, bool normally)
+{
+  CaraWifiRemoteStation *station = (CaraWifiRemoteStation *) st;
+  return normally || station->m_failed >= m_probeThreshold;
+}
+
+bool 
+CaraWifiManager::IsLowLatency (void) const
+{
+  return true;
 }
 
 } // namespace ns3
--- a/src/devices/wifi/cara-wifi-manager.h	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/cara-wifi-manager.h	Wed Jan 06 16:26:07 2010 +0100
@@ -42,50 +42,30 @@
   virtual ~CaraWifiManager ();
 
 private:
-  friend class CaraWifiRemoteStation;
-  virtual class WifiRemoteStation *CreateStation (void);
+  // overriden from base class
+  virtual class WifiRemoteStation *DoCreateStation (void) const;
+  virtual void DoReportRxOk (WifiRemoteStation *station, 
+                             double rxSnr, WifiMode txMode);
+  virtual void DoReportRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportDataFailed (WifiRemoteStation *station);
+  virtual void DoReportRtsOk (WifiRemoteStation *station,
+                              double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void DoReportDataOk (WifiRemoteStation *station,
+                               double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual void DoReportFinalRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportFinalDataFailed (WifiRemoteStation *station);
+  virtual WifiMode DoGetDataMode (WifiRemoteStation *station, uint32_t size);
+  virtual WifiMode DoGetRtsMode (WifiRemoteStation *station);
+  virtual bool DoNeedRts (WifiRemoteStation *station,
+                          Ptr<const Packet> packet, bool normally);
+  virtual bool IsLowLatency (void) const;
+
   uint32_t m_timerTimeout;
   uint32_t m_successThreshold;
   uint32_t m_failureThreshold;
   uint32_t m_probeThreshold;
 };
 
-
-class CaraWifiRemoteStation : public WifiRemoteStation
-{
-public:
-  CaraWifiRemoteStation (Ptr<CaraWifiManager> manager);
-  virtual ~CaraWifiRemoteStation ();
-
-private:
-  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
-  virtual void DoReportRtsFailed (void);
-  virtual void DoReportDataFailed (void);
-  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
-  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
-  virtual void DoReportFinalRtsFailed (void);
-  virtual void DoReportFinalDataFailed (void);
-  virtual void DoReportRxOk (double rxSnr, WifiMode txMode);
-  virtual WifiMode DoGetDataMode (uint32_t size);
-  virtual WifiMode DoGetRtsMode (void);
-
-  virtual bool NeedRts (Ptr<const Packet> packet);
-
-  uint32_t m_timer;
-  uint32_t m_success;
-  uint32_t m_failed;
-  
-  uint32_t m_rate;
-  
-  Ptr<CaraWifiManager> m_manager;
-  
-  uint32_t GetMaxRate (void);
-  uint32_t GetMinRate (void);
-
-  bool NeedNormalFallback (void);
-  
-};
-
 } // namespace ns3
 
 #endif /* CARA_WIFI_MANAGER_H */
--- a/src/devices/wifi/constant-rate-wifi-manager.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/constant-rate-wifi-manager.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -25,50 +25,6 @@
 
 namespace ns3 {
 
-ConstantRateWifiRemoteStation::ConstantRateWifiRemoteStation (Ptr<ConstantRateWifiManager> manager)
-  : m_manager (manager)
-{}
-ConstantRateWifiRemoteStation::~ConstantRateWifiRemoteStation ()
-{}
-
-void 
-ConstantRateWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
-{}
-void 
-ConstantRateWifiRemoteStation::DoReportRtsFailed (void)
-{}
-void 
-ConstantRateWifiRemoteStation::DoReportDataFailed (void)
-{}
-void 
-ConstantRateWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
-{}
-void 
-ConstantRateWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
-{}
-void 
-ConstantRateWifiRemoteStation::DoReportFinalRtsFailed (void)
-{}
-void 
-ConstantRateWifiRemoteStation::DoReportFinalDataFailed (void)
-{}
-
-WifiMode 
-ConstantRateWifiRemoteStation::DoGetDataMode (uint32_t size)
-{
-  return m_manager->GetDataMode ();
-}
-WifiMode 
-ConstantRateWifiRemoteStation::DoGetRtsMode (void)
-{
-  return m_manager->GetCtlMode ();
-}
-Ptr<WifiRemoteStationManager>
-ConstantRateWifiRemoteStation::GetManager (void) const
-{
-  return m_manager;
-}
-
 NS_OBJECT_ENSURE_REGISTERED (ConstantRateWifiManager);
 
 TypeId 
@@ -94,22 +50,57 @@
 ConstantRateWifiManager::~ConstantRateWifiManager ()
 {}
 
-WifiMode 
-ConstantRateWifiManager::GetDataMode (void) const
+
+WifiRemoteStation *
+ConstantRateWifiManager::DoCreateStation (void) const
+{
+  WifiRemoteStation *station = new WifiRemoteStation ();
+  return station;
+}
+
+
+void 
+ConstantRateWifiManager::DoReportRxOk (WifiRemoteStation *station,
+                                double rxSnr, WifiMode txMode)
+{}
+void 
+ConstantRateWifiManager::DoReportRtsFailed (WifiRemoteStation *station)
+{}
+void 
+ConstantRateWifiManager::DoReportDataFailed (WifiRemoteStation *station)
+{}
+void 
+ConstantRateWifiManager::DoReportRtsOk (WifiRemoteStation *st,
+                                 double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+}
+void 
+ConstantRateWifiManager::DoReportDataOk (WifiRemoteStation *st,
+                                  double ackSnr, WifiMode ackMode, double dataSnr)
+{
+}
+void 
+ConstantRateWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *station)
+{}
+void 
+ConstantRateWifiManager::DoReportFinalDataFailed (WifiRemoteStation *station)
+{}
+
+WifiMode
+ConstantRateWifiManager::DoGetDataMode (WifiRemoteStation *st, uint32_t size)
 {
   return m_dataMode;
 }
-WifiMode 
-ConstantRateWifiManager::GetCtlMode (void) const
+WifiMode
+ConstantRateWifiManager::DoGetRtsMode (WifiRemoteStation *st)
 {
   return m_ctlMode;
 }
 
-
-WifiRemoteStation *
-ConstantRateWifiManager::CreateStation (void)
+bool 
+ConstantRateWifiManager::IsLowLatency (void) const
 {
-  return new ConstantRateWifiRemoteStation (this);
+  return true;
 }
 
 } // namespace ns3
--- a/src/devices/wifi/constant-rate-wifi-manager.h	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/constant-rate-wifi-manager.h	Wed Jan 06 16:26:07 2010 +0100
@@ -39,38 +39,27 @@
   ConstantRateWifiManager ();
   virtual ~ConstantRateWifiManager ();
 
-  WifiMode GetDataMode (void) const;
-  WifiMode GetCtlMode (void) const;
 private:
-  virtual class WifiRemoteStation *CreateStation (void);
+  // overriden from base class
+  virtual class WifiRemoteStation *DoCreateStation (void) const;
+  virtual void DoReportRxOk (WifiRemoteStation *station, 
+                             double rxSnr, WifiMode txMode);
+  virtual void DoReportRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportDataFailed (WifiRemoteStation *station);
+  virtual void DoReportRtsOk (WifiRemoteStation *station,
+                              double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void DoReportDataOk (WifiRemoteStation *station,
+                               double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual void DoReportFinalRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportFinalDataFailed (WifiRemoteStation *station);
+  virtual WifiMode DoGetDataMode (WifiRemoteStation *station, uint32_t size);
+  virtual WifiMode DoGetRtsMode (WifiRemoteStation *station);
+  virtual bool IsLowLatency (void) const;
 
   WifiMode m_dataMode;
   WifiMode m_ctlMode;
 };
 
-
-class ConstantRateWifiRemoteStation : public WifiRemoteStation
-{
-public:
-  ConstantRateWifiRemoteStation (Ptr<ConstantRateWifiManager> stations);
-  virtual ~ConstantRateWifiRemoteStation ();
-
-protected:
-  virtual void DoReportRxOk (double rxSnr, WifiMode txMode);
-  virtual void DoReportRtsFailed (void);
-  virtual void DoReportDataFailed (void);
-  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
-  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
-  virtual void DoReportFinalRtsFailed (void);
-  virtual void DoReportFinalDataFailed (void);
-
-private:
-  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
-  virtual WifiMode DoGetDataMode (uint32_t size);
-  virtual WifiMode DoGetRtsMode (void);
-  Ptr<ConstantRateWifiManager> m_manager;
-};
-
 } // namespace ns3
 
 
--- a/src/devices/wifi/dca-txop.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/dca-txop.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -225,18 +225,12 @@
   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_stationManager->PrepareForQueue (hdr.GetAddr1 (), &hdr,
+                                     packet, fullPacketSize);
   m_queue->Enqueue (packet, hdr);
   StartAccessIfNeeded ();
 }
 
-WifiRemoteStation *
-DcaTxop::GetStation (Mac48Address ad) const
-{
-  return m_stationManager->Lookup (ad);
-}
-
 void
 DcaTxop::RestartAccessIfNeeded (void)
 {
@@ -271,28 +265,28 @@
 bool
 DcaTxop::NeedRts (void)
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->NeedRts (m_currentPacket);
+  return m_stationManager->NeedRts (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                    m_currentPacket);
 }
 
 bool
 DcaTxop::NeedRtsRetransmission (void)
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->NeedRtsRetransmission (m_currentPacket);
+  return m_stationManager->NeedRtsRetransmission (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                                  m_currentPacket);
 }
 
 bool
 DcaTxop::NeedDataRetransmission (void)
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->NeedDataRetransmission (m_currentPacket);
+  return m_stationManager->NeedDataRetransmission (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                                   m_currentPacket);
 }
 bool
 DcaTxop::NeedFragmentation (void)
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->NeedFragmentation (m_currentPacket);
+  return m_stationManager->NeedFragmentation (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                              m_currentPacket);
 }
 
 void
@@ -304,28 +298,28 @@
 uint32_t
 DcaTxop::GetFragmentSize (void)
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->GetFragmentSize (m_currentPacket, m_fragmentNumber);
+  return m_stationManager->GetFragmentSize (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                            m_currentPacket, m_fragmentNumber);
 }
 bool
 DcaTxop::IsLastFragment (void) 
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->IsLastFragment (m_currentPacket, m_fragmentNumber);
+  return m_stationManager->IsLastFragment (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                           m_currentPacket, m_fragmentNumber);
 }
 
 uint32_t
 DcaTxop::GetNextFragmentSize (void) 
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->GetFragmentSize (m_currentPacket, m_fragmentNumber + 1);
+  return m_stationManager->GetFragmentSize (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                            m_currentPacket, m_fragmentNumber + 1);
 }
 
 uint32_t
 DcaTxop::GetFragmentOffset (void) 
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->GetFragmentOffset (m_currentPacket, m_fragmentNumber);
+  return m_stationManager->GetFragmentOffset (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                              m_currentPacket, m_fragmentNumber);
 }
 
 Ptr<Packet>
@@ -470,8 +464,7 @@
   if (!NeedRtsRetransmission ())
     {
       MY_DEBUG ("Cts Fail");
-      WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-      station->ReportFinalRtsFailed ();
+      m_stationManager->ReportFinalRtsFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
       if (!m_txFailedCallback.IsNull ()) 
         {
           m_txFailedCallback (m_currentHdr);
@@ -521,8 +514,7 @@
   if (!NeedDataRetransmission ()) 
     {
       MY_DEBUG ("Ack Fail");
-      WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-      station->ReportFinalDataFailed ();
+      m_stationManager->ReportFinalDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
       if (!m_txFailedCallback.IsNull ()) 
         {
           m_txFailedCallback (m_currentHdr);
--- a/src/devices/wifi/dca-txop.h	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/dca-txop.h	Wed Jan 06 16:26:07 2010 +0100
@@ -148,7 +148,6 @@
   uint32_t GetNextFragmentSize (void);
   uint32_t GetFragmentSize (void);
   uint32_t GetFragmentOffset (void);
-  WifiRemoteStation *GetStation (Mac48Address to) const;
   bool IsLastFragment (void);
   void NextFragment (void);
   Ptr<Packet> GetFragmentPacket (WifiMacHeader *hdr);
--- a/src/devices/wifi/edca-txop-n.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/edca-txop-n.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -412,8 +412,7 @@
   if (!NeedRtsRetransmission ())
     {
       MY_DEBUG ("Cts Fail");
-      WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-      station->ReportFinalRtsFailed ();
+      m_stationManager->ReportFinalRtsFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
       if (!m_txFailedCallback.IsNull ()) 
         {
           m_txFailedCallback (m_currentHdr);
@@ -443,8 +442,8 @@
   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_stationManager->PrepareForQueue (hdr.GetAddr1 (), &hdr,
+                                     packet, fullPacketSize);
   m_queue->Enqueue (packet, hdr);
   StartAccessIfNeeded ();
 }
@@ -482,8 +481,7 @@
   if (!NeedDataRetransmission ()) 
     {
       MY_DEBUG ("Ack Fail");
-      WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-      station->ReportFinalDataFailed ();
+      m_stationManager->ReportFinalDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
       if (!m_txFailedCallback.IsNull ()) 
         {
           m_txFailedCallback (m_currentHdr);
@@ -535,22 +533,22 @@
 bool
 EdcaTxopN::NeedRts (void)
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->NeedRts (m_currentPacket);
+  return m_stationManager->NeedRts (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                    m_currentPacket);
 }
 
 bool
 EdcaTxopN::NeedRtsRetransmission (void)
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->NeedRtsRetransmission (m_currentPacket);
+  return m_stationManager->NeedRtsRetransmission (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                                  m_currentPacket);
 }
 
 bool
 EdcaTxopN::NeedDataRetransmission (void)
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->NeedDataRetransmission (m_currentPacket);
+  return m_stationManager->NeedDataRetransmission (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                                   m_currentPacket);
 }
 
 void
@@ -593,42 +591,37 @@
 bool
 EdcaTxopN::NeedFragmentation (void) const
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->NeedFragmentation (m_currentPacket);
+  return m_stationManager->NeedFragmentation (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                              m_currentPacket);
 }
 
 uint32_t
 EdcaTxopN::GetFragmentSize (void)
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->GetFragmentSize (m_currentPacket, m_fragmentNumber);
+  return m_stationManager->GetFragmentSize (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                            m_currentPacket, m_fragmentNumber);
 }
 
 uint32_t
 EdcaTxopN::GetNextFragmentSize (void) 
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->GetFragmentSize (m_currentPacket, m_fragmentNumber + 1);
+  return m_stationManager->GetFragmentSize (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                            m_currentPacket, m_fragmentNumber + 1);
 }
 
 uint32_t
 EdcaTxopN::GetFragmentOffset (void) 
 {
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  return station->GetFragmentOffset (m_currentPacket, m_fragmentNumber);
+  return m_stationManager->GetFragmentOffset (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                              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);
+  return m_stationManager->IsLastFragment (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                           m_currentPacket, m_fragmentNumber);
 }
 
 Ptr<Packet>
--- a/src/devices/wifi/edca-txop-n.h	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/edca-txop-n.h	Wed Jan 06 16:26:07 2010 +0100
@@ -123,7 +123,6 @@
   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<Packet> GetFragmentPacket (WifiMacHeader *hdr);
--- a/src/devices/wifi/ideal-wifi-manager.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/ideal-wifi-manager.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -25,6 +25,11 @@
 
 namespace ns3 {
 
+struct IdealWifiRemoteStation : public WifiRemoteStation
+{
+  double m_lastSnr;
+};
+
 NS_OBJECT_ENSURE_REGISTERED (IdealWifiManager);
 
 TypeId 
@@ -60,12 +65,6 @@
   WifiRemoteStationManager::SetupPhy (phy);
 }
 
-WifiRemoteStation *
-IdealWifiManager::CreateStation (void)
-{
-  return new IdealWifiRemoteStation (this);
-}
-
 double 
 IdealWifiManager::GetSnrThreshold (WifiMode mode) const
 {
@@ -86,52 +85,61 @@
   m_thresholds.push_back (std::make_pair (snr,mode));
 }
 
-IdealWifiRemoteStation::IdealWifiRemoteStation (Ptr<IdealWifiManager> manager)
-  : m_manager (manager),
-    m_lastSnr (0.0)
-{}
-IdealWifiRemoteStation::~IdealWifiRemoteStation ()
+WifiRemoteStation *
+IdealWifiManager::DoCreateStation (void) const
+{
+  IdealWifiRemoteStation *station = new IdealWifiRemoteStation ();
+  station->m_lastSnr = 0.0;
+  return station;
+}
+
+
+void 
+IdealWifiManager::DoReportRxOk (WifiRemoteStation *station,
+                                double rxSnr, WifiMode txMode)
 {}
 void 
-IdealWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
-{}
-void 
-IdealWifiRemoteStation::DoReportRtsFailed (void)
+IdealWifiManager::DoReportRtsFailed (WifiRemoteStation *station)
 {}
 void 
-IdealWifiRemoteStation::DoReportDataFailed (void)
+IdealWifiManager::DoReportDataFailed (WifiRemoteStation *station)
 {}
 void 
-IdealWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
+IdealWifiManager::DoReportRtsOk (WifiRemoteStation *st,
+                                 double ctsSnr, WifiMode ctsMode, double rtsSnr)
 {
-  m_lastSnr = rtsSnr;
+  IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st;
+  station->m_lastSnr = rtsSnr;
 }
 void 
-IdealWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+IdealWifiManager::DoReportDataOk (WifiRemoteStation *st,
+                                  double ackSnr, WifiMode ackMode, double dataSnr)
 {
-  m_lastSnr = dataSnr;
+  IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st;
+  station->m_lastSnr = dataSnr;
 }
 void 
-IdealWifiRemoteStation::DoReportFinalRtsFailed (void)
+IdealWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *station)
 {}
 void 
-IdealWifiRemoteStation::DoReportFinalDataFailed (void)
+IdealWifiManager::DoReportFinalDataFailed (WifiRemoteStation *station)
 {}
 
 WifiMode
-IdealWifiRemoteStation::DoGetDataMode (uint32_t size)
+IdealWifiManager::DoGetDataMode (WifiRemoteStation *st, uint32_t size)
 {
+  IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st;
   // We search within the Supported rate set the mode with the 
   // highest snr threshold possible which is smaller than m_lastSnr 
   // to ensure correct packet delivery.
   double maxThreshold = 0.0;
-  WifiMode maxMode = m_manager->GetDefaultMode ();
-  for (uint32_t i = 0; i < GetNSupportedModes (); i++)
+  WifiMode maxMode = GetDefaultMode ();
+  for (uint32_t i = 0; i < GetNSupported (station); i++)
     {
-      WifiMode mode = GetSupportedMode (i);
-      double threshold = m_manager->GetSnrThreshold (mode);
+      WifiMode mode = GetSupported (station, i);
+      double threshold = GetSnrThreshold (mode);
       if (threshold > maxThreshold && 
-          threshold < m_lastSnr)
+          threshold < station->m_lastSnr)
         {
           maxThreshold = threshold;
           maxMode = mode;
@@ -140,19 +148,20 @@
   return maxMode;
 }
 WifiMode
-IdealWifiRemoteStation::DoGetRtsMode (void)
+IdealWifiManager::DoGetRtsMode (WifiRemoteStation *st)
 {
+  IdealWifiRemoteStation *station = (IdealWifiRemoteStation *)st;
   // We search within the Basic rate set the mode with the highest 
   // snr threshold possible which is smaller than m_lastSnr to 
   // ensure correct packet delivery.
   double maxThreshold = 0.0;
-  WifiMode maxMode = m_manager->GetDefaultMode ();
-  for (uint32_t i = 0; i < m_manager->GetNBasicModes (); i++)
+  WifiMode maxMode = GetDefaultMode ();
+  for (uint32_t i = 0; i < GetNBasicModes (); i++)
     {
-      WifiMode mode = m_manager->GetBasicMode (i);
-      double threshold = m_manager->GetSnrThreshold (mode);
+      WifiMode mode = GetBasicMode (i);
+      double threshold = GetSnrThreshold (mode);
       if (threshold > maxThreshold && 
-          threshold < m_lastSnr)
+          threshold < station->m_lastSnr)
         {
           maxThreshold = threshold;
           maxMode = mode;
@@ -160,10 +169,11 @@
     }
   return maxMode;
 }
-Ptr<WifiRemoteStationManager>
-IdealWifiRemoteStation::GetManager (void) const
+
+bool 
+IdealWifiManager::IsLowLatency (void) const
 {
-  return m_manager;
+  return true;
 }
 
 } // namespace ns3
--- a/src/devices/wifi/ideal-wifi-manager.h	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/ideal-wifi-manager.h	Wed Jan 06 16:26:07 2010 +0100
@@ -17,8 +17,8 @@
  *
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
-#ifndef IDEAL_MAC_STATIONS_H
-#define IDEAL_MAC_STATIONS_H
+#ifndef IDEAL_WIFI_MANAGER_H
+#define IDEAL_WIFI_MANAGER_H
 
 #include <stdint.h>
 #include <vector>
@@ -50,12 +50,27 @@
 
   virtual void SetupPhy (Ptr<WifiPhy> phy);
 
+private:
+  // overriden from base class
+  virtual class WifiRemoteStation *DoCreateStation (void) const;
+  virtual void DoReportRxOk (WifiRemoteStation *station, 
+                             double rxSnr, WifiMode txMode);
+  virtual void DoReportRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportDataFailed (WifiRemoteStation *station);
+  virtual void DoReportRtsOk (WifiRemoteStation *station,
+                              double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void DoReportDataOk (WifiRemoteStation *station,
+                               double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual void DoReportFinalRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportFinalDataFailed (WifiRemoteStation *station);
+  virtual WifiMode DoGetDataMode (WifiRemoteStation *station, uint32_t size);
+  virtual WifiMode DoGetRtsMode (WifiRemoteStation *station);
+  virtual bool IsLowLatency (void) const;
+
   // return the min snr needed to successfully transmit
   // data with this mode at the specified ber.
   double GetSnrThreshold (WifiMode mode) const;
   void AddModeSnrThreshold (WifiMode mode, double ber);
-private:
-  virtual class WifiRemoteStation *CreateStation (void);
 
   typedef std::vector<std::pair<double,WifiMode> > Thresholds;
 
@@ -65,31 +80,6 @@
   double m_maxSnr;
 };
 
-class IdealWifiRemoteStation : public WifiRemoteStation
-{
-public:
-  IdealWifiRemoteStation (Ptr<IdealWifiManager> stations);
-
-  virtual ~IdealWifiRemoteStation ();
-
-protected:
-  virtual void DoReportRxOk (double rxSnr, WifiMode txMode);
-  virtual void DoReportRtsFailed (void);
-  virtual void DoReportDataFailed (void);
-  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
-  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
-  virtual void DoReportFinalRtsFailed (void);
-  virtual void DoReportFinalDataFailed (void);
-
-private:
-  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
-  virtual WifiMode DoGetDataMode (uint32_t size);
-  virtual WifiMode DoGetRtsMode (void);
-
-  Ptr<IdealWifiManager> m_manager;
-  double m_lastSnr;
-};
-
 } // namespace ns3
 
-#endif /* MAC_STA_H */
+#endif /* IDEAL_WIFI_MANAGER_H */
--- a/src/devices/wifi/mac-low.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/mac-low.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -24,6 +24,7 @@
 #include "ns3/tag.h"
 #include "ns3/log.h"
 #include "ns3/node.h"
+#include "ns3/double.h"
 
 #include "mac-low.h"
 #include "wifi-phy.h"
@@ -575,8 +576,8 @@
         {
           NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
           NS_ASSERT (m_sendCtsEvent.IsExpired ());
-          WifiRemoteStation *station = GetStation (hdr.GetAddr2 ());
-          station->ReportRxOk (rxSnr, txMode);
+          m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr, 
+                                        rxSnr, txMode);
           m_sendCtsEvent = Simulator::Schedule (GetSifs (),
                                                 &MacLow::SendCtsAfterRts, this,
                                                 hdr.GetAddr2 (), 
@@ -597,9 +598,10 @@
       NS_LOG_DEBUG ("receive cts from="<<m_currentHdr.GetAddr1 ());
       SnrTag tag;
       packet->RemovePacketTag (tag);
-      WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-      station->ReportRxOk (rxSnr, txMode);
-      station->ReportRtsOk (rxSnr, txMode, tag.Get ());
+      m_stationManager->ReportRxOk (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                    rxSnr, txMode);
+      m_stationManager->ReportRtsOk (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                     rxSnr, txMode, tag.Get ());
       
       m_ctsTimeoutEvent.Cancel ();
       NotifyCtsTimeoutResetNow ();
@@ -621,9 +623,10 @@
       NS_LOG_DEBUG ("receive ack from="<<m_currentHdr.GetAddr1 ());
       SnrTag tag;
       packet->RemovePacketTag (tag);
-      WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-      station->ReportRxOk (rxSnr, txMode);
-      station->ReportDataOk (rxSnr, txMode, tag.Get ());
+      m_stationManager->ReportRxOk (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                    rxSnr, txMode);
+      m_stationManager->ReportDataOk (m_currentHdr.GetAddr1 (), &m_currentHdr,
+                                      rxSnr, txMode, tag.Get ());
       bool gotAck = false;
       if (m_txParams.MustWaitNormalAck () &&
           m_normalAckTimeoutEvent.IsRunning ()) 
@@ -655,8 +658,8 @@
     } 
   else if (hdr.GetAddr1 () == m_self) 
     {
-      WifiRemoteStation *station = GetStation (hdr.GetAddr2 ());
-      station->ReportRxOk (rxSnr, txMode);
+      m_stationManager->ReportRxOk (hdr.GetAddr2 (), &hdr,
+                                    rxSnr, txMode);
       
       if (hdr.IsQosData () && hdr.IsQosNoAck ()) 
         {
@@ -743,7 +746,7 @@
 MacLow::GetRtsTxMode (Ptr<const Packet> packet, const WifiMacHeader *hdr) const
 {
   Mac48Address to = hdr->GetAddr1 ();
-  return GetStation (to)->GetRtsMode (packet);
+  return m_stationManager->GetRtsMode (to, hdr, packet);
 }
 WifiMode
 MacLow::GetDataTxMode (Ptr<const Packet> packet, const WifiMacHeader *hdr) const
@@ -751,18 +754,18 @@
   Mac48Address to = hdr->GetAddr1 ();
   WifiMacTrailer fcs;
   uint32_t size =  packet->GetSize () + hdr->GetSize () + fcs.GetSerializedSize ();
-  return GetStation (to)->GetDataMode (packet, size);
+  return m_stationManager->GetDataMode (to, hdr, packet, size);
 }
 
 WifiMode
 MacLow::GetCtsTxModeForRts (Mac48Address to, WifiMode rtsTxMode) const
 {
-  return GetStation (to)->GetCtsMode (rtsTxMode);
+  return m_stationManager->GetCtsMode (to, rtsTxMode);
 }
 WifiMode
 MacLow::GetAckTxModeForData (Mac48Address to, WifiMode dataTxMode) const
 {
-  return GetStation (to)->GetAckMode (dataTxMode);
+  return m_stationManager->GetAckMode (to, dataTxMode);
 }
 
 
@@ -937,8 +940,7 @@
   // XXX: should check that there was no rx start before now.
   // we should restart a new cts timeout now until the expected
   // end of rx if there was a rx start before now.
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  station->ReportRtsFailed ();
+  m_stationManager->ReportRtsFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
   m_currentPacket = 0;
   MacLowTransmissionListener *listener = m_listener;
   m_listener = 0;
@@ -952,8 +954,7 @@
   // XXX: should check that there was no rx start before now.
   // we should restart a new ack timeout now until the expected
   // end of rx if there was a rx start before now.
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  station->ReportDataFailed ();
+  m_stationManager->ReportDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
   MacLowTransmissionListener *listener = m_listener;
   m_listener = 0;
   listener->MissedAck ();
@@ -962,8 +963,7 @@
 MacLow::FastAckTimeout (void)
 {
   NS_LOG_FUNCTION (this);
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  station->ReportDataFailed ();
+  m_stationManager->ReportDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
   MacLowTransmissionListener *listener = m_listener;
   m_listener = 0;
   if (m_phy->IsStateIdle ()) 
@@ -980,8 +980,7 @@
 MacLow::SuperFastAckTimeout ()
 {
   NS_LOG_FUNCTION (this);
-  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
-  station->ReportDataFailed ();
+  m_stationManager->ReportDataFailed (m_currentHdr.GetAddr1 (), &m_currentHdr);
   MacLowTransmissionListener *listener = m_listener;
   m_listener = 0;
   if (m_phy->IsStateIdle ()) 
@@ -1138,12 +1137,6 @@
     }
 }
 
-WifiRemoteStation *
-MacLow::GetStation (Mac48Address ad) const
-{
-  return m_stationManager->Lookup (ad);
-}
-
 void
 MacLow::SendCtsAfterRts (Mac48Address source, Time duration, WifiMode rtsTxMode, double rtsSnr)
 {
--- a/src/devices/wifi/mac-low.h	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/mac-low.h	Wed Jan 06 16:26:07 2010 +0100
@@ -371,7 +371,6 @@
   uint32_t GetCtsSize (void) const;
   uint32_t GetSize (Ptr<const Packet> packet, const WifiMacHeader *hdr) const;
   Time NowUs (void) const;
-  WifiRemoteStation *GetStation (Mac48Address to) const;
   void ForwardDown (Ptr<const Packet> packet, const WifiMacHeader *hdr, 
                     WifiMode txMode);
   Time CalculateOverallTxTime (Ptr<const Packet> packet,
--- a/src/devices/wifi/minstrel-wifi-manager.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/minstrel-wifi-manager.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -28,8 +28,6 @@
  * http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/minstrel
  */
 
-
-
 #include "minstrel-wifi-manager.h"
 #include "wifi-phy.h"
 #include "ns3/random-variable.h"
@@ -46,6 +44,83 @@
 
 namespace ns3 {
 
+/**
+ * A struct to contain all information related to a data rate 
+ */
+struct RateInfo
+{
+  /**
+   * Perfect transmission time calculation, or frame calculation
+   * Given a bit rate and a packet length n bytes 
+   */
+  Time perfectTxTime;		
+  
+  
+  uint32_t retryCount;  ///< retry limit
+  uint32_t adjustedRetryCount;  ///< adjust the retry limit for this rate
+  uint32_t numRateAttempt;  ///< how many number of attempts so far
+    uint32_t numRateSuccess;  ///< number of successful pkts 
+  uint32_t prob;  ///< (# pkts success )/(# total pkts)
+
+  /**
+   * EWMA calculation
+   * ewma_prob =[prob *(100 - ewma_level) + (ewma_prob_old * ewma_level)]/100 
+   */
+  uint32_t ewmaProb;
+  
+  uint32_t prevNumRateAttempt;  ///< from last rate
+  uint32_t prevNumRateSuccess;  ///< from last rate
+  uint64_t successHist;  ///< aggregate of all successes
+  uint64_t attemptHist;  ///< aggregate of all attempts
+  uint32_t throughput;  ///< throughput of a rate
+};
+  
+/**
+ * Data structure for a Minstrel Rate table 
+ * A vector of a struct RateInfo 
+ */
+typedef std::vector<struct RateInfo> MinstrelRate;
+
+/**
+ * Data structure for a Sample Rate table
+ * A vector of a vector uint32_t 
+ */
+typedef std::vector<std::vector<uint32_t> > SampleRate;
+
+struct MinstrelWifiRemoteStation : public WifiRemoteStation
+{
+  Time m_nextStatsUpdate;  ///< 10 times every second
+  MinstrelRate m_minstrelTable;  ///< minstrel table	
+  SampleRate m_sampleTable;  ///< sample table
+
+  /**
+   * To keep track of the current position in the our random sample table
+   * going row by row from 1st column until the 10th column(Minstrel defines 10)
+   * then we wrap back to the row 1 col 1.
+   * note: there are many other ways to do this.
+   */
+  uint32_t m_col, m_index;							
+  uint32_t m_maxTpRate;  ///< the current throughput rate 
+  uint32_t m_maxTpRate2;  ///< second highest throughput rate
+  uint32_t m_maxProbRate;  ///< rate with highest prob of success
+
+  int m_packetCount;  ///< total number of packets as of now
+  int m_sampleCount;  ///< how many packets we have sample so far
+
+  bool m_isSampling;  ///< a flag to indicate we are currently sampling
+  uint32_t m_sampleRate;  ///< current sample rate
+  bool 	m_sampleRateSlower;  ///< a flag to indicate sample rate is slower
+  uint32_t m_currentRate;  ///< current rate we are using
+
+  uint32_t m_shortRetry;  ///< short retries such as control packts
+  uint32_t m_longRetry;  ///< long retries such as data packets
+  uint32_t m_retry;  ///< total retries short + long
+  uint32_t m_err;  ///< retry errors
+  uint32_t m_txrate;  ///< current transmit rate
+
+  bool m_initialized;  ///< for initializing tables
+};
+
 NS_OBJECT_ENSURE_REGISTERED (MinstrelWifiManager);
 
 TypeId
@@ -106,12 +181,6 @@
   WifiRemoteStationManager::SetupPhy (phy);
 }
 
-WifiRemoteStation *
-MinstrelWifiManager::CreateStation (void)
-{
-  return new MinstrelWifiRemoteStation (this);
-}
-
 Time
 MinstrelWifiManager::GetCalcTxTime (WifiMode mode) const
 {
@@ -130,113 +199,139 @@
 void
 MinstrelWifiManager::AddCalcTxTime (WifiMode mode, Time t)
 {
-  m_calcTxTime.push_back (std::make_pair (t, mode));
+   m_calcTxTime.push_back (std::make_pair (t, mode));
 }
 
-MinstrelWifiRemoteStation::MinstrelWifiRemoteStation (Ptr<MinstrelWifiManager> stations)
-  :m_stations (stations),
-  m_nextStatsUpdate (Simulator::Now () + stations->m_updateStats),
-  m_col (0), 
-  m_index (0), 
-  m_maxTpRate (0), 
-  m_maxTpRate2 (0), 
-  m_maxProbRate (0),
-  m_packetCount (0), 
-  m_sampleCount (0), 
-  m_isSampling (false), 
-  m_sampleRate (0), 
-  m_sampleRateSlower (false),
-  m_currentRate (0),
-  m_shortRetry (0),
-  m_longRetry (0),
-  m_retry (0),
-  m_err (0),
-  m_txrate (0),
-  m_initialized (false)
-{}
+WifiRemoteStation *
+MinstrelWifiManager::DoCreateStation (void) const
+{
+  MinstrelWifiRemoteStation *station = new MinstrelWifiRemoteStation ();
 
-MinstrelWifiRemoteStation::~MinstrelWifiRemoteStation ()
-{}
+  station->m_nextStatsUpdate = Simulator::Now () + m_updateStats;
+  station->m_col = 0;
+  station->m_index = 0; 
+  station->m_maxTpRate = 0; 
+  station->m_maxTpRate2 = 0; 
+  station->m_maxProbRate = 0;
+  station->m_packetCount = 0; 
+  station->m_sampleCount = 0; 
+  station->m_isSampling = false; 
+  station->m_sampleRate = 0;
+  station->m_sampleRateSlower = false;
+  station->m_currentRate = 0;
+  station->m_shortRetry = 0;
+  station->m_longRetry = 0;
+  station->m_retry = 0;
+  station->m_err = 0;
+  station->m_txrate = 0;
+  station->m_initialized = false;
+
+  return station;
+}
 
 void 
-MinstrelWifiRemoteStation::CheckInit(void)
+MinstrelWifiManager::CheckInit(MinstrelWifiRemoteStation *station)
 {
-  if (!m_initialized)
+  if (!station->m_initialized)
     {
-      m_minstrelTable  =  MinstrelRate(GetNSupportedModes ());
-      m_sampleTable = SampleRate(GetNSupportedModes (), std::vector<uint32_t> (m_stations->m_sampleCol));
-      InitSampleTable ();
-      RateInit ();
-      m_initialized = true;
+      // Note: we appear to be doing late initialization of the table 
+      // to make sure that the set of supported rates has been initialized
+      // before we perform our own initialization.
+      station->m_minstrelTable = MinstrelRate(GetNSupported (station));
+      station->m_sampleTable = SampleRate(GetNSupported (station), std::vector<uint32_t> (m_sampleCol));
+      InitSampleTable (station);
+      RateInit (station);
+      station->m_initialized = true;
     }
 }
 
 void
-MinstrelWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
+MinstrelWifiManager::DoReportRxOk (WifiRemoteStation *st,
+                                   double rxSnr, WifiMode txMode)
 {
-  NS_LOG_DEBUG("DoReportRxOk m_txrate=" << m_txrate);
+  MinstrelWifiRemoteStation *station = (MinstrelWifiRemoteStation *)st;
+  NS_LOG_DEBUG("DoReportRxOk m_txrate=" << station->m_txrate);
 }
 
 void
-MinstrelWifiRemoteStation::DoReportRtsFailed (void)
+MinstrelWifiManager::DoReportRtsFailed (WifiRemoteStation *st)
 {
-  NS_LOG_DEBUG("DoReportRtsFailed m_txrate=" << m_txrate);
+  MinstrelWifiRemoteStation *station = (MinstrelWifiRemoteStation *)st;
+  NS_LOG_DEBUG("DoReportRtsFailed m_txrate=" << station->m_txrate);
 
-  m_shortRetry++;
+  station->m_shortRetry++;
 }
 
 void
-MinstrelWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
+MinstrelWifiManager::DoReportRtsOk (WifiRemoteStation *st, double ctsSnr, WifiMode ctsMode, double rtsSnr)
 {
-  NS_LOG_DEBUG ("self="<<this<<" rts ok");
+  NS_LOG_DEBUG ("self="<<st<<" rts ok");
+}
+
+void
+MinstrelWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *st)
+{
+  MinstrelWifiRemoteStation *station = (MinstrelWifiRemoteStation *)st;
+  UpdateRetry (station);
+  station->m_err++;
 }
 
 void
-MinstrelWifiRemoteStation::DoReportFinalRtsFailed (void)
+MinstrelWifiManager::DoReportDataFailed (WifiRemoteStation *st)
 {
-  UpdateRetry ();
-  m_err++;
-}
+  MinstrelWifiRemoteStation *station = (MinstrelWifiRemoteStation *)st;
+  /**
+   *
+   * Retry Chain table is implemented here
+   *
+   * Try |         LOOKAROUND RATE              | NORMAL RATE
+   *     | random < best    | random > best     |
+   * --------------------------------------------------------------
+   *  1  | Best throughput  | Random rate       | Best throughput
+   *  2  | Random rate      | Best throughput   | Next best throughput
+   *  3  | Best probability | Best probability  | Best probability
+   *  4  | Lowest Baserate  | Lowest baserate   | Lowest baserate
+   *
+   * Note: For clarity, multiple blocks of if's and else's are used
+   * After a failing 7 times, DoReportFinalDataFailed will be called
+   */
 
-void
-MinstrelWifiRemoteStation::DoReportDataFailed (void)
-{
-  CheckInit();
+  CheckInit(station);
 
-  m_longRetry++;
+  station->m_longRetry++;
 
-  NS_LOG_DEBUG ("DoReportDataFailed " << this << "\t rate " << m_txrate << "\tlongRetry \t" << m_longRetry);
+  NS_LOG_DEBUG ("DoReportDataFailed " << station << "\t rate " << station->m_txrate << "\tlongRetry \t" << station->m_longRetry);
 
   /// for normal rate, we're not currently sampling random rates
-  if (!m_isSampling)
+  if (!station->m_isSampling)
     {
       /// use best throughput rate
-      if( m_longRetry < m_minstrelTable[m_txrate].adjustedRetryCount)
+      if (station->m_longRetry < station->m_minstrelTable[station->m_txrate].adjustedRetryCount)
         {
           ;  ///<  there's still a few retries left
         }
 
       /// use second best throughput rate
-      else if (m_longRetry <= (m_minstrelTable[m_txrate].adjustedRetryCount +  
-               m_minstrelTable[m_maxTpRate].adjustedRetryCount))
+      else if (station->m_longRetry <= (station->m_minstrelTable[station->m_txrate].adjustedRetryCount +  
+                                        station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
         {
-          m_txrate = m_maxTpRate2;
+          station->m_txrate = station->m_maxTpRate2;
         }
 
       /// use best probability rate
-      else if (m_longRetry <= (m_minstrelTable[m_txrate].adjustedRetryCount +  
-               m_minstrelTable[m_maxTpRate2].adjustedRetryCount + 
-               m_minstrelTable[m_maxTpRate].adjustedRetryCount))
+      else if (station->m_longRetry <= (station->m_minstrelTable[station->m_txrate].adjustedRetryCount +  
+                                        station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount + 
+                                        station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
         {
-          m_txrate = m_maxProbRate;
+          station->m_txrate = station->m_maxProbRate;
         }
 
       /// use lowest base rate	
-      else if (m_longRetry > (m_minstrelTable[m_txrate].adjustedRetryCount +  
-               m_minstrelTable[m_maxTpRate2].adjustedRetryCount + 
-               m_minstrelTable[m_maxTpRate].adjustedRetryCount))
+      else if (station->m_longRetry > (station->m_minstrelTable[station->m_txrate].adjustedRetryCount +  
+                              station->m_minstrelTable[station->m_maxTpRate2].adjustedRetryCount + 
+                              station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
         {
-          m_txrate = 0;
+          station->m_txrate = 0;
         }
     }
 
@@ -244,35 +339,35 @@
   else
     {
       /// current sampling rate is slower than the current best rate
-      if (m_sampleRateSlower)
+      if (station->m_sampleRateSlower)
         {
           /// use best throughput rate
-          if (m_longRetry < m_minstrelTable[m_txrate].adjustedRetryCount)
+          if (station->m_longRetry < station->m_minstrelTable[station->m_txrate].adjustedRetryCount)
             {
               ;	///<  there are a few retries left
             }
 
           ///	use random rate
-          else if (m_longRetry <= (m_minstrelTable[m_txrate].adjustedRetryCount + 
-                   m_minstrelTable[m_maxTpRate].adjustedRetryCount))
+          else if (station->m_longRetry <= (station->m_minstrelTable[station->m_txrate].adjustedRetryCount + 
+                                            station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
             {
-              m_txrate = m_sampleRate;
+              station->m_txrate = station->m_sampleRate;
             }
 
           /// use max probability rate
-          else if (m_longRetry <= (m_minstrelTable[m_txrate].adjustedRetryCount +  
-                   m_minstrelTable[m_sampleRate].adjustedRetryCount + 
-                   m_minstrelTable[m_maxTpRate].adjustedRetryCount ))
+          else if (station->m_longRetry <= (station->m_minstrelTable[station->m_txrate].adjustedRetryCount +  
+                                            station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount + 
+                                            station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount ))
             {
-              m_txrate = m_maxProbRate;
+              station->m_txrate = station->m_maxProbRate;
             }
 
           /// use lowest base rate
-          else if (m_longRetry > (m_minstrelTable[m_txrate].adjustedRetryCount +  
-                   m_minstrelTable[m_sampleRate].adjustedRetryCount + 
-                   m_minstrelTable[m_maxTpRate].adjustedRetryCount)) 
+          else if (station->m_longRetry > (station->m_minstrelTable[station->m_txrate].adjustedRetryCount +  
+                                           station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount + 
+                                           station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount))
             {
-              m_txrate = 0;
+              station->m_txrate = 0;
             }
         }
 
@@ -280,140 +375,146 @@
         else
           {
             /// use random rate
-            if (m_longRetry < m_minstrelTable[m_txrate].adjustedRetryCount)
+            if (station->m_longRetry < station->m_minstrelTable[station->m_txrate].adjustedRetryCount)
               {
                 ;  ///< keep using it
               }
 
             /// use the best rate
-            else if (m_longRetry <= m_minstrelTable[m_txrate].adjustedRetryCount + 
-                     m_minstrelTable[m_sampleRate].adjustedRetryCount)
+            else if (station->m_longRetry <= (station->m_minstrelTable[station->m_txrate].adjustedRetryCount + 
+                                              station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount))
               {
-                m_txrate = m_maxTpRate;
+                station->m_txrate = station->m_maxTpRate;
               }
 
             /// use the best probability rate
-            else if (m_longRetry <= m_minstrelTable[m_txrate].adjustedRetryCount + 
-                     m_minstrelTable[m_maxTpRate].adjustedRetryCount +  
-                     m_minstrelTable[m_sampleRate].adjustedRetryCount)
+            else if (station->m_longRetry <= (station->m_minstrelTable[station->m_txrate].adjustedRetryCount + 
+                                              station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +  
+                                              station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount))
               {
-                m_txrate = m_maxProbRate;
+                station->m_txrate = station->m_maxProbRate;
               }
 
             /// use the lowest base rate
-            else if (m_longRetry > m_minstrelTable[m_txrate].adjustedRetryCount + 
-                     m_minstrelTable[m_maxTpRate].adjustedRetryCount +  
-                     m_minstrelTable[m_sampleRate].adjustedRetryCount) 
+            else if (station->m_longRetry > (station->m_minstrelTable[station->m_txrate].adjustedRetryCount + 
+                                             station->m_minstrelTable[station->m_maxTpRate].adjustedRetryCount +  
+                                             station->m_minstrelTable[station->m_sampleRate].adjustedRetryCount))
               {
-                m_txrate = 0;
+                station->m_txrate = 0;
               }
           }
     }
 }
 
 void
-MinstrelWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+MinstrelWifiManager::DoReportDataOk (WifiRemoteStation *st,
+                                     double ackSnr, WifiMode ackMode, double dataSnr)
 {
-  m_isSampling = false;
-  m_sampleRateSlower=false;
+  MinstrelWifiRemoteStation *station = (MinstrelWifiRemoteStation *) st;
 
-  CheckInit ();
+  station->m_isSampling = false;
+  station->m_sampleRateSlower=false;
+
+  CheckInit (station);
 
-  m_minstrelTable[m_txrate].numRateSuccess++;
-  m_minstrelTable[m_txrate].numRateAttempt++;
+  station->m_minstrelTable[station->m_txrate].numRateSuccess++;
+  station->m_minstrelTable[station->m_txrate].numRateAttempt++;
 	
-  UpdateRetry ();
+  UpdateRetry (station);
 
-  m_minstrelTable[m_txrate].numRateAttempt += m_retry;
-  m_packetCount++;
+  station->m_minstrelTable[station->m_txrate].numRateAttempt += station->m_retry;
+  station->m_packetCount++;
 
-  if (GetNSupportedModes () >= 1)
+  if (GetNSupported (station) >= 1)
     {
-      m_txrate = FindRate ();
+      station->m_txrate = FindRate (station);
     }
 }
 
 void
-MinstrelWifiRemoteStation::DoReportFinalDataFailed (void)
+MinstrelWifiManager::DoReportFinalDataFailed (WifiRemoteStation *st)
 {
-  NS_LOG_DEBUG ("DoReportFinalDataFailed m_txrate=" << m_txrate);
+  MinstrelWifiRemoteStation *station = (MinstrelWifiRemoteStation *) st;
+  NS_LOG_DEBUG ("DoReportFinalDataFailed m_txrate=" << station->m_txrate);
 
-  m_isSampling = false;
-  m_sampleRateSlower=false;
+  station->m_isSampling = false;
+  station->m_sampleRateSlower=false;
 
-  UpdateRetry ();
+  UpdateRetry (station);
 
-  m_minstrelTable[m_txrate].numRateAttempt += m_retry;
-  m_err++;
+  station->m_minstrelTable[station->m_txrate].numRateAttempt += station->m_retry;
+  station->m_err++;
 
-  if (GetNSupportedModes () >= 1)
+  if (GetNSupported (station) >= 1)
     {
-      m_txrate = FindRate ();
+      station->m_txrate = FindRate (station);
     }
 }
 
 void
-MinstrelWifiRemoteStation::UpdateRetry (void)
+MinstrelWifiManager::UpdateRetry (MinstrelWifiRemoteStation *station)
 {
-  m_retry = m_shortRetry + m_longRetry;
-  m_shortRetry = 0;
-  m_longRetry = 0;
+  station->m_retry = station->m_shortRetry + station->m_longRetry;
+  station->m_shortRetry = 0;
+  station->m_longRetry = 0;
 }
 
-Ptr<WifiRemoteStationManager>
-MinstrelWifiRemoteStation::GetManager (void) const
+WifiMode
+MinstrelWifiManager::DoGetDataMode (WifiRemoteStation *st,
+                                    uint32_t size)
 {
-  return m_stations;
+  MinstrelWifiRemoteStation *station = (MinstrelWifiRemoteStation *) st;
+  if (!station->m_initialized)
+    {
+      CheckInit (station);
+
+      /// start the rate at half way
+      station->m_txrate = GetNSupported (station) / 2;
+    }
+  UpdateStats (station);
+  return GetSupported (station, station->m_txrate);
 }
 
 WifiMode
-MinstrelWifiRemoteStation::DoGetDataMode (uint32_t size)
+MinstrelWifiManager::DoGetRtsMode (WifiRemoteStation *st)
 {
-  if (!m_initialized)
-    {
-      CheckInit ();
+  MinstrelWifiRemoteStation *station = (MinstrelWifiRemoteStation *) st;
+  NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << station->m_txrate);
 
-      /// start the rate at half way
-      m_txrate = GetNSupportedModes () / 2;
-    }
-  UpdateStats ();
-  return GetSupportedMode (m_txrate);
+  return GetSupported (station, 0);
 }
 
-WifiMode
-MinstrelWifiRemoteStation::DoGetRtsMode (void)
+bool 
+MinstrelWifiManager::IsLowLatency (void) const
 {
-  NS_LOG_DEBUG ("DoGetRtsMode m_txrate=" << m_txrate);
-
-  return GetSupportedMode (0);
+  return false;
 }
-
 uint32_t 
-MinstrelWifiRemoteStation::GetNextSample ()
+MinstrelWifiManager::GetNextSample (MinstrelWifiRemoteStation *station)
 {
   uint32_t bitrate;
-  bitrate = m_sampleTable[m_index][m_col];
-  m_index++;
+  bitrate = station->m_sampleTable[station->m_index][station->m_col];
+  station->m_index++;
 
   /// bookeeping for m_index and m_col variables
-  if (m_index > (GetNSupportedModes () -2)) 
+  if (station->m_index > (GetNSupported (station) - 2)) 
     {
-      m_index =0;
-      m_col++;
-      if (m_col >= m_stations->m_sampleCol)
+      station->m_index =0;
+      station->m_col++;
+      if (station->m_col >= m_sampleCol)
         {
-          m_col = 0;
+          station->m_col = 0;
         }
     }
   return bitrate;
 }
 
 uint32_t
-MinstrelWifiRemoteStation::FindRate ()
+MinstrelWifiManager::FindRate (MinstrelWifiRemoteStation *station)
 {
-  NS_LOG_DEBUG ("FindRate " << "packet=" << m_packetCount );
+  NS_LOG_DEBUG ("FindRate " << "packet=" << station->m_packetCount );
 
-  if ((m_sampleCount + m_packetCount) == 0)
+  if ((station->m_sampleCount + station->m_packetCount) == 0)
     {
       return 0;
     }
@@ -429,55 +530,56 @@
    * note: do it randomly by flipping a coin instead sampling 
    * all at once until it reaches the look around rate
    */
-  if ( (((100* m_sampleCount) / (m_sampleCount + m_packetCount )) < m_stations->m_lookAroundRate) &&
-     ((int)coinFlip.GetValue ()) % 2 == 1 )
+  if ( (((100* station->m_sampleCount) / (station->m_sampleCount + station->m_packetCount )) < m_lookAroundRate) &&
+       ((int)coinFlip.GetValue ()) % 2 == 1 )
     {
 
       /// now go through the table and find an index rate
-      idx = GetNextSample();
+      idx = GetNextSample(station);
 			
 			
       /**
        * This if condition is used to make sure that we don't need to use
        * the sample rate it is the same as our current rate
        */
-      if (idx != m_maxTpRate && idx != m_txrate) 
+      if (idx != station->m_maxTpRate && idx != station->m_txrate) 
         {
 		
           /// start sample count
-          m_sampleCount++;
+          station->m_sampleCount++;
 
           /// set flag that we are currently sampling
-          m_isSampling = true;
+          station->m_isSampling = true;
 
           /// bookeeping for resetting stuff
-          if (m_packetCount >= 10000) 
+          if (station->m_packetCount >= 10000) 
             {
-              m_sampleCount = 0;
-              m_packetCount = 0;
+              station->m_sampleCount = 0;
+              station->m_packetCount = 0;
             }
 
           /// error check
-          if (idx >= GetNSupportedModes	() || idx < 0 )
+          if (idx >= GetNSupported (station) || idx < 0)
             {
               NS_LOG_DEBUG ("ALERT!!! ERROR");
             }
 
           /// set the rate that we're currently sampling
-          m_sampleRate = idx;
+          station->m_sampleRate = idx;
 
-          if (m_sampleRate == m_maxTpRate)
+          if (station->m_sampleRate == station->m_maxTpRate)
             {
-              m_sampleRate = m_maxTpRate2;
+              station->m_sampleRate = station->m_maxTpRate2;
             }
 
           /// is this rate slower than the current best rate
-          m_sampleRateSlower = (m_minstrelTable[idx].perfectTxTime > m_minstrelTable[m_maxTpRate].perfectTxTime);
+          station->m_sampleRateSlower = 
+            (station->m_minstrelTable[idx].perfectTxTime > station->m_minstrelTable[station->m_maxTpRate].perfectTxTime);
 
           /// using the best rate instead
-          if (m_sampleRateSlower)
+          if (station->m_sampleRateSlower)
             {
-              idx =  m_maxTpRate;
+              idx =  station->m_maxTpRate;
             }
         }
 			
@@ -486,7 +588,7 @@
   ///	continue using the best rate
   else
     {
-      idx = m_maxTpRate; 
+      idx = station->m_maxTpRate; 
     }
 
 
@@ -496,25 +598,25 @@
 }
 
 void
-MinstrelWifiRemoteStation::UpdateStats ()
+MinstrelWifiManager::UpdateStats (MinstrelWifiRemoteStation *station)
 {
-  if (Simulator::Now () <  m_nextStatsUpdate)
+  if (Simulator::Now () <  station->m_nextStatsUpdate)
     {
       return;
     }
 
   NS_LOG_DEBUG ("Updating stats="<<this);
 
-  m_nextStatsUpdate = Simulator::Now () + m_stations->m_updateStats;
+  station->m_nextStatsUpdate = Simulator::Now () + m_updateStats;
 
   Time txTime;
   uint32_t tempProb;
 
-  for (uint32_t i =0; i < GetNSupportedModes (); i++)
+  for (uint32_t i =0; i < GetNSupported (station); i++)
     {        
 
       /// calculate the perfect tx time for this rate
-      txTime = m_minstrelTable[i].perfectTxTime;       
+      txTime = station->m_minstrelTable[i].perfectTxTime;       
 
       /// just for initialization
       if (txTime.GetMicroSeconds () == 0)
@@ -522,60 +624,62 @@
           txTime = Seconds (1);
         }
 
-      NS_LOG_DEBUG ("m_txrate=" << m_txrate << "\t attempt=" << m_minstrelTable[i].numRateAttempt << "\t success=" << m_minstrelTable[i].numRateSuccess);
+      NS_LOG_DEBUG ("m_txrate=" << station->m_txrate << 
+                    "\t attempt=" << station->m_minstrelTable[i].numRateAttempt << 
+                    "\t success=" << station->m_minstrelTable[i].numRateSuccess);
 
       /// if we've attempted something
-      if (m_minstrelTable[i].numRateAttempt)
+      if (station->m_minstrelTable[i].numRateAttempt)
         {
           /**
            * calculate the probability of success
            * assume probability scales from 0 to 18000
            */
-          tempProb = (m_minstrelTable[i].numRateSuccess * 18000) / m_minstrelTable[i].numRateAttempt;
+          tempProb = (station->m_minstrelTable[i].numRateSuccess * 18000) / station->m_minstrelTable[i].numRateAttempt;
 
           /// bookeeping
-          m_minstrelTable[i].successHist += m_minstrelTable[i].numRateSuccess;
-          m_minstrelTable[i].attemptHist += m_minstrelTable[i].numRateAttempt;
-          m_minstrelTable[i].prob = tempProb;
+          station->m_minstrelTable[i].successHist += station->m_minstrelTable[i].numRateSuccess;
+          station->m_minstrelTable[i].attemptHist += station->m_minstrelTable[i].numRateAttempt;
+          station->m_minstrelTable[i].prob = tempProb;
 
           /// ewma probability (cast for gcc 3.4 compatibility)
-          tempProb = static_cast<uint32_t>(((tempProb * (100 - m_stations->m_ewmaLevel)) + (m_minstrelTable[i].ewmaProb * m_stations->m_ewmaLevel) )/100);
+          tempProb = static_cast<uint32_t>(((tempProb * (100 - m_ewmaLevel)) + (station->m_minstrelTable[i].ewmaProb * m_ewmaLevel) )/100);
 
-          m_minstrelTable[i].ewmaProb = tempProb;
+          station->m_minstrelTable[i].ewmaProb = tempProb;
 
           /// calculating throughput
-          m_minstrelTable[i].throughput = tempProb * (1000000 / txTime.GetMicroSeconds());
+          station->m_minstrelTable[i].throughput = tempProb * (1000000 / txTime.GetMicroSeconds());
 
         }
 
       /// bookeeping
-      m_minstrelTable[i].prevNumRateAttempt= m_minstrelTable[i].numRateAttempt;
-      m_minstrelTable[i].prevNumRateSuccess = m_minstrelTable[i].numRateSuccess;
-      m_minstrelTable[i].numRateSuccess = 0;
-      m_minstrelTable[i].numRateAttempt = 0;
+      station->m_minstrelTable[i].prevNumRateAttempt = station->m_minstrelTable[i].numRateAttempt;
+      station->m_minstrelTable[i].prevNumRateSuccess = station->m_minstrelTable[i].numRateSuccess;
+      station->m_minstrelTable[i].numRateSuccess = 0;
+      station->m_minstrelTable[i].numRateAttempt = 0;
 
       /// Sample less often below 10% and  above 95% of success
-      if ((m_minstrelTable[i].ewmaProb > 17100) || (m_minstrelTable[i].ewmaProb < 1800)) 
+      if ((station->m_minstrelTable[i].ewmaProb > 17100) || (station->m_minstrelTable[i].ewmaProb < 1800)) 
         {
           /**
            * retry count denotes the number of retries permitted for each rate
            * # retry_count/2
            */
-          m_minstrelTable[i].adjustedRetryCount = m_minstrelTable[i].retryCount >> 1;
-          if (m_minstrelTable[i].adjustedRetryCount > 2)
+          station->m_minstrelTable[i].adjustedRetryCount = station->m_minstrelTable[i].retryCount >> 1;
+          if (station->m_minstrelTable[i].adjustedRetryCount > 2)
             {
-              m_minstrelTable[i].adjustedRetryCount = 2 ;
+              station->m_minstrelTable[i].adjustedRetryCount = 2 ;
             }
         }
       else
         {
-          m_minstrelTable[i].adjustedRetryCount = m_minstrelTable[i].retryCount;
+          station->m_minstrelTable[i].adjustedRetryCount = station->m_minstrelTable[i].retryCount;
         }
 
       /// if it's 0 allow one retry limit
-      if (m_minstrelTable[i].adjustedRetryCount == 0)
+      if (station->m_minstrelTable[i].adjustedRetryCount == 0)
         {
-          m_minstrelTable[i].adjustedRetryCount = 1;
+          station->m_minstrelTable[i].adjustedRetryCount = 1;
         }
     }
 
@@ -583,85 +687,86 @@
   uint32_t max_prob = 0, index_max_prob =0, max_tp =0, index_max_tp=0, index_max_tp2=0;
 
   /// go find max throughput, second maximum throughput, high probability succ
-  for (uint32_t i =0; i < GetNSupportedModes (); i++) 
+  for (uint32_t i =0; i < GetNSupported (station); i++) 
     {
-      NS_LOG_DEBUG ("throughput" << m_minstrelTable[i].throughput << "\n ewma" << m_minstrelTable[i].ewmaProb);
+      NS_LOG_DEBUG ("throughput" << station->m_minstrelTable[i].throughput << 
+                    "\n ewma" << station->m_minstrelTable[i].ewmaProb);
 
-      if (max_tp < m_minstrelTable[i].throughput) 
+      if (max_tp < station->m_minstrelTable[i].throughput) 
         {
           index_max_tp = i;
-          max_tp = m_minstrelTable[i].throughput;
+          max_tp = station->m_minstrelTable[i].throughput;
         }
 
-      if (max_prob < m_minstrelTable[i].ewmaProb) 
+      if (max_prob < station->m_minstrelTable[i].ewmaProb) 
         {
           index_max_prob = i;
-          max_prob = m_minstrelTable[i].ewmaProb;
+          max_prob = station->m_minstrelTable[i].ewmaProb;
         }
     }
 
 
   max_tp = 0;
   /// find the second highest max
-  for (uint32_t i =0; i < GetNSupportedModes (); i++) 
+  for (uint32_t i =0; i < GetNSupported (station); i++) 
     {
-      if ((i != index_max_tp) && (max_tp < m_minstrelTable[i].throughput))
+      if ((i != index_max_tp) && (max_tp < station->m_minstrelTable[i].throughput))
         {
           index_max_tp2 = i;
-          max_tp = m_minstrelTable[i].throughput;
+          max_tp = station->m_minstrelTable[i].throughput;
         }
     }
 
-  m_maxTpRate = index_max_tp;
-  m_maxTpRate2 = index_max_tp2;
-  m_maxProbRate = index_max_prob;
-  m_currentRate = index_max_tp;
+  station->m_maxTpRate = index_max_tp;
+  station->m_maxTpRate2 = index_max_tp2;
+  station->m_maxProbRate = index_max_prob;
+  station->m_currentRate = index_max_tp;
 
-  if (index_max_tp > m_txrate)
+  if (index_max_tp > station->m_txrate)
     {
-      m_txrate= index_max_tp;
+      station->m_txrate = index_max_tp;
     }
 
   NS_LOG_DEBUG ("max tp="<< index_max_tp << "\nmax tp2="<< index_max_tp2<< "\nmax prob="<< index_max_prob);
 
   /// reset it
-  RateInit ();
+  RateInit (station);
 }
 
 void
-MinstrelWifiRemoteStation::RateInit ()
+MinstrelWifiManager::RateInit (MinstrelWifiRemoteStation *station)
 {
-  NS_LOG_DEBUG ("RateInit="<<this);
+  NS_LOG_DEBUG ("RateInit="<<station);
 
-  for (uint32_t i = 0; i < GetNSupportedModes (); i++)
+  for (uint32_t i = 0; i < GetNSupported (station); i++)
     {
-      m_minstrelTable[i].numRateAttempt = 0;
-      m_minstrelTable[i].numRateSuccess = 0;
-      m_minstrelTable[i].prob = 0;
-      m_minstrelTable[i].ewmaProb = 0;
-      m_minstrelTable[i].prevNumRateAttempt = 0;
-      m_minstrelTable[i].prevNumRateSuccess = 0;
-      m_minstrelTable[i].successHist = 0;
-      m_minstrelTable[i].attemptHist = 0;
-      m_minstrelTable[i].throughput = 0;
-      m_minstrelTable[i].perfectTxTime = m_stations->GetCalcTxTime (GetSupportedMode (i));
-      m_minstrelTable[i].retryCount =1;
-      m_minstrelTable[i].adjustedRetryCount =1;
+      station->m_minstrelTable[i].numRateAttempt = 0;
+      station->m_minstrelTable[i].numRateSuccess = 0;
+      station->m_minstrelTable[i].prob = 0;
+      station->m_minstrelTable[i].ewmaProb = 0;
+      station->m_minstrelTable[i].prevNumRateAttempt = 0;
+      station->m_minstrelTable[i].prevNumRateSuccess = 0;
+      station->m_minstrelTable[i].successHist = 0;
+      station->m_minstrelTable[i].attemptHist = 0;
+      station->m_minstrelTable[i].throughput = 0;
+      station->m_minstrelTable[i].perfectTxTime = GetCalcTxTime (GetSupported (station, i));
+      station->m_minstrelTable[i].retryCount = 1;
+      station->m_minstrelTable[i].adjustedRetryCount = 1;
     }
 }
 
 void
-MinstrelWifiRemoteStation::InitSampleTable ()
+MinstrelWifiManager::InitSampleTable (MinstrelWifiRemoteStation *station)
 {
   NS_LOG_DEBUG ("InitSampleTable="<<this);
 	
-  m_col = m_index = 0;
+  station->m_col = station->m_index = 0;
 
   /// for off-seting to make rates fall between 0 and numrates 
-  uint32_t numSampleRates= GetNSupportedModes () - 1;
+  uint32_t numSampleRates = GetNSupported (station);
 
   uint32_t newIndex;
-  for (uint32_t col = 0; col < m_stations->m_sampleCol; col++)
+  for (uint32_t col = 0; col < m_sampleCol; col++)
     {
       for (uint32_t i = 0; i < numSampleRates; i++ )
         {
@@ -674,40 +779,40 @@
           newIndex = (i + (uint32_t)uv.GetValue	()) % numSampleRates;	
 
           /// this loop is used for filling in other uninitilized places
-          while	(m_sampleTable[newIndex][col] != 0)
+          while	(station->m_sampleTable[newIndex][col] != 0)
             {
-              newIndex = (newIndex + 1)%GetNSupportedModes ();
+              newIndex = (newIndex + 1)%GetNSupported (station);
             }
-          m_sampleTable[newIndex][col] = i+1;
+          station->m_sampleTable[newIndex][col] = i+1;
 
         }
     }
 }
 
 void
-MinstrelWifiRemoteStation::PrintSampleTable ()
+MinstrelWifiManager::PrintSampleTable (MinstrelWifiRemoteStation *station)
 {
-  NS_LOG_DEBUG ("PrintSampleTable="<<this );
+  NS_LOG_DEBUG ("PrintSampleTable="<<station);
 
-  uint32_t numSampleRates= GetNSupportedModes ();
-  for (uint32_t i=0; i < numSampleRates; i++)
+  uint32_t numSampleRates = GetNSupported (station);
+  for (uint32_t i = 0; i < numSampleRates; i++)
     {
-      for (uint32_t j=0; j < m_stations->m_sampleCol; j++)
+      for (uint32_t j = 0; j < m_sampleCol; j++)
         {
-          std::cout << m_sampleTable[i][j] << "\t";
+          std::cout << station->m_sampleTable[i][j] << "\t";
         }
       std::cout << std::endl;
     }
 }
 	
 void
-MinstrelWifiRemoteStation::PrintTable ()
+MinstrelWifiManager::PrintTable (MinstrelWifiRemoteStation *station)
 {
-  NS_LOG_DEBUG ("PrintTable="<<this);
+  NS_LOG_DEBUG ("PrintTable="<<station);
 
-  for (uint32_t i=0; i < GetNSupportedModes (); i++)
+  for (uint32_t i=0; i < GetNSupported (station); i++)
     {
-      std::cout << "index(" << i << ") = " << m_minstrelTable[i].perfectTxTime<< "\n";
+      std::cout << "index(" << i << ") = " << station->m_minstrelTable[i].perfectTxTime<< "\n";
     }
 }
 
--- a/src/devices/wifi/minstrel-wifi-manager.h	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/minstrel-wifi-manager.h	Wed Jan 06 16:26:07 2010 +0100
@@ -28,8 +28,6 @@
 #include "ns3/nstime.h"
 #include <vector>
 
-
-
 /**
  * \author Duy Nguyen
  * \brief Implementation of Minstrel Rate Control Algorithm 
@@ -41,49 +39,7 @@
 
 namespace ns3 {
 
-
-/**
- * A struct to contain all information related to a data rate 
- */
-struct RateInfo{
-
-  /**
-   * Perfect transmission time calculation, or frame calculation
-   * Given a bit rate and a packet length n bytes 
-   */
-  Time perfectTxTime;		
-
-
-  uint32_t retryCount;  ///< retry limit
-  uint32_t adjustedRetryCount;  ///< adjust the retry limit for this rate
-  uint32_t numRateAttempt;  ///< how many number of attempts so far
-  uint32_t numRateSuccess;  ///< number of successful pkts 
-  uint32_t prob;  ///< (# pkts success )/(# total pkts)
-
-  /**
-   * EWMA calculation
-   * ewma_prob =[prob *(100 - ewma_level) + (ewma_prob_old * ewma_level)]/100 
-   */
-  uint32_t ewmaProb;
-
-  uint32_t prevNumRateAttempt;  ///< from last rate
-  uint32_t prevNumRateSuccess;  ///< from last rate
-  uint64_t successHist;  ///< aggregate of all successes
-  uint64_t attemptHist;  ///< aggregate of all attempts
-  uint32_t throughput;  ///< throughput of a rate
-};
-
-/**
- * Data structure for a Minstrel Rate table 
- * A vector of a struct RateInfo 
- */
-typedef std::vector<struct RateInfo> MinstrelRate;
-
-/**
- * Data structure for a Sample Rate table
- * A vector of a vector uint32_t 
- */
-typedef std::vector<std::vector<uint32_t> > SampleRate;
+class MinstrelWifiRemoteStation;
 
 
 class MinstrelWifiManager : public WifiRemoteStationManager
@@ -96,13 +52,53 @@
 
   virtual void SetupPhy (Ptr<WifiPhy> phy);
 
+private:
+  // overriden from base class
+  virtual class WifiRemoteStation *DoCreateStation (void) const;
+  virtual void DoReportRxOk (WifiRemoteStation *station, 
+                             double rxSnr, WifiMode txMode);
+  virtual void DoReportRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportDataFailed (WifiRemoteStation *station);
+  virtual void DoReportRtsOk (WifiRemoteStation *station,
+                              double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void DoReportDataOk (WifiRemoteStation *station,
+                               double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual void DoReportFinalRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportFinalDataFailed (WifiRemoteStation *station);
+  virtual WifiMode DoGetDataMode (WifiRemoteStation *station, uint32_t size);
+  virtual WifiMode DoGetRtsMode (WifiRemoteStation *station);
+  virtual bool IsLowLatency (void) const;
+
   /// for estimating the TxTime of a packet with a given mode  
   Time GetCalcTxTime (WifiMode mode) const;
   void AddCalcTxTime (WifiMode mode, Time t);
 
-private:
-  friend class MinstrelWifiRemoteStation;
-  virtual class WifiRemoteStation *CreateStation (void);
+  /// update the number of retries and reset accordingly
+  void UpdateRetry (MinstrelWifiRemoteStation *station);
+
+  /// getting the next sample from Sample Table
+  uint32_t GetNextSample (MinstrelWifiRemoteStation *station);
+
+  /// find a rate to use from Minstrel Table
+  uint32_t FindRate (MinstrelWifiRemoteStation *station);
+
+  /// updating the Minstrel Table every 1/10 seconds
+  void UpdateStats (MinstrelWifiRemoteStation *station);
+
+  /// initialize Minstrel Table
+  void RateInit (MinstrelWifiRemoteStation *station);
+
+  /// initialize Sample Table
+  void InitSampleTable (MinstrelWifiRemoteStation *station);
+
+  /// printing Sample Table
+  void PrintSampleTable (MinstrelWifiRemoteStation *station);
+
+  /// printing Minstrel Table
+  void PrintTable (MinstrelWifiRemoteStation *station);
+
+  void CheckInit (MinstrelWifiRemoteStation *station);  ///< check for initializations
+
 
   typedef std::vector<std::pair<Time,WifiMode> > TxTime;
 
@@ -112,144 +108,9 @@
   double m_ewmaLevel;  ///< exponential weighted moving average
   uint32_t m_segmentSize;  ///< largest allowable segment size
   uint32_t m_sampleCol;  ///< number of sample columns
-  uint32_t m_pktLen;  ///< packet length used  for calculate mode TxTime
-  
+  uint32_t m_pktLen;  ///< packet length used  for calculate mode TxTime  
 };
 
-class MinstrelWifiRemoteStation : public WifiRemoteStation
-{
-public:
-  MinstrelWifiRemoteStation (Ptr<MinstrelWifiManager> stations);
- 
-  virtual ~MinstrelWifiRemoteStation ();
-
-protected:
-
-  /** 
-   * when packet is successfully received
-   * see wifi-remote-station-manager.h for more documentation
-   */
-  virtual void DoReportRxOk (double rxSnr, WifiMode txMode);
-
-  /// when RTS timeout expires
-  virtual void DoReportRtsFailed (void);
-
-
-  /**
-   *
-   * Retry Chain table is implemented here
-   *
-   * Try |         LOOKAROUND RATE              | NORMAL RATE
-   *     | random < best    | random > best     |
-   * --------------------------------------------------------------
-   *  1  | Best throughput  | Random rate       | Best throughput
-   *  2  | Random rate      | Best throughput   | Next best throughput
-   *  3  | Best probability | Best probability  | Best probability
-   *  4  | Lowest Baserate  | Lowest baserate   | Lowest baserate
-   *
-   * Note: For clarity, multiple blocks of if's and else's are used
-   * After a failing 7 times, DoReportFinalDataFailed will be called
-   */
-  virtual void DoReportDataFailed (void);
-
-  /// when receive a CTS, associated with an RTS
-  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
-
-  /// when an ACK, associated with a data pkt, is received
-  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
-
-  /// after calling ReportRtsFailed if NeedRtsRetransmission returns false
-  virtual void DoReportFinalRtsFailed (void);
-
-  /// after calling ReportDataFailed if NeedDataRetransmission returns false
-  virtual void DoReportFinalDataFailed (void);
-
-
-private:
-  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
-
-  /** 
-   * returns the transmission mode for sending this packet
-   * this function gets called when node is getting ready to send DATA
-   * see wifi-remote-station-manager.h for more documentation
-   */
-  virtual WifiMode DoGetDataMode (uint32_t size);
-
-  /// returns the transmission mode for sending RTS packet
-  virtual WifiMode DoGetRtsMode (void);
-
-  /// update the number of retries and reset accordingly
-  void UpdateRetry (void);
-
-  /// getting the next sample from Sample Table
-  uint32_t GetNextSample (void);
-
-  /// find a rate to use from Minstrel Table
-  uint32_t FindRate (void);
-
-  /// updating the Minstrel Table every 1/10 seconds
-  void UpdateStats (void);
-
-  /// initialize Minstrel Table
-  void RateInit (void);
-
-  /// initialize Sample Table
-  void InitSampleTable (void);
-
-  /// printing Sample Table
-  void PrintSampleTable (void);
-
-  /// printing Minstrel Table
-  void PrintTable (void);
-
-  /**
-   * \param packet lenghth 
-   * \param current WifiMode
-   * \returns calcuated transmit duration 
-   */
-  Time CalcRatePacket (uint32_t, WifiMode);
-
-  void CheckInit(void);  ///< check for initializations
-
-  Ptr<MinstrelWifiManager> m_stations;
-
-  Time m_nextStatsUpdate;  ///< 10 times every second
-
-  MinstrelRate m_minstrelTable;  ///< minstrel table	
-
-  SampleRate m_sampleTable;  ///< sample table
-
-  /**
-   * To keep track of the current position in the our random sample table
-   * going row by row from 1st column until the 10th column(Minstrel defines 10)
-   * then we wrap back to the row 1 col 1.
-   * note: there are many other ways to do this.
-   */
-  uint32_t m_col, m_index;							
-
-  uint32_t m_maxTpRate;  ///< the current throughput rate 
-  uint32_t m_maxTpRate2;  ///< second highest throughput rate
-  uint32_t m_maxProbRate;  ///< rate with highest prob of success
-
-  int m_packetCount;  ///< total number of packets as of now
-  int m_sampleCount;  ///< how many packets we have sample so far
-
-  bool m_isSampling;  ///< a flag to indicate we are currently sampling
-  uint32_t m_sampleRate;  ///< current sample rate
-  bool 	m_sampleRateSlower;  ///< a flag to indicate sample rate is slower
-  uint32_t m_currentRate;  ///< current rate we are using
-
-  uint32_t m_shortRetry;  ///< short retries such as control packts
-  uint32_t m_longRetry;  ///< long retries such as data packets
-  uint32_t m_retry;  ///< total retries short + long
-  uint32_t m_err;  ///< retry errors
-  uint32_t m_txrate;  ///< current transmit rate
-
-  bool m_initialized;  ///< for initializing tables
-
-
-}; 
-
 }// namespace ns3
 
 #endif /* MINSTREL_WIFI_MANAGER_H */
--- a/src/devices/wifi/nqap-wifi-mac.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/nqap-wifi-mac.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -21,6 +21,7 @@
 #include "ns3/log.h"
 #include "ns3/simulator.h"
 #include "ns3/node.h"
+#include "ns3/boolean.h"
 
 #include "nqap-wifi-mac.h"
 #include "dca-txop.h"
@@ -416,24 +417,22 @@
 NqapWifiMac::TxOk (const WifiMacHeader &hdr)
 {
   NS_LOG_FUNCTION (this);
-  WifiRemoteStation *station = m_stationManager->Lookup (hdr.GetAddr1 ());
   if (hdr.IsAssocResp () && 
-      station->IsWaitAssocTxOk ()) 
+      m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ())) 
     {
       NS_LOG_DEBUG ("associated with sta="<<hdr.GetAddr1 ());
-      station->RecordGotAssocTxOk ();
+      m_stationManager->RecordGotAssocTxOk (hdr.GetAddr1 ());
     }
 }
 void 
 NqapWifiMac::TxFailed (const WifiMacHeader &hdr)
 {
   NS_LOG_FUNCTION (this);
-  WifiRemoteStation *station = m_stationManager->Lookup (hdr.GetAddr1 ());
   if (hdr.IsAssocResp () && 
-      station->IsWaitAssocTxOk ()) 
+      m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ())) 
     {
       NS_LOG_DEBUG ("assoc failed with sta="<<hdr.GetAddr1 ());
-      station->RecordGotAssocTxFailed ();
+      m_stationManager->RecordGotAssocTxFailed (hdr.GetAddr1 ());
     }
 }
 void 
@@ -442,7 +441,6 @@
   NS_LOG_FUNCTION (this << packet << hdr);
 
   Mac48Address from = hdr->GetAddr2 ();
-  WifiRemoteStation *fromStation = m_stationManager->Lookup (from);
 
   if (hdr->IsData ()) 
     {
@@ -450,17 +448,16 @@
       if (!hdr->IsFromDs () && 
           hdr->IsToDs () &&
           bssid == GetAddress () &&
-          fromStation->IsAssociated ()) 
+          m_stationManager->IsAssociated (from)) 
         {
           Mac48Address to = hdr->GetAddr3 ();
-          WifiRemoteStation *toStation = m_stationManager->Lookup (to);
           if (to == GetAddress ()) 
             {
               NS_LOG_DEBUG ("frame for me from="<<from);
               ForwardUp (packet, from, bssid);
             } 
           else if (to.IsGroup () ||
-                   toStation->IsAssociated ())
+                   m_stationManager->IsAssociated (to))
             {
               NS_LOG_DEBUG ("forwarding frame from="<<from<<", to="<<to);
               Ptr<Packet> copy = packet->Copy ();
@@ -530,17 +527,17 @@
                       WifiMode mode = m_phy->GetMode (j);
                       if (rates.IsSupportedRate (mode.GetDataRate ()))
                         {
-                          fromStation->AddSupportedMode (mode);
+                          m_stationManager->AddSupportedMode (from, mode);
                         }
                     }
-                  fromStation->RecordWaitAssocTxOk ();
+                  m_stationManager->RecordWaitAssocTxOk (from);
                   // send assoc response with success status.
                   SendAssocResp (hdr->GetAddr2 (), true);
                 }
             } 
           else if (hdr->IsDisassociation ()) 
             {
-              fromStation->RecordDisassociated ();
+              m_stationManager->RecordDisassociated (from);
             } 
           else if (hdr->IsReassocReq ()) 
             {
--- a/src/devices/wifi/nqsta-wifi-mac.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/nqsta-wifi-mac.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -24,6 +24,7 @@
 #include "ns3/log.h"
 #include "ns3/node.h"
 #include "ns3/uinteger.h"
+#include "ns3/boolean.h"
 #include "ns3/trace-source-accessor.h"
 
 #include "nqsta-wifi-mac.h"
@@ -609,13 +610,12 @@
               SetState (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);
+                      m_stationManager->AddSupportedMode (hdr->GetAddr2 (), mode);
                       if (rates.IsBasicRate (mode.GetDataRate ()))
                         {
                           m_stationManager->AddBasicMode (mode);
--- a/src/devices/wifi/onoe-wifi-manager.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/onoe-wifi-manager.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -27,6 +27,19 @@
 
 namespace ns3 {
 
+struct OnoeWifiRemoteStation : public WifiRemoteStation
+{
+  Time m_nextModeUpdate;
+  uint32_t m_shortRetry;
+  uint32_t m_longRetry;
+  uint32_t m_tx_ok;
+  uint32_t m_tx_err;
+  uint32_t m_tx_retr;
+  uint32_t m_tx_upper;
+  uint32_t m_txrate;
+};
+
+
 NS_OBJECT_ENSURE_REGISTERED (OnoeWifiManager);
 
 TypeId
@@ -55,74 +68,76 @@
 OnoeWifiManager::OnoeWifiManager ()
 {}
 WifiRemoteStation *
-OnoeWifiManager::CreateStation (void)
+OnoeWifiManager::DoCreateStation (void) const
 {
-  return new OnoeWifiRemoteStation (this);
+  OnoeWifiRemoteStation *station = new OnoeWifiRemoteStation ();
+  station->m_nextModeUpdate = Simulator::Now () + m_updatePeriod;
+  station->m_shortRetry = 0;
+  station->m_longRetry = 0;
+  station->m_tx_ok = 0;
+  station->m_tx_err = 0;
+  station->m_tx_retr = 0;
+  station->m_tx_upper = 0;
+  station->m_txrate = 0;
+  return station;
 }
-
-OnoeWifiRemoteStation::OnoeWifiRemoteStation (Ptr<OnoeWifiManager> stations)
-  : m_stations (stations),
-    m_nextModeUpdate (Simulator::Now () + stations->m_updatePeriod),
-    m_shortRetry (0),
-    m_longRetry (0),
-    m_tx_ok (0),
-    m_tx_err (0),
-    m_tx_retr (0),
-    m_tx_upper (0),
-    m_txrate (0)
-{}
-OnoeWifiRemoteStation::~OnoeWifiRemoteStation ()
-{}
-
 void 
-OnoeWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
+OnoeWifiManager::DoReportRxOk (WifiRemoteStation *station,
+                                     double rxSnr, WifiMode txMode)
 {}
 void 
-OnoeWifiRemoteStation::DoReportRtsFailed (void)
+OnoeWifiManager::DoReportRtsFailed (WifiRemoteStation *st)
 {
-  m_shortRetry++;
+  OnoeWifiRemoteStation *station = (OnoeWifiRemoteStation *)st;
+  station->m_shortRetry++;
+}
+void 
+OnoeWifiManager::DoReportDataFailed (WifiRemoteStation *st)
+{
+  OnoeWifiRemoteStation *station = (OnoeWifiRemoteStation *)st;
+  station->m_longRetry++;
 }
 void 
-OnoeWifiRemoteStation::DoReportDataFailed (void)
-{
-  m_longRetry++;
-}
-void 
-OnoeWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
+OnoeWifiManager::DoReportRtsOk (WifiRemoteStation *station,
+                                      double ctsSnr, WifiMode ctsMode, double rtsSnr)
 {}
 void 
-OnoeWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+OnoeWifiManager::DoReportDataOk (WifiRemoteStation *st,
+                                       double ackSnr, WifiMode ackMode, double dataSnr)
 {
-  UpdateRetry ();
-  m_tx_ok++;
+  OnoeWifiRemoteStation *station = (OnoeWifiRemoteStation *)st;
+  UpdateRetry (station);
+  station->m_tx_ok++;
 }
 void 
-OnoeWifiRemoteStation::DoReportFinalRtsFailed (void)
+OnoeWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *st)
 {
-  UpdateRetry ();
-  m_tx_err++;
+  OnoeWifiRemoteStation *station = (OnoeWifiRemoteStation *)st;
+  UpdateRetry (station);
+  station->m_tx_err++;
 }
 void 
-OnoeWifiRemoteStation::DoReportFinalDataFailed (void)
+OnoeWifiManager::DoReportFinalDataFailed (WifiRemoteStation *st)
 {
-  UpdateRetry ();
-  m_tx_err++;
+  OnoeWifiRemoteStation *station = (OnoeWifiRemoteStation *)st;
+  UpdateRetry (station);
+  station->m_tx_err++;
 }
 void
-OnoeWifiRemoteStation::UpdateRetry (void)
+OnoeWifiManager::UpdateRetry (OnoeWifiRemoteStation *station)
 {
-  m_tx_retr += m_shortRetry + m_longRetry;
-  m_shortRetry = 0;
-  m_longRetry = 0;
+  station->m_tx_retr += station->m_shortRetry + station->m_longRetry;
+  station->m_shortRetry = 0;
+  station->m_longRetry = 0;
 }
 void
-OnoeWifiRemoteStation::UpdateMode (void)
+OnoeWifiManager::UpdateMode (OnoeWifiRemoteStation *station)
 {
-  if (Simulator::Now () < m_nextModeUpdate)
+  if (Simulator::Now () < station->m_nextModeUpdate)
     {
       return;
     }
-  m_nextModeUpdate = Simulator::Now () + m_stations->m_updatePeriod;
+  station->m_nextModeUpdate = Simulator::Now () + m_updatePeriod;
   /**
    * The following 20 lines of code were copied from the Onoe
    * rate control kernel module used in the madwifi driver.
@@ -130,112 +145,116 @@
 
   int dir = 0, enough;
   uint32_t nrate;
-  enough = (m_tx_ok + m_tx_err >= 10);
+  enough = (station->m_tx_ok + station->m_tx_err >= 10);
 
   /* no packet reached -> down */
-  if (m_tx_err > 0 && m_tx_ok == 0)
+  if (station->m_tx_err > 0 && station->m_tx_ok == 0)
     dir = -1;
 
   /* all packets needs retry in average -> down */
-  if (enough && m_tx_ok < m_tx_retr)
+  if (enough && station->m_tx_ok < station->m_tx_retr)
     dir = -1;
 
   /* no error and less than rate_raise% of packets need retry -> up */
-  if (enough && m_tx_err == 0 &&
-      m_tx_retr < (m_tx_ok * m_stations->m_addCreditThreshold) / 100)
+  if (enough && station->m_tx_err == 0 &&
+      station->m_tx_retr < (station->m_tx_ok * m_addCreditThreshold) / 100)
     dir = 1;
 
-  NS_LOG_DEBUG (this << " ok " << m_tx_ok << " err " << m_tx_err << " retr " << m_tx_retr <<
-                " upper " << m_tx_upper << " dir " << dir);
+  NS_LOG_DEBUG (this << " ok " << station->m_tx_ok << " err " << station->m_tx_err << " retr " << station->m_tx_retr <<
+                " upper " << station->m_tx_upper << " dir " << dir);
 
-  nrate = m_txrate;
+  nrate = station->m_txrate;
   switch (dir) {
   case 0:
-    if (enough && m_tx_upper > 0)
-      m_tx_upper--;
+    if (enough && station->m_tx_upper > 0)
+      station->m_tx_upper--;
     break;
   case -1:
     if (nrate > 0) {
       nrate--;
     }
-    m_tx_upper = 0;
+    station->m_tx_upper = 0;
     break;
   case 1:
     /* raise rate if we hit rate_raise_threshold */
-    if (++m_tx_upper < m_stations->m_raiseThreshold)
+    if (++station->m_tx_upper < m_raiseThreshold)
       break;
-    m_tx_upper = 0;
-    if (nrate + 1 < GetNSupportedModes ()) {
+    station->m_tx_upper = 0;
+    if (nrate + 1 < GetNSupported (station)) {
       nrate++;
     }
     break;
   }
 
-  if (nrate != m_txrate) {
-    NS_ASSERT (nrate < GetNSupportedModes ());
-    m_txrate = nrate;
-    m_tx_ok = m_tx_err = m_tx_retr = m_tx_upper = 0;
+  if (nrate != station->m_txrate) {
+    NS_ASSERT (nrate < GetNSupported (station));
+    station->m_txrate = nrate;
+    station->m_tx_ok = station->m_tx_err = station->m_tx_retr = station->m_tx_upper = 0;
   } else if (enough)
-    m_tx_ok = m_tx_err = m_tx_retr = 0;
+    station->m_tx_ok = station->m_tx_err = station->m_tx_retr = 0;
 
 }
 
-Ptr<WifiRemoteStationManager>
-OnoeWifiRemoteStation::GetManager (void) const
-{
-  return m_stations;
-}
 WifiMode 
-OnoeWifiRemoteStation::DoGetDataMode (uint32_t size)
+OnoeWifiManager::DoGetDataMode (WifiRemoteStation *st,
+                                      uint32_t size)
 {
-  UpdateMode ();
-  NS_ASSERT (m_txrate < GetNSupportedModes ());
+  OnoeWifiRemoteStation *station = (OnoeWifiRemoteStation *)st;
+  UpdateMode (station);
+  NS_ASSERT (station->m_txrate < GetNSupported (station));
   uint32_t rateIndex;
-  if (m_longRetry < 4)
+  if (station->m_longRetry < 4)
     {
-      rateIndex = m_txrate;
+      rateIndex = station->m_txrate;
     }
-  else if (m_longRetry < 6)
+  else if (station->m_longRetry < 6)
     {
-      if (m_txrate > 0)
+      if (station->m_txrate > 0)
         {
-          rateIndex = m_txrate - 1;
+          rateIndex = station->m_txrate - 1;
         }
       else
         {
-          rateIndex = m_txrate;
+          rateIndex = station->m_txrate;
         }
     }
-  else if (m_longRetry < 8)
+  else if (station->m_longRetry < 8)
     {
-      if (m_txrate > 1)
+      if (station->m_txrate > 1)
         {
-          rateIndex = m_txrate - 2;
+          rateIndex = station->m_txrate - 2;
         }
       else
         {
-          rateIndex = m_txrate;
+          rateIndex = station->m_txrate;
         }
     }
   else
     {
-      if (m_txrate > 2)
+      if (station->m_txrate > 2)
         {
-          rateIndex = m_txrate - 3;
+          rateIndex = station->m_txrate - 3;
         }
       else
         {
-          rateIndex = m_txrate;
+          rateIndex = station->m_txrate;
         }
     }
-  return GetSupportedMode (rateIndex);
+  return GetSupported (station, rateIndex);
 }
 WifiMode 
-OnoeWifiRemoteStation::DoGetRtsMode (void)
+OnoeWifiManager::DoGetRtsMode (WifiRemoteStation *st)
 {
-  UpdateMode ();
+  OnoeWifiRemoteStation *station = (OnoeWifiRemoteStation *)st;
+  UpdateMode (station);
   // XXX: can we implement something smarter ?
-  return GetSupportedMode (0);
+  return GetSupported (station, 0);
+}
+
+bool 
+OnoeWifiManager::IsLowLatency (void) const
+{
+  return false;
 }
 
 } // namespace ns3
--- a/src/devices/wifi/onoe-wifi-manager.h	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/onoe-wifi-manager.h	Wed Jan 06 16:26:07 2010 +0100
@@ -25,6 +25,8 @@
 
 namespace ns3 {
 
+class OnoeWifiRemoteStation;
+
 /**
  * \brief an implementation of rate control algorithm developed 
  *        by Atsushi Onoe
@@ -42,49 +44,30 @@
   OnoeWifiManager ();
 
 private:
-  friend class OnoeWifiRemoteStation;
-  virtual WifiRemoteStation *CreateStation (void);
+  // overriden from base class
+  virtual class WifiRemoteStation *DoCreateStation (void) const;
+  virtual void DoReportRxOk (WifiRemoteStation *station, 
+                             double rxSnr, WifiMode txMode);
+  virtual void DoReportRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportDataFailed (WifiRemoteStation *station);
+  virtual void DoReportRtsOk (WifiRemoteStation *station,
+                              double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void DoReportDataOk (WifiRemoteStation *station,
+                               double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual void DoReportFinalRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportFinalDataFailed (WifiRemoteStation *station);
+  virtual WifiMode DoGetDataMode (WifiRemoteStation *station, uint32_t size);
+  virtual WifiMode DoGetRtsMode (WifiRemoteStation *station);
+  virtual bool IsLowLatency (void) const;
+
+  void UpdateRetry (OnoeWifiRemoteStation *station);
+  void UpdateMode (OnoeWifiRemoteStation *station);
 
   Time m_updatePeriod;
   uint32_t m_addCreditThreshold;
   uint32_t m_raiseThreshold;
 };
 
-class OnoeWifiRemoteStation : public WifiRemoteStation
-{
-public:
-  OnoeWifiRemoteStation (Ptr<OnoeWifiManager> stations);
-
-  virtual ~OnoeWifiRemoteStation ();
-
-protected:
-  virtual void DoReportRxOk (double rxSnr, WifiMode txMode);
-  virtual void DoReportRtsFailed (void);
-  virtual void DoReportDataFailed (void);
-  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
-  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
-  virtual void DoReportFinalRtsFailed (void);
-  virtual void DoReportFinalDataFailed (void);
-
-private:
-  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
-  virtual WifiMode DoGetDataMode (uint32_t size);
-  virtual WifiMode DoGetRtsMode (void);
-
-  void UpdateRetry (void);
-  void UpdateMode (void);
-
-  Ptr<OnoeWifiManager> m_stations;
-  Time m_nextModeUpdate;
-  uint32_t m_shortRetry;
-  uint32_t m_longRetry;
-  uint32_t m_tx_ok;
-  uint32_t m_tx_err;
-  uint32_t m_tx_retr;
-  uint32_t m_tx_upper;
-  uint32_t m_txrate;
-};
-
 } // namespace ns3
 
 #endif /* ONOE_WIFI_MANAGER_H */
--- a/src/devices/wifi/propagation-loss-model-test-suite.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/propagation-loss-model-test-suite.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -23,6 +23,7 @@
 #include "ns3/config.h"
 #include "ns3/string.h"
 #include "ns3/uinteger.h"
+#include "ns3/double.h"
 #include "ns3/data-rate.h"
 #include "ns3/inet-socket-address.h"
 #include "ns3/internet-stack-helper.h"
--- a/src/devices/wifi/qadhoc-wifi-mac.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/qadhoc-wifi-mac.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -243,16 +243,15 @@
   hdr.SetDsNotFrom ();
   hdr.SetDsNotTo ();
 
-  WifiRemoteStation *destination = m_stationManager->Lookup (to);
-  if (destination->IsBrandNew ())
+  if (m_stationManager->IsBrandNew (to))
     {
       // 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));
+          m_stationManager->AddSupportedMode (to, m_phy->GetMode (i));
         }
-      destination->RecordDisassociated ();
+      m_stationManager->RecordDisassociated (to);
     }
 
   uint8_t tid = QosUtilsGetTidForPacket (packet);
--- a/src/devices/wifi/qap-wifi-mac.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/qap-wifi-mac.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -24,6 +24,7 @@
 #include "ns3/simulator.h"
 #include "ns3/string.h"
 #include "ns3/pointer.h"
+#include "ns3/boolean.h"
 
 #include "qos-tag.h"
 #include "qap-wifi-mac.h"
@@ -529,12 +530,11 @@
 QapWifiMac::TxOk (const WifiMacHeader &hdr)
 {
   NS_LOG_FUNCTION (this);
-  WifiRemoteStation *station = m_stationManager->Lookup (hdr.GetAddr1 ());
   if (hdr.IsAssocResp () && 
-      station->IsWaitAssocTxOk ()) 
+      m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ())) 
     {
       NS_LOG_DEBUG ("associated with sta="<<hdr.GetAddr1 ());
-      station->RecordGotAssocTxOk ();
+      m_stationManager->RecordGotAssocTxOk (hdr.GetAddr1 ());
     }
 }
 
@@ -542,12 +542,11 @@
 QapWifiMac::TxFailed (const WifiMacHeader &hdr)
 {
   NS_LOG_FUNCTION (this);
-  WifiRemoteStation *station = m_stationManager->Lookup (hdr.GetAddr1 ());
   if (hdr.IsAssocResp () && 
-      station->IsWaitAssocTxOk ()) 
+      m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ())) 
     {
       NS_LOG_DEBUG ("assoc failed with sta="<<hdr.GetAddr1 ());
-      station->RecordGotAssocTxFailed ();
+      m_stationManager->RecordGotAssocTxFailed (hdr.GetAddr1 ());
     }
 }
 
@@ -557,7 +556,6 @@
   NS_LOG_FUNCTION (this << packet << hdr);
 
   Mac48Address from = hdr->GetAddr2 ();
-  WifiRemoteStation *fromStation = m_stationManager->Lookup (from);
   
   if (hdr->IsData ())
     {
@@ -565,10 +563,9 @@
       if (!hdr->IsFromDs () && 
           hdr->IsToDs () &&
           bssid == GetAddress () &&
-          fromStation->IsAssociated ())
+          m_stationManager->IsAssociated (from))
         {
           Mac48Address to = hdr->GetAddr3 ();
-          WifiRemoteStation *toStation = m_stationManager->Lookup (to);
           
           if (to == GetAddress ())
             {
@@ -592,7 +589,7 @@
                 }
             }
           else if (to.IsGroup () ||
-                   toStation->IsAssociated ())
+                   m_stationManager->IsAssociated (to))
             {
               NS_LOG_DEBUG ("forwarding frame from="<<from<<", to="<<to);
               Ptr<Packet> copy = packet->Copy ();
@@ -658,17 +655,17 @@
                      WifiMode mode = m_phy->GetMode (j);
                      if (rates.IsSupportedRate (mode.GetDataRate ()))
                        {
-                         fromStation->AddSupportedMode (mode);
+                         m_stationManager->AddSupportedMode (from, mode);
                        }
-                    }
-                  fromStation->RecordWaitAssocTxOk ();
-                  // send assoc response with success status.
-                  SendAssocResp (hdr->GetAddr2 (), true);
-                }
+                   }
+                 m_stationManager->RecordWaitAssocTxOk (from);
+                 // send assoc response with success status.
+                 SendAssocResp (hdr->GetAddr2 (), true);
+               }
             }
           else if (hdr->IsDisassociation ()) 
             {
-              fromStation->RecordDisassociated ();
+              m_stationManager->RecordDisassociated (from);
             } 
           else if (hdr->IsReassocReq ()) 
             {
--- a/src/devices/wifi/qsta-wifi-mac.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/qsta-wifi-mac.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -23,6 +23,7 @@
 #include "ns3/simulator.h"
 #include "ns3/string.h"
 #include "ns3/pointer.h"
+#include "ns3/boolean.h"
 
 #include "qos-tag.h"
 #include "edca-txop-n.h"
@@ -649,13 +650,12 @@
               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);
+                      m_stationManager->AddSupportedMode (hdr->GetAddr2 (), mode);
                       if (rates.IsBasicRate (mode.GetDataRate ()))
                         {
                           m_stationManager->AddBasicMode (mode);
--- a/src/devices/wifi/rraa-wifi-manager.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/rraa-wifi-manager.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -30,162 +30,21 @@
 
 namespace ns3 {
 
-NS_OBJECT_ENSURE_REGISTERED(RraaWifiManager);
-  
-RraaWifiRemoteStation::RraaWifiRemoteStation (Ptr<RraaWifiManager> stations)
-  : m_stations (stations)
-{
-  m_initialized = false;
-  m_rtsWnd = 0;
-  m_rtsCounter = 0;
-  m_rtsOn = false;
-  m_lastFrameFail = false;
-}
-
-RraaWifiRemoteStation::~RraaWifiRemoteStation ()
-{}
-
-void
-RraaWifiRemoteStation::ResetCountersBasic (void)
-{
-  if (!m_initialized) {
-    m_rate = GetMaxRate ();
-    m_initialized = true;
-  }
-  m_failed = 0;
-  m_counter = GetThresholds (m_rate).ewnd;
-  m_lastReset = Simulator::Now ();
-}
-
-Ptr<WifiRemoteStationManager>
-RraaWifiRemoteStation::GetManager (void) const
-{
-  return m_stations;
-}
-
-uint32_t
-RraaWifiRemoteStation::GetMaxRate (void)
-{
-  return GetNSupportedModes () - 1;
-}
-uint32_t
-RraaWifiRemoteStation::GetMinRate (void)
-{
-  return 0;
-}
-
-ThresholdsItem
-RraaWifiRemoteStation::GetThresholds (uint32_t rate) 
-{
-  WifiMode mode = GetSupportedMode (rate);
-  return m_stations->GetThresholds (mode);
-}
-
-
-void 
-RraaWifiRemoteStation::DoReportRtsFailed (void)
-{}
-
-void 
-RraaWifiRemoteStation::DoReportDataFailed (void)
-{
-  m_lastFrameFail = true;
-  CheckTimeout ();
-  m_counter--;
-  m_failed++;
-  RunBasicAlgorithm ();
-}
-void 
-RraaWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
-{}
-void 
-RraaWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
-{
-  NS_LOG_DEBUG ("self="<<this<<" rts ok");
-}
-void 
-RraaWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+struct RraaWifiRemoteStation : public WifiRemoteStation
 {
-  m_lastFrameFail = false;
-  CheckTimeout ();
-  m_counter--;
-  RunBasicAlgorithm ();
-}
-void 
-RraaWifiRemoteStation::DoReportFinalRtsFailed (void)
-{}
-void 
-RraaWifiRemoteStation::DoReportFinalDataFailed (void)
-{}
-
-WifiMode
-RraaWifiRemoteStation::DoGetDataMode (uint32_t size)
-{
-  if (!m_initialized)
-    ResetCountersBasic ();
-  return GetSupportedMode (m_rate);
-}
-WifiMode
-RraaWifiRemoteStation::DoGetRtsMode (void)
-{
-  return GetSupportedMode (0);
-}
-
-bool
-RraaWifiRemoteStation::NeedRts (Ptr<const Packet> packet)
-{
-  if (m_stations->OnlyBasic ())
-    return WifiRemoteStation::NeedRts (packet);
-  ARts ();
-  return m_rtsOn;
-}
+  uint32_t m_counter;
+  uint32_t m_failed;
+  uint32_t m_rtsWnd;
+  uint32_t m_rtsCounter;
+  Time m_lastReset;
+  bool m_rtsOn;
+  bool m_lastFrameFail;
+  bool m_initialized;
 
-void
-RraaWifiRemoteStation::CheckTimeout (void)
-{
-  Time d = Simulator::Now () - m_lastReset;
-  if (m_counter == 0 || d > m_stations->GetTimeout ()) {
-    ResetCountersBasic ();
-  }
-}
+  uint32_t m_rate;
+};
 
-void
-RraaWifiRemoteStation::RunBasicAlgorithm (void)
-{
-  ThresholdsItem thresholds = GetThresholds (m_rate);
-  double ploss = (double) m_failed / (double) thresholds.ewnd;
-  if (m_counter == 0 || ploss > thresholds.pmtl) {
-    if (m_rate > GetMinRate () && ploss > thresholds.pmtl) {
-      m_rate--;
-    }
-    else if (m_rate < GetMaxRate () && ploss < thresholds.pori) {
-      m_rate++;
-    }
-    ResetCountersBasic ();
-  }
-}
-
-void
-RraaWifiRemoteStation::ARts (void)
-{
-  if (!m_rtsOn && m_lastFrameFail) {
-    m_rtsWnd++;
-    m_rtsCounter = m_rtsWnd;
-  }
-  else if ((m_rtsOn && m_lastFrameFail) || 
-           (!m_rtsOn && !m_lastFrameFail)) {
-    m_rtsWnd = m_rtsWnd / 2;
-    m_rtsCounter = m_rtsWnd;
-  }
-  if (m_rtsCounter > 0) {
-    m_rtsOn = true;
-    m_rtsCounter--;
-  }
-  else {
-    m_rtsOn = false;
-  }
-}
-
+NS_OBJECT_ENSURE_REGISTERED(RraaWifiManager);
 
 TypeId 
 RraaWifiManager::GetTypeId (void)
@@ -323,87 +182,251 @@
 RraaWifiManager::~RraaWifiManager ()
 {}
 
+
 WifiRemoteStation *
-RraaWifiManager::CreateStation (void)
+RraaWifiManager::DoCreateStation (void) const
+{
+  RraaWifiRemoteStation *station = new RraaWifiRemoteStation ();
+  station->m_initialized = false;
+  station->m_rtsWnd = 0;
+  station->m_rtsCounter = 0;
+  station->m_rtsOn = false;
+  station->m_lastFrameFail = false;
+  return station;
+}
+
+void
+RraaWifiManager::ResetCountersBasic (RraaWifiRemoteStation *station)
+{
+  if (!station->m_initialized)
+    {
+      station->m_rate = GetMaxRate (station);
+      station->m_initialized = true;
+    }
+  station->m_failed = 0;
+  station->m_counter = GetThresholds (station, station->m_rate).ewnd;
+  station->m_lastReset = Simulator::Now ();
+}
+
+uint32_t
+RraaWifiManager::GetMaxRate (RraaWifiRemoteStation *station)
+{
+  return GetNSupported (station) - 1;
+}
+uint32_t
+RraaWifiManager::GetMinRate (RraaWifiRemoteStation *station)
+{
+  return 0;
+}
+
+
+void 
+RraaWifiManager::DoReportRtsFailed (WifiRemoteStation *st)
+{}
+
+void 
+RraaWifiManager::DoReportDataFailed (WifiRemoteStation *st)
 {
-  return new RraaWifiRemoteStation (this);
+  RraaWifiRemoteStation *station = (RraaWifiRemoteStation *) st;
+  station->m_lastFrameFail = true;
+  CheckTimeout (station);
+  station->m_counter--;
+  station->m_failed++;
+  RunBasicAlgorithm (station);
+}
+void 
+RraaWifiManager::DoReportRxOk (WifiRemoteStation *st,
+                               double rxSnr, WifiMode txMode)
+{}
+void 
+RraaWifiManager::DoReportRtsOk (WifiRemoteStation *st,
+                                double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+  NS_LOG_DEBUG ("self="<<st<<" rts ok");
+}
+void 
+RraaWifiManager::DoReportDataOk (WifiRemoteStation *st,
+                                 double ackSnr, WifiMode ackMode, double dataSnr)
+{
+  RraaWifiRemoteStation *station = (RraaWifiRemoteStation *) st;
+  station->m_lastFrameFail = false;
+  CheckTimeout (station);
+  station->m_counter--;
+  RunBasicAlgorithm (station);
+}
+void 
+RraaWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *st)
+{}
+void 
+RraaWifiManager::DoReportFinalDataFailed (WifiRemoteStation *st)
+{}
+
+WifiMode
+RraaWifiManager::DoGetDataMode (WifiRemoteStation *st,
+                                uint32_t size)
+{
+  RraaWifiRemoteStation *station = (RraaWifiRemoteStation *) st;
+  if (!station->m_initialized)
+    {
+      ResetCountersBasic (station);
+    }
+  return GetSupported (station, station->m_rate);
+}
+WifiMode
+RraaWifiManager::DoGetRtsMode (WifiRemoteStation *st)
+{
+  return GetSupported (st, 0);
 }
 
 bool
-RraaWifiManager::OnlyBasic (void)
+RraaWifiManager::DoNeedRts (WifiRemoteStation *st,
+                            Ptr<const Packet> packet, bool normally)
 {
-  return m_basic;
+  RraaWifiRemoteStation *station = (RraaWifiRemoteStation *) st;
+  if (m_basic)
+    {
+      return normally;
+    }
+  ARts (station);
+  return station->m_rtsOn;
+}
+
+void
+RraaWifiManager::CheckTimeout (RraaWifiRemoteStation *station)
+{
+  Time d = Simulator::Now () - station->m_lastReset;
+  if (station->m_counter == 0 || d > m_timeout) 
+    {
+      ResetCountersBasic (station);
+    }
 }
 
-Time
-RraaWifiManager::GetTimeout (void) const
+void
+RraaWifiManager::RunBasicAlgorithm (RraaWifiRemoteStation *station)
 {
-  return m_timeout;
+  ThresholdsItem thresholds = GetThresholds (station, station->m_rate);
+  double ploss = (double) station->m_failed / (double) thresholds.ewnd;
+  if (station->m_counter == 0 || 
+      ploss > thresholds.pmtl) 
+    {
+      if (station->m_rate > GetMinRate (station) && 
+          ploss > thresholds.pmtl) 
+        {
+          station->m_rate--;
+        }
+      else if (station->m_rate < GetMaxRate (station) && 
+               ploss < thresholds.pori) 
+        {
+          station->m_rate++;
+        }
+      ResetCountersBasic (station);
+    }
 }
 
-ThresholdsItem
+void
+RraaWifiManager::ARts (RraaWifiRemoteStation *station)
+{
+  if (!station->m_rtsOn && 
+      station->m_lastFrameFail) 
+    {
+      station->m_rtsWnd++;
+      station->m_rtsCounter = station->m_rtsWnd;
+    }
+  else if ((station->m_rtsOn && station->m_lastFrameFail) || 
+           (!station->m_rtsOn && !station->m_lastFrameFail)) 
+    {
+      station->m_rtsWnd = station->m_rtsWnd / 2;
+      station->m_rtsCounter = station->m_rtsWnd;
+    }
+  if (station->m_rtsCounter > 0) 
+    {
+      station->m_rtsOn = true;
+      station->m_rtsCounter--;
+    }
+  else 
+    {
+      station->m_rtsOn = false;
+    }
+}
+
+struct RraaWifiManager::ThresholdsItem
+RraaWifiManager::GetThresholds (RraaWifiRemoteStation *station, 
+                                uint32_t rate) const
+{
+  WifiMode mode = GetSupported (station, rate);
+  return GetThresholds (mode);
+}
+
+struct RraaWifiManager::ThresholdsItem
 RraaWifiManager::GetThresholds (WifiMode mode) const
 {
-  switch (mode.GetDataRate () / 1000000) {
-  case 54: {
-    ThresholdsItem mode54 = {54000000, 
-                             0.0, 
-                             m_pmtlfor54, 
-                             m_ewndfor54};
-    return mode54;
-  } break;
-  case 48: {
-    ThresholdsItem mode48 = {48000000, 
-                             m_porifor48, 
-                             m_pmtlfor48, 
-                             m_ewndfor48};
-    return mode48;
-  } break;
-  case 36: {
-    ThresholdsItem mode36 = {36000000, 
-                             m_porifor36, 
-                             m_pmtlfor36, 
-                             m_ewndfor36};
-    return mode36;
-  } break;
-  case 24: {
-    ThresholdsItem mode24 = {24000000, 
-                             m_porifor24, 
-                             m_pmtlfor24, 
-                             m_ewndfor24};
-    return mode24;
-  } break;
-  case 18: {
-    ThresholdsItem mode18 = {18000000, 
-                             m_porifor18, 
-                             m_pmtlfor18, 
-                             m_ewndfor18};
-    return mode18;
-  } break;
-  case 12: {
-    ThresholdsItem mode12 = {12000000, 
-                             m_porifor12, 
-                             m_pmtlfor12, 
-                             m_ewndfor12};
-    return mode12;
-  } break;
-  case 9: {
-    ThresholdsItem mode9 =  {9000000, 
-                             m_porifor9, 
-                             m_pmtlfor9, 
-                             m_ewndfor9};
-    return mode9;
-  } break;
-  case 6: {
-    ThresholdsItem mode6 =  {6000000, 
-                             m_porifor6, 
-                             1.0, 
-                             m_ewndfor6};
-    return mode6;
-  } break;
-  }
+  switch (mode.GetDataRate () / 1000000) 
+    {
+    case 54: {
+      ThresholdsItem mode54 = {54000000, 
+                               0.0, 
+                               m_pmtlfor54, 
+                               m_ewndfor54};
+      return mode54;
+    } break;
+    case 48: {
+      ThresholdsItem mode48 = {48000000, 
+                               m_porifor48, 
+                               m_pmtlfor48, 
+                               m_ewndfor48};
+      return mode48;
+    } break;
+    case 36: {
+      ThresholdsItem mode36 = {36000000, 
+                               m_porifor36, 
+                               m_pmtlfor36, 
+                               m_ewndfor36};
+      return mode36;
+    } break;
+    case 24: {
+      ThresholdsItem mode24 = {24000000, 
+                               m_porifor24, 
+                               m_pmtlfor24, 
+                               m_ewndfor24};
+      return mode24;
+    } break;
+    case 18: {
+      ThresholdsItem mode18 = {18000000, 
+                               m_porifor18, 
+                               m_pmtlfor18, 
+                               m_ewndfor18};
+      return mode18;
+    } break;
+    case 12: {
+      ThresholdsItem mode12 = {12000000, 
+                               m_porifor12, 
+                               m_pmtlfor12, 
+                               m_ewndfor12};
+      return mode12;
+    } break;
+    case 9: {
+      ThresholdsItem mode9 =  {9000000, 
+                               m_porifor9, 
+                               m_pmtlfor9, 
+                               m_ewndfor9};
+      return mode9;
+    } break;
+    case 6: {
+      ThresholdsItem mode6 =  {6000000, 
+                               m_porifor6, 
+                               1.0, 
+                               m_ewndfor6};
+      return mode6;
+    } break;
+    }
   NS_ASSERT_MSG(false, "Thresholds for an unknown mode are asked");
   return ThresholdsItem ();
 }
 
+bool
+RraaWifiManager::IsLowLatency (void) const
+{
+  return true;
+}
+
 } // namespace ns3
--- a/src/devices/wifi/rraa-wifi-manager.h	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/rraa-wifi-manager.h	Wed Jan 06 16:26:07 2010 +0100
@@ -25,14 +25,7 @@
 
 namespace ns3 {
 
-struct ThresholdsItem {
-  uint32_t datarate;
-  double pori;
-  double pmtl;
-  uint32_t ewnd;
-};
-
-typedef std::vector<ThresholdsItem> Thresholds;
+class RraaWifiRemoteStation;
 
 /**
  * \brief Robust Rate Adaptation Algorithm
@@ -49,11 +42,44 @@
 
   RraaWifiManager ();
   virtual ~RraaWifiManager ();
-  bool OnlyBasic (void);
-  Time GetTimeout (void) const;
-  ThresholdsItem GetThresholds (WifiMode mode) const;
+
 private:
-  virtual class WifiRemoteStation *CreateStation (void);  
+
+  struct ThresholdsItem 
+  {
+    uint32_t datarate;
+    double pori;
+    double pmtl;
+    uint32_t ewnd;
+  };
+
+  // overriden from base class
+  virtual class WifiRemoteStation *DoCreateStation (void) const;
+  virtual void DoReportRxOk (WifiRemoteStation *station, 
+                             double rxSnr, WifiMode txMode);
+  virtual void DoReportRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportDataFailed (WifiRemoteStation *station);
+  virtual void DoReportRtsOk (WifiRemoteStation *station,
+                              double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void DoReportDataOk (WifiRemoteStation *station,
+                               double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual void DoReportFinalRtsFailed (WifiRemoteStation *station);
+  virtual void DoReportFinalDataFailed (WifiRemoteStation *station);
+  virtual WifiMode DoGetDataMode (WifiRemoteStation *station, uint32_t size);
+  virtual WifiMode DoGetRtsMode (WifiRemoteStation *station);
+  virtual bool DoNeedRts (WifiRemoteStation *st,
+                          Ptr<const Packet> packet, bool normally);
+  virtual bool IsLowLatency (void) const;
+
+  uint32_t GetMaxRate (RraaWifiRemoteStation *station);
+  uint32_t GetMinRate (RraaWifiRemoteStation *station);
+  void CheckTimeout (RraaWifiRemoteStation *station);
+  void RunBasicAlgorithm (RraaWifiRemoteStation *station);
+  void ARts (RraaWifiRemoteStation *station);
+  void ResetCountersBasic (RraaWifiRemoteStation *station);
+  struct ThresholdsItem GetThresholds (WifiMode mode) const;
+  struct ThresholdsItem GetThresholds (RraaWifiRemoteStation *station, uint32_t rate) const;
+
   bool m_basic;
   Time m_timeout;
   uint32_t m_ewndfor54;
@@ -80,49 +106,6 @@
   double m_pmtlfor9;
 };
 
-
-class RraaWifiRemoteStation : public WifiRemoteStation
-{
-public:
-  RraaWifiRemoteStation (Ptr<RraaWifiManager> stations);
-  virtual ~RraaWifiRemoteStation ();
-
-  virtual bool NeedRts (Ptr<const Packet> packet);
-protected:
-  virtual void DoReportRxOk (double rxSnr, WifiMode txMode);
-  virtual void DoReportRtsFailed (void);
-  virtual void DoReportDataFailed (void);
-  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
-  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
-  virtual void DoReportFinalRtsFailed (void);
-  virtual void DoReportFinalDataFailed (void);
-
-private:
-  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
-  virtual WifiMode DoGetDataMode (uint32_t size);
-  virtual WifiMode DoGetRtsMode (void);
-  uint32_t GetMaxRate (void);
-  uint32_t GetMinRate (void);
-  ThresholdsItem GetThresholds (uint32_t rate);
-  void CheckTimeout (void);
-  void RunBasicAlgorithm (void);
-  void ARts (void);
-  void ResetCountersBasic (void);
-
-  uint32_t m_counter;
-  uint32_t m_failed;
-  uint32_t m_rtsWnd;
-  uint32_t m_rtsCounter;
-  Time m_lastReset;
-  bool m_rtsOn;
-  bool m_lastFrameFail;
-  bool m_initialized;
-
-  uint32_t m_rate;
-
-  Ptr<RraaWifiManager> m_stations;
-};
-
 } // namespace ns3
 
 #endif /* RRAA_WIFI_MANAGER_H */
--- a/src/devices/wifi/wifi-remote-station-manager.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/wifi-remote-station-manager.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -23,342 +23,14 @@
 #include "ns3/log.h"
 #include "ns3/tag.h"
 #include "ns3/boolean.h"
+#include "ns3/double.h"
 #include "ns3/uinteger.h"
 #include "ns3/wifi-phy.h"
 #include "ns3/trace-source-accessor.h"
+#include "wifi-mac-header.h"
 
 NS_LOG_COMPONENT_DEFINE ("WifiRemoteStationManager");
 
-namespace ns3 {
-
-/**
- * _all_ broadcast and multicast frames are transmitted
- * at the same constant default rate because since we don't
- * have any kind of feedback from their transmission,
- * we cannot adjust the rate, so, we pick one which ensures
- * that all frames reach destination.
- */
-class NonUnicastWifiRemoteStation : public WifiRemoteStation
-{
-public:
-  NonUnicastWifiRemoteStation (Ptr<WifiRemoteStationManager> stations);
-protected:
-  virtual void DoReportRxOk (double rxSnr, WifiMode txMode);
-  virtual void DoReportRtsFailed (void);
-  virtual void DoReportDataFailed (void);
-  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
-  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
-  virtual void DoReportFinalRtsFailed (void);
-  virtual void DoReportFinalDataFailed (void);
-private:
-  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
-  virtual WifiMode DoGetDataMode (uint32_t size);
-  virtual WifiMode DoGetRtsMode (void);
-  Ptr<WifiRemoteStationManager> m_stations;
-};
-
-NonUnicastWifiRemoteStation::NonUnicastWifiRemoteStation (Ptr<WifiRemoteStationManager> stations)
-  : m_stations (stations)
-{
-  RecordDisassociated ();
-}
-void 
-NonUnicastWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
-{
-  NS_ASSERT (false);
-}
-void 
-NonUnicastWifiRemoteStation::DoReportRtsFailed (void)
-{
-  NS_ASSERT (false);
-}
-void 
-NonUnicastWifiRemoteStation::DoReportDataFailed (void)
-{
-  NS_ASSERT (false);
-}
-void 
-NonUnicastWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
-{
-  NS_ASSERT (false);
-}
-void 
-NonUnicastWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
-{
-  NS_ASSERT (false);
-}
-void 
-NonUnicastWifiRemoteStation::DoReportFinalRtsFailed (void)
-{}
-void 
-NonUnicastWifiRemoteStation::DoReportFinalDataFailed (void)
-{}
-
-WifiMode 
-NonUnicastWifiRemoteStation::DoGetDataMode (uint32_t size)
-{
-  WifiMode mode = m_stations->GetNonUnicastMode ();
-  NS_LOG_DEBUG ("non-unicast size="<<size<<", mode="<<mode);
-  return mode;
-}
-WifiMode 
-NonUnicastWifiRemoteStation::DoGetRtsMode (void)
-{
-  NS_ASSERT (false);
-  // theoretically, no rts for broadcast/multicast packets.
-  return m_stations->GetBasicMode (0);
-}
-Ptr<WifiRemoteStationManager>
-NonUnicastWifiRemoteStation::GetManager (void) const
-{
-  return m_stations;
-}
-
-
-} // namespace ns3
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (WifiRemoteStationManager);
-
-TypeId 
-WifiRemoteStationManager::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::WifiRemoteStationManager")
-    .SetParent<Object> ()
-    .AddAttribute ("IsLowLatency", "If true, we attempt to modelize a so-called low-latency device: a device"
-                   " where decisions about tx parameters can be made on a per-packet basis and feedback about the"
-                   " transmission of each packet is obtained before sending the next. Otherwise, we modelize a "
-                   " high-latency device, that is a device where we cannot update our decision about tx parameters"
-                   " after every packet transmission.",
-                   BooleanValue (true),
-                   MakeBooleanAccessor (&WifiRemoteStationManager::m_isLowLatency),
-                   MakeBooleanChecker ())
-    .AddAttribute ("MaxSsrc", "The maximum number of retransmission attempts for an RTS. This value"
-                   " will not have any effect on some rate control algorithms.",
-                   UintegerValue (7),
-                   MakeUintegerAccessor (&WifiRemoteStationManager::m_maxSsrc),
-                   MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("MaxSlrc", "The maximum number of retransmission attempts for a DATA packet. This value"
-                   " will not have any effect on some rate control algorithms.",
-                   UintegerValue (7),
-                   MakeUintegerAccessor (&WifiRemoteStationManager::m_maxSlrc),
-                   MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("RtsCtsThreshold", "If a data packet is bigger than this value, we use an RTS/CTS handshake"
-                   " before sending the data. This value will not have any effect on some rate control algorithms.",
-                   UintegerValue (1500),
-                   MakeUintegerAccessor (&WifiRemoteStationManager::m_rtsCtsThreshold),
-                   MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("FragmentationThreshold", "If a data packet is bigger than this value, we fragment it such that"
-                   " the size of the fragments are equal or smaller than this value. This value will not have any effect"
-                   " on some rate control algorithms.",
-                   UintegerValue (1500),
-                   MakeUintegerAccessor (&WifiRemoteStationManager::m_fragmentationThreshold),
-                   MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("NonUnicastMode", "Wifi mode used for non-unicast transmissions.",
-                   WifiModeValue (),
-                   MakeWifiModeAccessor (&WifiRemoteStationManager::m_nonUnicastMode),
-                   MakeWifiModeChecker ())
-    .AddTraceSource ("MacTxRtsFailed", 
-                     "The transmission of a RTS by the MAC layer has failed",
-                     MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxRtsFailed))
-    .AddTraceSource ("MacTxDataFailed", 
-                     "The transmission of a data packet by the MAC layer has failed",
-                     MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxDataFailed))
-    .AddTraceSource ("MacTxFinalRtsFailed", 
-                     "The transmission of a RTS has exceeded the maximum number of attempts",
-                     MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxFinalRtsFailed))
-    .AddTraceSource ("MacTxFinalDataFailed", 
-                     "The transmission of a data packet has exceeded the maximum number of attempts",
-                     MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxFinalDataFailed))
-    ;
-  return tid;
-}
-
-WifiRemoteStationManager::WifiRemoteStationManager ()
-  : m_nonUnicast (new NonUnicastWifiRemoteStation (this))
-{}
-
-WifiRemoteStationManager::~WifiRemoteStationManager ()
-{
-}
-void 
-WifiRemoteStationManager::DoDispose (void)
-{
-  for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) 
-    {
-      delete (*i);
-    }
-  m_stations.clear ();
-  delete m_nonUnicast;
-}
-void
-WifiRemoteStationManager::SetupPhy (Ptr<WifiPhy> phy)
-{
-  m_defaultTxMode = phy->GetMode (0);
-  Reset ();
-}
-
-uint32_t 
-WifiRemoteStationManager::GetMaxSsrc (void) const
-{
-  return m_maxSsrc;
-}
-uint32_t 
-WifiRemoteStationManager::GetMaxSlrc (void) const
-{
-  return m_maxSlrc;
-}
-uint32_t 
-WifiRemoteStationManager::GetRtsCtsThreshold (void) const
-{
-  return m_rtsCtsThreshold;
-}
-uint32_t 
-WifiRemoteStationManager::GetFragmentationThreshold (void) const
-{
-  return m_fragmentationThreshold;
-}
-void 
-WifiRemoteStationManager::SetMaxSsrc (uint32_t maxSsrc)
-{
-  m_maxSsrc = maxSsrc;
-}
-void 
-WifiRemoteStationManager::SetMaxSlrc (uint32_t maxSlrc)
-{
-  m_maxSlrc = maxSlrc;
-}
-void 
-WifiRemoteStationManager::SetRtsCtsThreshold (uint32_t threshold)
-{
-  m_rtsCtsThreshold = threshold;
-}
-void 
-WifiRemoteStationManager::SetFragmentationThreshold (uint32_t threshold)
-{
-  m_fragmentationThreshold = threshold;
-} 
-
-WifiRemoteStation *
-WifiRemoteStationManager::Lookup (Mac48Address address)
-{
-  if (address.IsGroup ())
-    {
-      return m_nonUnicast;
-    }
-  for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) 
-    {
-      if ((*i)->GetAddress () == address)
-        {
-          return (*i);
-        }
-    }
-  WifiRemoteStation *station = CreateStation ();
-  station->SetAddress(address);
-  station->Reset ();
-  m_stations.push_back (station);
-  return station;
-}
-
-WifiRemoteStation *
-WifiRemoteStationManager::LookupNonUnicast (void)
-{
-  return m_nonUnicast;
-}
-
-WifiMode 
-WifiRemoteStationManager::GetDefaultMode (void) const
-{
-  return m_defaultTxMode;
-}
-void
-WifiRemoteStationManager::Reset (void)
-{
-  for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++)
-    {
-      delete (*i);
-    }
-  m_stations.clear ();
-  m_basicModes.clear ();
-  m_basicModes.push_back (m_defaultTxMode);
-  NS_ASSERT (m_defaultTxMode.IsMandatory ());
-}
-void 
-WifiRemoteStationManager::AddBasicMode (WifiMode mode)
-{
-  for (uint32_t i = 0; i < GetNBasicModes (); i++)
-    {
-      if (GetBasicMode (i) == mode)
-        {
-          return;
-        }
-    }
-  m_basicModes.push_back (mode);
-}
-uint32_t 
-WifiRemoteStationManager::GetNBasicModes (void) const
-{
-  return m_basicModes.size ();
-}
-WifiMode 
-WifiRemoteStationManager::GetBasicMode (uint32_t i) const
-{
-  NS_ASSERT (i < m_basicModes.size ());
-  return m_basicModes[i];
-}
-WifiRemoteStationManager::BasicModesIterator 
-WifiRemoteStationManager::BeginBasicModes (void) const
-{
-  return m_basicModes.begin ();
-}
-WifiRemoteStationManager::BasicModesIterator 
-WifiRemoteStationManager::EndBasicModes (void) const
-{
-  return m_basicModes.end ();
-}
-bool
-WifiRemoteStationManager::IsLowLatency (void) const
-{
-  return m_isLowLatency;
-}
-WifiMode
-WifiRemoteStationManager::GetNonUnicastMode (void) const
-{
-  if (m_nonUnicastMode == WifiMode ())
-    return GetBasicMode(0);
-  else
-    return m_nonUnicastMode;
-}
-
-
-void 
-WifiRemoteStationManager::NotifyTxRtsFailed (Mac48Address address)
-{
-  m_macTxRtsFailed (address);
-}
-
-void 
-WifiRemoteStationManager::NotifyTxDataFailed (Mac48Address address)
-{
-  m_macTxDataFailed (address);
-}
-
-void 
-WifiRemoteStationManager::NotifyTxFinalRtsFailed (Mac48Address address)
-{
-  m_macTxFinalRtsFailed (address);
-}
-
-void 
-WifiRemoteStationManager::NotifyTxFinalDataFailed (Mac48Address address)
-{
-  m_macTxFinalDataFailed (address);
-}
-
-
-
-} // namespace ns3
 
 /***************************************************************
  *           Packet Mode Tagger
@@ -451,103 +123,409 @@
 } // namespace ns3
 
 
-/***************************************************************
- *           WifiRemoteStation below.
- ***************************************************************/ 
+namespace ns3 {
 
-namespace ns3 {
+NS_OBJECT_ENSURE_REGISTERED (WifiRemoteStationManager);
 
 TypeId 
-WifiRemoteStation::GetTypeId (void)
+WifiRemoteStationManager::GetTypeId (void)
 {
-  static TypeId tid = TypeId ("ns3::WifiRemoteStation")
+  static TypeId tid = TypeId ("ns3::WifiRemoteStationManager")
     .SetParent<Object> ()
-    .AddTraceSource ("Ssrc", "The value of the ssrc counter: indicates the number of retransmissions of RTS.",
-                     MakeTraceSourceAccessor (&WifiRemoteStation::m_ssrc))
-    .AddTraceSource ("Slrc", "The value of the slrc counter: indicates the number of retransmissions of DATA.",
-                     MakeTraceSourceAccessor (&WifiRemoteStation::m_slrc))
+    .AddAttribute ("IsLowLatency", "If true, we attempt to modelize a so-called low-latency device: a device"
+                   " where decisions about tx parameters can be made on a per-packet basis and feedback about the"
+                   " transmission of each packet is obtained before sending the next. Otherwise, we modelize a "
+                   " high-latency device, that is a device where we cannot update our decision about tx parameters"
+                   " after every packet transmission.",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&WifiRemoteStationManager::IsLowLatency),
+                   MakeBooleanChecker ())
+    .AddAttribute ("MaxSsrc", "The maximum number of retransmission attempts for an RTS. This value"
+                   " will not have any effect on some rate control algorithms.",
+                   UintegerValue (7),
+                   MakeUintegerAccessor (&WifiRemoteStationManager::m_maxSsrc),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MaxSlrc", "The maximum number of retransmission attempts for a DATA packet. This value"
+                   " will not have any effect on some rate control algorithms.",
+                   UintegerValue (7),
+                   MakeUintegerAccessor (&WifiRemoteStationManager::m_maxSlrc),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("RtsCtsThreshold", "If a data packet is bigger than this value, we use an RTS/CTS handshake"
+                   " before sending the data. This value will not have any effect on some rate control algorithms.",
+                   UintegerValue (1500),
+                   MakeUintegerAccessor (&WifiRemoteStationManager::m_rtsCtsThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("FragmentationThreshold", "If a data packet is bigger than this value, we fragment it such that"
+                   " the size of the fragments are equal or smaller than this value. This value will not have any effect"
+                   " on some rate control algorithms.",
+                   UintegerValue (1500),
+                   MakeUintegerAccessor (&WifiRemoteStationManager::m_fragmentationThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("NonUnicastMode", "Wifi mode used for non-unicast transmissions.",
+                   WifiModeValue (),
+                   MakeWifiModeAccessor (&WifiRemoteStationManager::m_nonUnicastMode),
+                   MakeWifiModeChecker ())
+    .AddTraceSource ("MacTxRtsFailed", 
+                     "The transmission of a RTS by the MAC layer has failed",
+                     MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxRtsFailed))
+    .AddTraceSource ("MacTxDataFailed", 
+                     "The transmission of a data packet by the MAC layer has failed",
+                     MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxDataFailed))
+    .AddTraceSource ("MacTxFinalRtsFailed", 
+                     "The transmission of a RTS has exceeded the maximum number of attempts",
+                     MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxFinalRtsFailed))
+    .AddTraceSource ("MacTxFinalDataFailed", 
+                     "The transmission of a data packet has exceeded the maximum number of attempts",
+                     MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxFinalDataFailed))
+    .AddAttribute("AvgSlrcCoefficient", "The weigh of the slrc count in the slrc avg calculation",
+                  DoubleValue (0.9),
+                  MakeDoubleAccessor (&WifiRemoteStationManager::m_avgSlrcCoefficient),
+                  MakeDoubleChecker<double> ())
     ;
   return tid;
 }
 
-WifiRemoteStation::WifiRemoteStation ()
-  : m_state (BRAND_NEW),
-    m_ssrc (0),
-    m_slrc (0),
-    m_avgSlrcCoefficient(0.9),
-    m_avgSlrc (0)
-{}
-WifiRemoteStation::~WifiRemoteStation ()
+WifiRemoteStationManager::WifiRemoteStationManager ()
 {}
 
-bool
-WifiRemoteStation::IsBrandNew (void) const
+WifiRemoteStationManager::~WifiRemoteStationManager ()
+{
+}
+void 
+WifiRemoteStationManager::DoDispose (void)
 {
-  return m_state == BRAND_NEW;
+  for (StationStates::const_iterator i = m_states.begin (); i != m_states.end (); i++) 
+    {
+      delete (*i);
+    }
+  m_states.clear ();
+  for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) 
+    {
+      delete (*i);
+    }
+  m_stations.clear ();
+}
+void
+WifiRemoteStationManager::SetupPhy (Ptr<WifiPhy> phy)
+{
+  m_defaultTxMode = phy->GetMode (0);
+  Reset ();
 }
 
-bool 
-WifiRemoteStation::IsAssociated (void) const
+uint32_t 
+WifiRemoteStationManager::GetMaxSsrc (void) const
 {
-  return m_state == GOT_ASSOC_TX_OK;
+  return m_maxSsrc;
+}
+uint32_t 
+WifiRemoteStationManager::GetMaxSlrc (void) const
+{
+  return m_maxSlrc;
+}
+uint32_t 
+WifiRemoteStationManager::GetRtsCtsThreshold (void) const
+{
+  return m_rtsCtsThreshold;
 }
-bool 
-WifiRemoteStation::IsWaitAssocTxOk (void) const
+uint32_t 
+WifiRemoteStationManager::GetFragmentationThreshold (void) const
+{
+  return m_fragmentationThreshold;
+}
+void 
+WifiRemoteStationManager::SetMaxSsrc (uint32_t maxSsrc)
 {
-  return m_state == WAIT_ASSOC_TX_OK;
+  m_maxSsrc = maxSsrc;
+}
+void 
+WifiRemoteStationManager::SetMaxSlrc (uint32_t maxSlrc)
+{
+  m_maxSlrc = maxSlrc;
+}
+void 
+WifiRemoteStationManager::SetRtsCtsThreshold (uint32_t threshold)
+{
+  m_rtsCtsThreshold = threshold;
 }
 void 
-WifiRemoteStation::RecordWaitAssocTxOk (void)
+WifiRemoteStationManager::SetFragmentationThreshold (uint32_t threshold)
+{
+  m_fragmentationThreshold = threshold;
+} 
+
+void
+WifiRemoteStationManager::Reset (Mac48Address address)
 {
-  m_state = WAIT_ASSOC_TX_OK;
+  NS_ASSERT (!address.IsGroup ());
+  WifiRemoteStationState *state = LookupState (address);
+  state->m_modes.clear ();
+  AddSupportedMode (address, GetDefaultMode ());
 }
-void 
-WifiRemoteStation::RecordGotAssocTxOk (void)
+void
+WifiRemoteStationManager::AddSupportedMode (Mac48Address address, WifiMode mode)
 {
-  m_state = GOT_ASSOC_TX_OK;
+  NS_ASSERT (!address.IsGroup ());
+  WifiRemoteStationState *state = LookupState (address);
+  for (WifiRemoteStationState::SupportedModes::const_iterator i = state->m_modes.begin (); i != state->m_modes.end (); i++)
+    {
+      if ((*i) == mode)
+        {
+          // already in.
+          return;
+        }
+    }
+  state->m_modes.push_back (mode);
 }
-void 
-WifiRemoteStation::RecordGotAssocTxFailed (void)
+bool
+WifiRemoteStationManager::IsBrandNew (Mac48Address address) const
 {
-  m_state = DISASSOC;
+  if (address.IsGroup ())
+    {
+      return false;
+    }
+  return LookupState (address)->m_state == WifiRemoteStationState::BRAND_NEW;
 }
-void 
-WifiRemoteStation::RecordDisassociated (void)
+bool
+WifiRemoteStationManager::IsAssociated (Mac48Address address) const
+{
+  if (address.IsGroup ())
+    {
+      return true;
+    }
+  return LookupState (address)->m_state == WifiRemoteStationState::GOT_ASSOC_TX_OK;
+}
+bool
+WifiRemoteStationManager::IsWaitAssocTxOk (Mac48Address address) const
 {
-  m_state = DISASSOC;
+  if (address.IsGroup ())
+    {
+      return false;
+    }
+  return LookupState (address)->m_state == WifiRemoteStationState::WAIT_ASSOC_TX_OK;
+}
+void
+WifiRemoteStationManager::RecordWaitAssocTxOk (Mac48Address address)
+{
+  NS_ASSERT (!address.IsGroup ());
+  LookupState (address)->m_state = WifiRemoteStationState::WAIT_ASSOC_TX_OK;
 }
-
-void 
-WifiRemoteStation::Reset (void)
+void
+WifiRemoteStationManager::RecordGotAssocTxOk (Mac48Address address)
+{
+  NS_ASSERT (!address.IsGroup ());
+  LookupState (address)->m_state = WifiRemoteStationState::GOT_ASSOC_TX_OK;
+}
+void
+WifiRemoteStationManager::RecordGotAssocTxFailed (Mac48Address address)
 {
-  m_modes.clear ();
-  AddSupportedMode (GetManager ()->GetDefaultMode ());
+  NS_ASSERT (!address.IsGroup ());
+  LookupState (address)->m_state = WifiRemoteStationState::DISASSOC;
 }
-void 
-WifiRemoteStation::AddSupportedMode (WifiMode mode)
+void
+WifiRemoteStationManager::RecordDisassociated (Mac48Address address)
 {
-  if (IsIn (mode))
+  NS_ASSERT (!address.IsGroup ());
+  LookupState (address)->m_state = WifiRemoteStationState::DISASSOC;
+}
+void
+WifiRemoteStationManager::PrepareForQueue (Mac48Address address, const WifiMacHeader *header,
+                                           Ptr<const Packet> packet, uint32_t fullPacketSize)
+{
+  if (IsLowLatency () || address.IsGroup ())
     {
       return;
     }
-  m_modes.push_back (mode);
+  TxModeTag tag = TxModeTag (GetRtsMode (address, header, packet), 
+                             GetDataMode (address, header, packet, fullPacketSize));
+  packet->AddPacketTag (tag);
+}
+WifiMode
+WifiRemoteStationManager::GetDataMode (Mac48Address address, const WifiMacHeader *header,
+                                       Ptr<const Packet> packet, uint32_t fullPacketSize)
+{
+  if (address.IsGroup ())
+    {
+      return GetNonUnicastMode ();
+    }
+  if (!IsLowLatency ())
+    {
+      // Note: removing the packet below is wrong: what happens in case of retransmissions ???
+      TxModeTag tag;
+      bool found;
+      found = ConstCast<Packet> (packet)->RemovePacketTag (tag);
+      NS_ASSERT (found);
+      return tag.GetDataMode ();
+    }
+  return DoGetDataMode (Lookup (address, header), fullPacketSize);
+}
+WifiMode
+WifiRemoteStationManager::GetRtsMode (Mac48Address address, const WifiMacHeader *header,
+                                      Ptr<const Packet> packet)
+{
+  NS_ASSERT (!address.IsGroup ());
+  if (!IsLowLatency ())
+    {
+      TxModeTag tag;
+      bool found;
+      found = ConstCast<Packet> (packet)->RemovePacketTag (tag);
+      NS_ASSERT (found);
+      return tag.GetRtsMode ();
+    }
+  return DoGetRtsMode (Lookup (address, header));
+}
+void
+WifiRemoteStationManager::ReportRtsFailed (Mac48Address address, const WifiMacHeader *header)
+{
+  NS_ASSERT (!address.IsGroup ());
+  WifiRemoteStation *station = Lookup (address, header);
+  station->m_ssrc++;
+  m_macTxRtsFailed (address);
+  DoReportRtsFailed (station);
+}
+void
+WifiRemoteStationManager::ReportDataFailed (Mac48Address address, const WifiMacHeader *header)
+{
+  NS_ASSERT (!address.IsGroup ());
+  WifiRemoteStation *station = Lookup (address, header);
+  station->m_slrc++;
+  m_macTxDataFailed (address);
+  DoReportDataFailed (station);
+}
+void
+WifiRemoteStationManager::ReportRtsOk (Mac48Address address, const WifiMacHeader *header,
+                                       double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+  NS_ASSERT (!address.IsGroup ());
+  WifiRemoteStation *station = Lookup (address, header);
+  station->m_ssrc = 0;
+  DoReportRtsOk (station, ctsSnr, ctsMode, rtsSnr);
+}
+void
+WifiRemoteStationManager::ReportDataOk (Mac48Address address, const WifiMacHeader *header,
+                                        double ackSnr, WifiMode ackMode, double dataSnr)
+{
+  NS_ASSERT (!address.IsGroup ());
+  WifiRemoteStation *station = Lookup (address, header);
+  station->m_avgSlrc = station->m_avgSlrc * m_avgSlrcCoefficient + (double) station->m_slrc * (1 - m_avgSlrcCoefficient);
+  station->m_slrc = 0;
+  DoReportDataOk (station, ackSnr, ackMode, dataSnr);
+}
+void
+WifiRemoteStationManager::ReportFinalRtsFailed (Mac48Address address, const WifiMacHeader *header)
+{
+  NS_ASSERT (!address.IsGroup ());
+  WifiRemoteStation *station = Lookup (address, header);
+  station->m_ssrc = 0;
+  m_macTxFinalRtsFailed (address);
+  DoReportFinalRtsFailed (station);
+}
+void
+WifiRemoteStationManager::ReportFinalDataFailed (Mac48Address address, const WifiMacHeader *header)
+{
+  NS_ASSERT (!address.IsGroup ());
+  WifiRemoteStation *station = Lookup (address, header);
+  station->m_slrc = 0;
+  m_macTxFinalDataFailed (address);
+  DoReportFinalDataFailed (station);
+}
+void
+WifiRemoteStationManager::ReportRxOk (Mac48Address address, const WifiMacHeader *header,
+                                      double rxSnr, WifiMode txMode)
+{
+  if (address.IsGroup ())
+    {
+      return;
+    }
+  WifiRemoteStation *station = Lookup (address, header);
+  DoReportRxOk (station, rxSnr, txMode);
+}
+bool
+WifiRemoteStationManager::NeedRts (Mac48Address address, const WifiMacHeader *header,
+                                   Ptr<const Packet> packet)
+{
+  if (address.IsGroup ())
+    {
+      return false;
+    }
+  bool normally = packet->GetSize () > GetRtsCtsThreshold ();
+  return DoNeedRts (Lookup (address, header), packet, normally);
+}
+bool
+WifiRemoteStationManager::NeedRtsRetransmission (Mac48Address address, const WifiMacHeader *header,
+                                                 Ptr<const Packet> packet)
+{
+  NS_ASSERT (!address.IsGroup ());
+  WifiRemoteStation *station = Lookup (address, header);
+  bool normally = station->m_ssrc < GetMaxSsrc ();
+  return DoNeedRtsRetransmission (station, packet, normally);
+}
+bool
+WifiRemoteStationManager::NeedDataRetransmission (Mac48Address address, const WifiMacHeader *header,
+                                                  Ptr<const Packet> packet)
+{
+  NS_ASSERT (!address.IsGroup ());
+  WifiRemoteStation *station = Lookup (address, header);
+  bool normally = station->m_slrc < GetMaxSlrc ();
+  return DoNeedDataRetransmission (station, packet, normally);
+}
+bool
+WifiRemoteStationManager::NeedFragmentation (Mac48Address address, const WifiMacHeader *header,
+                                             Ptr<const Packet> packet)
+{
+  if (address.IsGroup ())
+    {
+      return false;
+    }
+  WifiRemoteStation *station = Lookup (address, header);
+  bool normally = packet->GetSize () > GetFragmentationThreshold ();
+  return DoNeedFragmentation (station, packet, normally);
+}
+uint32_t
+WifiRemoteStationManager::GetNFragments (Ptr<const Packet> packet)
+{
+  uint32_t nFragments = packet->GetSize () / GetFragmentationThreshold () + 1;
+  return nFragments;
 }
 
-bool
-WifiRemoteStation::IsIn (WifiMode mode) const
+uint32_t
+WifiRemoteStationManager::GetFragmentSize (Mac48Address address, const WifiMacHeader *header,
+                                           Ptr<const Packet> packet, uint32_t fragmentNumber)
 {
-  for (SupportedModes::const_iterator i = m_modes.begin (); i != m_modes.end (); i++)
+  NS_ASSERT (!address.IsGroup ());
+  uint32_t nFragment = GetNFragments (packet);
+  if (fragmentNumber >= nFragment)
+    {
+      return 0;
+    }
+  if (fragmentNumber == nFragment - 1)
+    {
+      uint32_t lastFragmentSize = packet->GetSize () % GetFragmentationThreshold ();
+      return lastFragmentSize;
+    }
+  else
     {
-      if ((*i) == mode)
-        {
-          return true;
-        }
+      return GetFragmentationThreshold ();
     }
-  return false;
+}
+uint32_t
+WifiRemoteStationManager::GetFragmentOffset (Mac48Address address, const WifiMacHeader *header,
+                                             Ptr<const Packet> packet, uint32_t fragmentNumber)
+{
+  NS_ASSERT (!address.IsGroup ());
+  NS_ASSERT (fragmentNumber < GetNFragments (packet));
+  uint32_t fragmentOffset = fragmentNumber * GetFragmentationThreshold ();
+  return fragmentOffset;
 }
-
+bool
+WifiRemoteStationManager::IsLastFragment (Mac48Address address, const WifiMacHeader *header,
+                                          Ptr<const Packet> packet, uint32_t fragmentNumber)
+{
+  NS_ASSERT (!address.IsGroup ());
+  bool isLast = fragmentNumber == (GetNFragments (packet) - 1);
+  return isLast;
+}
 WifiMode
-WifiRemoteStation::GetControlAnswerMode (WifiMode reqMode)
+WifiRemoteStationManager::GetControlAnswerMode (Mac48Address address, WifiMode reqMode)
 {
   /**
    * see ieee 802.11e, section 9.6:
@@ -569,19 +547,16 @@
    * received frame, unless they conflict with the requirement to use 
    * the BSSBasicRateSet parameter.
    */
-  WifiMode mode = GetManager ()->GetDefaultMode ();
-  bool found = false;
+  WifiMode mode = GetDefaultMode ();
 
   // First, search the BSS Basic Rate set
-  for (WifiRemoteStationManager::BasicModesIterator i = GetManager ()->BeginBasicModes (); 
-       i != GetManager ()->EndBasicModes (); i++)
+  for (WifiRemoteStationManager::BasicModesIterator i = BeginBasicModes (); i != EndBasicModes (); i++)
     {
       if (i->GetPhyRate () > mode.GetPhyRate () &&
           i->GetPhyRate () <= reqMode.GetPhyRate () &&
           i->GetModulationType () == reqMode.GetModulationType ())
         {
           mode = *i;
-          found = true;
         }
     }
   // no need to search Mandatory rate set because it is included
@@ -589,212 +564,181 @@
   return mode;
 }
 
-WifiMode 
-WifiRemoteStation::GetCtsMode (WifiMode rtsMode)
+WifiMode
+WifiRemoteStationManager::GetCtsMode (Mac48Address address, WifiMode rtsMode)
 {
-  return GetControlAnswerMode (rtsMode);
+  NS_ASSERT (!address.IsGroup ());
+  return GetControlAnswerMode (address, rtsMode);
 }
-WifiMode 
-WifiRemoteStation::GetAckMode (WifiMode dataMode)
+WifiMode
+WifiRemoteStationManager::GetAckMode (Mac48Address address, WifiMode dataMode)
 {
-  return GetControlAnswerMode (dataMode);
+  NS_ASSERT (!address.IsGroup ());
+  return GetControlAnswerMode (address, dataMode);
 }
 double
-WifiRemoteStation::GetAvgSlrc () const
-{
-  return m_avgSlrc;
-}
-void 
-WifiRemoteStation::SetAddress(Mac48Address address)
-{
-  m_address = address;
-}  
-Mac48Address 
-WifiRemoteStation::GetAddress()
-{
-  return m_address;
-}
-uint32_t 
-WifiRemoteStation::GetNSupportedModes (void) const
-{
-  return m_modes.size ();
-}
-WifiMode 
-WifiRemoteStation::GetSupportedMode (uint32_t i) const
-{
-  NS_ASSERT (i < m_modes.size ());
-  return m_modes[i];
-}
-void 
-WifiRemoteStation::PrepareForQueue (Ptr<const Packet> packet, uint32_t fullPacketSize)
+WifiRemoteStationManager::GetAvgSlrc (Mac48Address address) const
 {
-  if (GetManager ()->IsLowLatency ())
-    {
-      return;
-    }
-  TxModeTag tag = TxModeTag (DoGetRtsMode (), DoGetDataMode (fullPacketSize));
-  packet->AddPacketTag (tag);
-}
-WifiMode 
-WifiRemoteStation::GetDataMode (Ptr<const Packet> packet, uint32_t fullPacketSize)
-{
-  if (GetManager ()->IsLowLatency ())
-    {
-      return DoGetDataMode (fullPacketSize);
-    }
-  TxModeTag tag;
-  bool found;
-  found = ConstCast<Packet> (packet)->RemovePacketTag (tag);
-  NS_ASSERT (found);
-  return tag.GetDataMode ();
-}
-WifiMode 
-WifiRemoteStation::GetRtsMode (Ptr<const Packet> packet)
-{
-  if (GetManager ()->IsLowLatency ())
-    {
-      return DoGetRtsMode ();
-    }
-  TxModeTag tag;
-  bool found;
-  found = ConstCast<Packet> (packet)->RemovePacketTag (tag);
-  NS_ASSERT (found);
-  return tag.GetRtsMode ();
+  NS_FATAL_ERROR ("XXX");
+  NS_ASSERT (!address.IsGroup ());
+  WifiRemoteStation *station = Lookup (address, (uint8_t)0);
+  return station->m_avgSlrc;
 }
 
-bool
-WifiRemoteStation::NeedRts (Ptr<const Packet> packet)
-{
-  if (packet->GetSize () > GetManager ()->GetRtsCtsThreshold ()) 
-    {
-      return true;
-    } 
-  else 
-    {
-      return false;
-    }
-}
-bool
-WifiRemoteStation::NeedRtsRetransmission (Ptr<const Packet> packet)
-{
-  return (m_ssrc < GetManager ()->GetMaxSsrc ());
-}
-
-bool
-WifiRemoteStation::NeedDataRetransmission (Ptr<const Packet> packet)
-{
-  return (m_slrc < GetManager ()->GetMaxSlrc ());
-}
-
-bool
-WifiRemoteStation::NeedFragmentation (Ptr<const Packet> packet)
+WifiRemoteStationState *
+WifiRemoteStationManager::LookupState (Mac48Address address) const
 {
-  if (packet->GetSize () > GetManager ()->GetFragmentationThreshold ()) 
-    {
-      return true;
-    } 
-  else 
+  for (StationStates::const_iterator i = m_states.begin (); i != m_states.end (); i++) 
     {
-      return false;
+      if ((*i)->m_address == address)
+        {
+          return (*i);
+        }
     }
+  WifiRemoteStationState *state = new WifiRemoteStationState ();
+  state->m_state = WifiRemoteStationState::BRAND_NEW;
+  state->m_address = address;
+  state->m_modes.push_back (GetDefaultMode ());
+  return state;
 }
-uint32_t
-WifiRemoteStation::GetNFragments (Ptr<const Packet> packet)
+WifiRemoteStation *
+WifiRemoteStationManager::Lookup (Mac48Address address, const WifiMacHeader *header) const
 {
-  uint32_t nFragments = packet->GetSize () / GetManager ()->GetFragmentationThreshold () + 1;
-  return nFragments;
-}
-
-uint32_t
-WifiRemoteStation::GetFragmentSize (Ptr<const Packet> packet, uint32_t fragmentNumber)
-{
-  uint32_t nFragment = GetNFragments (packet);
-  if (fragmentNumber >= nFragment)
+  uint8_t tid;
+  if (header->IsQosData ())
     {
-      return 0;
-    }
-  if (fragmentNumber == nFragment - 1)
-    {
-      uint32_t lastFragmentSize = packet->GetSize () % GetManager ()->GetFragmentationThreshold ();
-      return lastFragmentSize;
+      tid = header->GetQosTid ();
     }
   else
     {
-      return GetManager ()->GetFragmentationThreshold ();
+      tid = 0;
     }
+  return Lookup (address, tid);
 }
-uint32_t
-WifiRemoteStation::GetFragmentOffset (Ptr<const Packet> packet, uint32_t fragmentNumber)
+WifiRemoteStation *
+WifiRemoteStationManager::Lookup (Mac48Address address, uint8_t tid) const
 {
-  NS_ASSERT (fragmentNumber < GetNFragments (packet));
-  uint32_t fragmentOffset = fragmentNumber * GetManager ()->GetFragmentationThreshold ();
-  return fragmentOffset;
+  for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) 
+    {
+      if ((*i)->m_tid == tid && 
+          (*i)->m_state->m_address == address)
+        {
+          return (*i);
+        }
+    }
+  WifiRemoteStationState *state = LookupState (address);
+  
+  WifiRemoteStation *station = DoCreateStation ();
+  station->m_state = state;
+  station->m_ssrc = 0;
+  station->m_slrc = 0;
+  station->m_avgSlrc = 0;
+  // XXX
+  const_cast<WifiRemoteStationManager *> (this)->m_stations.push_back (station);
+  return station;
+  
 }
 
-bool
-WifiRemoteStation::IsLastFragment (Ptr<const Packet> packet, uint32_t fragmentNumber) 
+WifiMode 
+WifiRemoteStationManager::GetDefaultMode (void) const
+{
+  return m_defaultTxMode;
+}
+void
+WifiRemoteStationManager::Reset (void)
 {
-  if (fragmentNumber == (GetNFragments (packet) - 1)) 
+  for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++)
+    {
+      delete (*i);
+    }
+  m_stations.clear ();
+  m_basicModes.clear ();
+  m_basicModes.push_back (m_defaultTxMode);
+  NS_ASSERT (m_defaultTxMode.IsMandatory ());
+}
+void 
+WifiRemoteStationManager::AddBasicMode (WifiMode mode)
+{
+  for (uint32_t i = 0; i < GetNBasicModes (); i++)
     {
-      return true;
-    } 
-  else 
+      if (GetBasicMode (i) == mode)
+        {
+          return;
+        }
+    }
+  m_basicModes.push_back (mode);
+}
+uint32_t 
+WifiRemoteStationManager::GetNBasicModes (void) const
+{
+  return m_basicModes.size ();
+}
+WifiMode 
+WifiRemoteStationManager::GetBasicMode (uint32_t i) const
+{
+  NS_ASSERT (i < m_basicModes.size ());
+  return m_basicModes[i];
+}
+WifiRemoteStationManager::BasicModesIterator 
+WifiRemoteStationManager::BeginBasicModes (void) const
+{
+  return m_basicModes.begin ();
+}
+WifiRemoteStationManager::BasicModesIterator 
+WifiRemoteStationManager::EndBasicModes (void) const
+{
+  return m_basicModes.end ();
+}
+
+WifiMode
+WifiRemoteStationManager::GetNonUnicastMode (void) const
+{
+  if (m_nonUnicastMode == WifiMode ())
     {
-      return false;
+      return GetBasicMode(0);
+    }
+  else
+    {
+      return m_nonUnicastMode;
     }
 }
 
-void 
-WifiRemoteStation::ReportRtsFailed (void)
+bool 
+WifiRemoteStationManager::DoNeedRts (WifiRemoteStation *station, 
+                                     Ptr<const Packet> packet, bool normally)
 {
-  m_ssrc++;
-  GetManager ()->NotifyTxRtsFailed (m_address);
-  DoReportRtsFailed ();
+  return normally;
 }
-
-void 
-WifiRemoteStation::ReportDataFailed (void)
+bool 
+WifiRemoteStationManager::DoNeedRtsRetransmission (WifiRemoteStation *station, 
+                                                   Ptr<const Packet> packet, bool normally)
 {
-  m_slrc++;
-  GetManager ()->NotifyTxDataFailed (m_address);
-  DoReportDataFailed ();
+  return normally; 
 }
-
-void 
-WifiRemoteStation::ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
+bool
+WifiRemoteStationManager::DoNeedDataRetransmission (WifiRemoteStation *station, 
+                                                    Ptr<const Packet> packet, bool normally)
 {
-  m_ssrc = 0;
-  DoReportRtsOk (ctsSnr, ctsMode, rtsSnr);
+  return normally;
+}
+bool
+WifiRemoteStationManager::DoNeedFragmentation (WifiRemoteStation *station, 
+                                               Ptr<const Packet> packet, bool normally)
+{
+  return normally;
 }
 
-void 
-WifiRemoteStation::ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+WifiMode 
+WifiRemoteStationManager::GetSupported (const WifiRemoteStation *station, uint32_t i) const
 {
-  m_avgSlrc = m_avgSlrc * m_avgSlrcCoefficient + (double) m_slrc * (1 - m_avgSlrcCoefficient);
-  m_slrc = 0;
-  DoReportDataOk (ackSnr, ackMode, dataSnr);
+  NS_ASSERT (i < GetNSupported (station));
+  return station->m_state->m_modes[i];
 }
-
-void 
-WifiRemoteStation::ReportFinalRtsFailed (void)
+uint32_t 
+WifiRemoteStationManager::GetNSupported (const WifiRemoteStation *station) const
 {
-  m_ssrc = 0;
-  GetManager ()->NotifyTxFinalRtsFailed (m_address);
-  DoReportFinalRtsFailed ();
+  return station->m_state->m_modes.size ();
 }
 
-void 
-WifiRemoteStation::ReportFinalDataFailed (void)
-{
-  m_slrc = 0;
-  GetManager ()->NotifyTxFinalDataFailed (m_address);
-  DoReportFinalDataFailed ();
-}
 
-void 
-WifiRemoteStation::ReportRxOk (double rxSnr, WifiMode txMode)
-{
-  DoReportRxOk (rxSnr, txMode);
-}
 } // namespace ns3
-
--- a/src/devices/wifi/wifi-remote-station-manager.h	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/wifi-remote-station-manager.h	Wed Jan 06 16:26:07 2010 +0100
@@ -23,16 +23,17 @@
 #include <vector>
 #include <utility>
 #include "ns3/mac48-address.h"
+#include "ns3/traced-callback.h"
 #include "ns3/packet.h"
 #include "ns3/object.h"
-#include "ns3/traced-value.h"
 #include "wifi-mode.h"
 
 namespace ns3 {
 
 class WifiRemoteStation;
-class NonUnicastWifiRemoteStation;
+class WifiRemoteStationState;
 class WifiPhy;
+class WifiMacHeader;
 
 /**
  * \brief hold a list of per-remote-station state.
@@ -78,112 +79,14 @@
   BasicModesIterator BeginBasicModes (void) const;
   BasicModesIterator EndBasicModes (void) const;
 
-  bool IsLowLatency (void) const;
-
   WifiMode GetNonUnicastMode (void) const;
 
-  WifiRemoteStation *Lookup (Mac48Address address);
-  WifiRemoteStation *LookupNonUnicast (void);
-protected:
-  friend class WifiRemoteStation;
-  virtual void DoDispose (void);
-private:
-  typedef std::vector <WifiRemoteStation *> Stations;
-  virtual class WifiRemoteStation *CreateStation (void) = 0;
-  Stations m_stations;
-  WifiMode m_defaultTxMode;
-  NonUnicastWifiRemoteStation *m_nonUnicast;
-  BasicModes m_basicModes;
-  bool m_isLowLatency;
-  uint32_t m_maxSsrc;
-  uint32_t m_maxSlrc;
-  uint32_t m_rtsCtsThreshold;
-  uint32_t m_fragmentationThreshold;
-  WifiMode m_nonUnicastMode;
-
-
-  /**
-   * Public method used to fire a MacTxRtsFailed trace.
-   * Implemented for encapsulation purposes.
-   */
-  void NotifyTxRtsFailed (Mac48Address address);  
-
-  /**
-   * Public method used to fire a MacTxDataFailed trace.
-   * Implemented for encapsulation purposes. 
-   */
-  void NotifyTxDataFailed (Mac48Address address);  
-
-  /**
-   * Public method used to fire a MacTxFinalRtsFailed trace.
-   * Implemented for encapsulation purposes.
-   */
-  void NotifyTxFinalRtsFailed (Mac48Address address);  
-
-  /**
-   * Public method used to fire a MacTxFinalDataFailed trace.
-   * Implemented for encapsulation purposes. 
-   */
-  void NotifyTxFinalDataFailed (Mac48Address address);    
-
-
-  /**
-   * The trace source fired when the transmission of a RTS has failed
-   *
-   * \see class CallBackTraceSource
-   */
-  TracedCallback<Mac48Address> m_macTxRtsFailed;
-
-  /**
-   * The trace source fired when the transmission of a data packet has failed 
-   *
-   * \see class CallBackTraceSource
-   */
-  TracedCallback<Mac48Address> m_macTxDataFailed;
-
-  /**
-   * The trace source fired when the transmission of a RTS has
-   * exceeded the maximum number of attempts
-   *
-   * \see class CallBackTraceSource
-   */
-  TracedCallback<Mac48Address> m_macTxFinalRtsFailed;
-
-  /**
-   * The trace source fired when the transmission of a data packet has
-   * exceeded the maximum number of attempts
-   *
-   * \see class CallBackTraceSource
-   */
-  TracedCallback<Mac48Address> m_macTxFinalDataFailed;
-
-};
-
-} // namespace ns3
-
-namespace ns3 {
-
-/**
- * \brief hold per-remote-station state.
- *
- * The state in this class is used to keep track
- * of association status if we are in an infrastructure
- * network and to perform the selection of tx parameters
- * on a per-packet basis.
- */
-class WifiRemoteStation {
-public:
-  
-  static TypeId GetTypeId (void);
-  
-  WifiRemoteStation ();
-  virtual ~WifiRemoteStation ();
 
   /**
    * Invoked in an AP upon disassociation of a
    * specific STA.
    */
-  void Reset (void);
+  void Reset (Mac48Address address);
   /**
    * Invoked in a STA or AP to store the set of 
    * modes supported by a destination which is
@@ -191,15 +94,15 @@
    * The set of supported modes includes
    * the BSSBasicRateSet.
    */
-  void AddSupportedMode (WifiMode mode);
+  void AddSupportedMode (Mac48Address address, WifiMode mode);
 
-  bool IsBrandNew (void) const;
-  bool IsAssociated (void) const;
-  bool IsWaitAssocTxOk (void) const;
-  void RecordWaitAssocTxOk (void);
-  void RecordGotAssocTxOk (void);
-  void RecordGotAssocTxFailed (void);
-  void RecordDisassociated (void);
+  bool IsBrandNew (Mac48Address address) const;
+  bool IsAssociated (Mac48Address address) const;
+  bool IsWaitAssocTxOk (Mac48Address address) const;
+  void RecordWaitAssocTxOk (Mac48Address address);
+  void RecordGotAssocTxOk (Mac48Address address);
+  void RecordGotAssocTxFailed (Mac48Address address);
+  void RecordDisassociated (Mac48Address address);
 
   /**
    * \param packet the packet to queue
@@ -210,49 +113,54 @@
    * is set to false, in which case, the tx parameters of the packet are calculated and stored in
    * the packet as a tag. These tx parameters are later retrieved from GetDadaMode and GetRtsMode.
    */
-  void PrepareForQueue (Ptr<const Packet> packet, uint32_t fullPacketSize);
+  void PrepareForQueue (Mac48Address address, const WifiMacHeader *header,
+                        Ptr<const Packet> packet, uint32_t fullPacketSize);
   /**
    * \param packet the packet to send
    * \param fullPacketSize the size of the packet after its 802.11 MAC header has been added.
    * \returns the transmission mode to use to send this packet
    */
-  WifiMode GetDataMode (Ptr<const Packet> packet, uint32_t fullPacketSize);
+  WifiMode GetDataMode (Mac48Address address, const WifiMacHeader *header,
+                        Ptr<const Packet> packet, uint32_t fullPacketSize);
   /**
    * \param packet the packet to send
    * \returns the transmission mode to use to send the RTS prior to the
    *          transmission of the data packet itself.
    */
-  WifiMode GetRtsMode (Ptr<const Packet> packet);
+  WifiMode GetRtsMode (Mac48Address address, const WifiMacHeader *header,
+                       Ptr<const Packet> packet);
   /**
    * Should be invoked whenever the RtsTimeout associated to a transmission
    * attempt expires.
    */
-  void ReportRtsFailed (void);
+  void ReportRtsFailed (Mac48Address address, const WifiMacHeader *header);
   /**
    * Should be invoked whenever the AckTimeout associated to a transmission
    * attempt expires.
    */
-  void ReportDataFailed (void);
+  void ReportDataFailed (Mac48Address address, const WifiMacHeader *header);
   /**
    * Should be invoked whenever we receive the Cts associated to an RTS 
    * we just sent.
    */
-  void ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  void ReportRtsOk (Mac48Address address, const WifiMacHeader *header,
+                    double ctsSnr, WifiMode ctsMode, double rtsSnr);
   /**
    * Should be invoked whenever we receive the Ack associated to a data packet
    * we just sent.
    */
-  void ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
+  void ReportDataOk (Mac48Address address, const WifiMacHeader *header,
+                     double ackSnr, WifiMode ackMode, double dataSnr);
   /**
    * Should be invoked after calling ReportRtsFailed if 
    * NeedRtsRetransmission returns false
    */
-  void ReportFinalRtsFailed (void);
+  void ReportFinalRtsFailed (Mac48Address address, const WifiMacHeader *header);
   /**
    * Should be invoked after calling ReportDataFailed if 
    * NeedDataRetransmission returns false
    */
-  void ReportFinalDataFailed (void);
+  void ReportFinalDataFailed (Mac48Address address, const WifiMacHeader *header);
 
   /**
    * \param rxSnr the snr of the packet received
@@ -260,112 +168,246 @@
    *
    * Should be invoked whenever a packet is successfully received.
    */
-  void ReportRxOk (double rxSnr, WifiMode txMode);
+  void ReportRxOk (Mac48Address address, const WifiMacHeader *header,
+                   double rxSnr, WifiMode txMode);
 
   /**
    * \param packet the packet to send
    * \returns true if we want to use an RTS/CTS handshake for this
    *          packet before sending it, false otherwise.
    */
-  virtual bool NeedRts (Ptr<const Packet> packet);
+  bool NeedRts (Mac48Address address, const WifiMacHeader *header,
+                Ptr<const Packet> packet);
   /**
    * \param packet the packet to send
    * \returns true if we want to restart a failed RTS/CTS 
    *          handshake, false otherwise.
    */
-  virtual bool NeedRtsRetransmission (Ptr<const Packet> packet);
+  bool NeedRtsRetransmission (Mac48Address address, const WifiMacHeader *header,
+                              Ptr<const Packet> packet);
   /**
    * \param packet the packet to send
    * \returns true if we want to resend a packet 
    *          after a failed transmission attempt, false otherwise.
    */
-  virtual bool NeedDataRetransmission (Ptr<const Packet> packet);
+  bool NeedDataRetransmission (Mac48Address address, const WifiMacHeader *header,
+                               Ptr<const Packet> packet);
 
   /**
    * \param packet the packet to send
    * \returns true if this packet should be fragmented, false otherwise.
    */
-  virtual bool NeedFragmentation (Ptr<const Packet> packet);
+  bool NeedFragmentation (Mac48Address address, const WifiMacHeader *header,
+                                  Ptr<const Packet> packet);
   /**
    * \param packet the packet to send
    * \param fragmentNumber the fragment index of the next fragment to send (starts at zero).
    * \returns the size of the corresponding fragment.
    */
-  virtual uint32_t GetFragmentSize (Ptr<const Packet> packet, uint32_t fragmentNumber);
+  uint32_t GetFragmentSize (Mac48Address address, const WifiMacHeader *header,
+                            Ptr<const Packet> packet, uint32_t fragmentNumber);
   /**
    * \param packet the packet to send
    * \param fragmentNumber the fragment index of the next fragment to send (starts at zero).
    * \returns the offset within the original packet where this fragment starts.
    */
-  virtual uint32_t GetFragmentOffset (Ptr<const Packet> packet, uint32_t fragmentNumber);
+  uint32_t GetFragmentOffset (Mac48Address address, const WifiMacHeader *header,
+                              Ptr<const Packet> packet, uint32_t fragmentNumber);
   /**
    * \param packet the packet to send
    * \param fragmentNumber the fragment index of the next fragment to send (starts at zero).
    * \returns true if this is the last fragment, false otherwise.
    */
-  virtual bool IsLastFragment (Ptr<const Packet> packet, uint32_t fragmentNumber);
+  bool IsLastFragment (Mac48Address address, const WifiMacHeader *header,
+                       Ptr<const Packet> packet, uint32_t fragmentNumber);
 
   /**
    * \param rtsMode the transmission mode used to send an RTS we just received
    * \returns the transmission mode to use for the CTS to complete the RTS/CTS
    *          handshake.
    */
-  WifiMode GetCtsMode (WifiMode rtsMode);
+  WifiMode GetCtsMode (Mac48Address address, WifiMode rtsMode);
   /**
    * \param dataMode the transmission mode used to send an ACK we just received
    * \returns the transmission mode to use for the ACK to complete the data/ACK
    *          handshake.
    */
-  WifiMode GetAckMode (WifiMode dataMode);
+  WifiMode GetAckMode (Mac48Address address, WifiMode dataMode);
   /**
    * \return exponentially weighted average SLRC, this is used by Airtime link metric of 802.11s
    */
-  double GetAvgSlrc () const;
-  /** 
-   * set the address of the remote stationt represented by this instance of WifiRemoteStation
-   * 
-   * @param address the MAC address of the remote station
-   */
-  void SetAddress(Mac48Address address);
-  /** 
-   * get the address of the remote stationt represented by this instance of WifiRemoteStation
-   * 
-   * @return the MAC address of the remote station
-   */
-  Mac48Address GetAddress();
+  double GetAvgSlrc (Mac48Address address) const;
+
+protected:
+  virtual void DoDispose (void);
+  // for convenience
+  WifiMode GetSupported (const WifiRemoteStation *station, uint32_t i) const;
+  uint32_t GetNSupported (const WifiRemoteStation *station) const;
 private:
-  virtual Ptr<WifiRemoteStationManager> GetManager (void) const = 0;
-  virtual WifiMode DoGetDataMode (uint32_t size) = 0;
-  virtual WifiMode DoGetRtsMode (void) = 0;
-  virtual void DoReportRtsFailed (void) = 0;
-  virtual void DoReportDataFailed (void) = 0;
-  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr) = 0;
-  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr) = 0;
-  virtual void DoReportFinalRtsFailed (void) = 0;
-  virtual void DoReportFinalDataFailed (void) = 0;
-  virtual void DoReportRxOk (double rxSnr, WifiMode txMode) = 0;
-protected:
-  uint32_t GetNSupportedModes (void) const;
-  WifiMode GetSupportedMode (uint32_t i) const;
-private:
+  /**
+   * \param station the station with which we need to communicate
+   * \param packet the packet to send
+   * \param normally indicates whether the normal 802.11 rts enable mechanism would
+   *        request that the rts is sent or not.
+   * \returns true if we want to use an RTS/CTS handshake for this
+   *          packet before sending it, false otherwise.
+   *
+   * Note: This method is called before a unicast packet is sent on the medium.
+   */
+  virtual bool DoNeedRts (WifiRemoteStation *station, 
+                          Ptr<const Packet> packet, bool normally);
+  /**
+   * \param station the station with which we need to communicate
+   * \param packet the packet to send
+   * \param normally indicates whether the normal 802.11 rts enable mechanism would
+   *        request that the rts is retransmitted or not.
+   * \returns true if we want to restart a failed RTS/CTS 
+   *          handshake, false otherwise.
+   *
+   * Note: This method is called after an rts/cts handshake has been attempted
+   *       and has failed.
+   */
+  virtual bool DoNeedRtsRetransmission (WifiRemoteStation *station, 
+                                        Ptr<const Packet> packet, bool normally);
+  /**
+   * \param station the station with which we need to communicate
+   * \param packet the packet to send
+   * \param normally indicates whether the normal 802.11 data retransmission mechanism
+   *        would request that the data is retransmitted or not.
+   * \returns true if we want to resend a packet 
+   *          after a failed transmission attempt, false otherwise.
+   *
+   * Note: This method is called after a unicast packet transmission has been attempted
+   *       and has failed.
+   */
+  virtual bool DoNeedDataRetransmission (WifiRemoteStation *station, 
+                                         Ptr<const Packet> packet, bool normally);
+
+  /**
+   * \param station the station with which we need to communicate
+   * \param packet the packet to send
+   * \param normally indicates whether the normal 802.11 data fragmentation mechanism
+   *        would request that the data packet is fragmented or not.
+   * \returns true if this packet should be fragmented, false otherwise.
+   *
+   * Note: This method is called before sending a unicast packet.
+   */
+  virtual bool DoNeedFragmentation (WifiRemoteStation *station, 
+                                    Ptr<const Packet> packet, bool normally);
+  /**
+   * \returns whether this manager is a manager designed to work in low-latency
+   *          environments.
+   *
+   * Note: In this context, low vs high latency is defined in <i>IEEE 802.11 Rate Adaptation:
+   * A Practical Approach</i>, by M. Lacage, M.H. Manshaei, and T. Turletti.
+   */
+  virtual bool IsLowLatency (void) const = 0;
+  /**
+   * \return a new station data structure
+   */
+  virtual class WifiRemoteStation *DoCreateStation (void) const = 0;
+  /**
+   * \param station the station with which we need to communicate
+   * \param size size of the packet or fragment we want to send
+   * \returns the transmission mode to use to send a packet to the station
+   *
+   * Note: This method is called before sending a unicast packet or a fragment
+   *       of a unicast packet to decide which transmission mode to use.
+   */
+  virtual WifiMode DoGetDataMode (WifiRemoteStation *station,
+                                  uint32_t size) = 0;
+  /**
+   * \param station the station with which we need to communicate
+   * \returns the transmission mode to use to send an rts to the station
+   *
+   * Note: This method is called before sending an rts to a station
+   *       to decide which transmission mode to use for the rts.
+   */
+  virtual WifiMode DoGetRtsMode (WifiRemoteStation *station) = 0;
+  virtual void DoReportRtsFailed (WifiRemoteStation *station) = 0;
+  virtual void DoReportDataFailed (WifiRemoteStation *station) = 0;
+  virtual void DoReportRtsOk (WifiRemoteStation *station,
+                              double ctsSnr, WifiMode ctsMode, double rtsSnr) = 0;
+  virtual void DoReportDataOk (WifiRemoteStation *station,
+                               double ackSnr, WifiMode ackMode, double dataSnr) = 0;
+  virtual void DoReportFinalRtsFailed (WifiRemoteStation *station) = 0;
+  virtual void DoReportFinalDataFailed (WifiRemoteStation *station) = 0;
+  virtual void DoReportRxOk (WifiRemoteStation *station,
+                             double rxSnr, WifiMode txMode) = 0;
+
+  WifiRemoteStationState *LookupState (Mac48Address address) const;
+  WifiRemoteStation *Lookup (Mac48Address address, const WifiMacHeader *header) const;
+  WifiRemoteStation *Lookup (Mac48Address address, uint8_t tid) const;
+  WifiMode GetControlAnswerMode (Mac48Address address, WifiMode reqMode);
+  uint32_t GetNFragments (Ptr<const Packet> packet);
+
+  typedef std::vector <WifiRemoteStation *> Stations;
+  typedef std::vector <WifiRemoteStationState *> StationStates;
+
+  StationStates m_states;
+  Stations m_stations;
+  WifiMode m_defaultTxMode;
+  BasicModes m_basicModes;
+  bool m_isLowLatency;
+  uint32_t m_maxSsrc;
+  uint32_t m_maxSlrc;
+  uint32_t m_rtsCtsThreshold;
+  uint32_t m_fragmentationThreshold;
+  WifiMode m_nonUnicastMode;
+  double m_avgSlrcCoefficient;
+  /**
+   * The trace source fired when the transmission of a single RTS has failed
+   */
+  TracedCallback<Mac48Address> m_macTxRtsFailed;
+  /**
+   * The trace source fired when the transmission of a single data packet has failed 
+   */
+  TracedCallback<Mac48Address> m_macTxDataFailed;
+  /**
+   * The trace source fired when the transmission of a RTS has
+   * exceeded the maximum number of attempts
+   */
+  TracedCallback<Mac48Address> m_macTxFinalRtsFailed;
+  /**
+   * The trace source fired when the transmission of a data packet has
+   * exceeded the maximum number of attempts
+   */
+  TracedCallback<Mac48Address> m_macTxFinalDataFailed;
+
+};
+
+struct WifiRemoteStationState
+{
   typedef std::vector<WifiMode> SupportedModes;
-  uint32_t GetNFragments (Ptr<const Packet> packet);
-  bool IsIn (WifiMode mode) const;
-  WifiMode GetControlAnswerMode (WifiMode reqMode);
-  enum {
-    BRAND_NEW,
-    DISASSOC,
-    WAIT_ASSOC_TX_OK,
-    GOT_ASSOC_TX_OK
-  } m_state;
+  enum 
+    {
+      BRAND_NEW,
+      DISASSOC,
+      WAIT_ASSOC_TX_OK,
+      GOT_ASSOC_TX_OK
+    } m_state;
   SupportedModes m_modes;
-  TracedValue<uint32_t> m_ssrc;
-  TracedValue<uint32_t> m_slrc;
-  double m_avgSlrcCoefficient;
-  double m_avgSlrc;
   Mac48Address m_address;
 };
 
+/**
+ * \brief hold per-remote-station state.
+ *
+ * The state in this class is used to keep track
+ * of association status if we are in an infrastructure
+ * network and to perform the selection of tx parameters
+ * on a per-packet basis.
+ */
+struct WifiRemoteStation
+{
+  struct WifiRemoteStationState *m_state;
+  uint32_t m_ssrc;
+  uint32_t m_slrc;
+  double m_avgSlrc;
+  uint8_t m_tid;
+};
+
+
 } // namespace ns3 
 
-#endif /* MAC_STATIONS_H */
+#endif /* WIFI_REMOTE_STATION_MANAGER_H */
--- a/src/devices/wifi/wscript	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/devices/wifi/wscript	Wed Jan 06 16:26:07 2010 +0100
@@ -41,12 +41,13 @@
         'arf-wifi-manager.cc',
         'aarf-wifi-manager.cc',
         'ideal-wifi-manager.cc',
+        'constant-rate-wifi-manager.cc',
         'amrr-wifi-manager.cc',
         'onoe-wifi-manager.cc',
         'rraa-wifi-manager.cc',
         'aarfcd-wifi-manager.cc',
         'cara-wifi-manager.cc',
-        'constant-rate-wifi-manager.cc',
+        'minstrel-wifi-manager.cc',
         'wifi-test.cc',
         'qos-tag.cc',
         'qos-utils.cc',
@@ -57,7 +58,6 @@
         'msdu-aggregator.cc',
         'amsdu-subframe-header.cc',
         'msdu-standard-aggregator.cc',
-        'minstrel-wifi-manager.cc',
         'dcf.cc',
         ]
     headers = bld.new_task_gen('ns3header')
@@ -79,11 +79,14 @@
         'wifi-remote-station-manager.h',
         'arf-wifi-manager.h',
         'aarf-wifi-manager.h',
+        'ideal-wifi-manager.h',
         'constant-rate-wifi-manager.h',
-        'ideal-wifi-manager.h',
         'amrr-wifi-manager.h',
         'onoe-wifi-manager.h',
         'rraa-wifi-manager.h',
+        'aarfcd-wifi-manager.h',
+        'cara-wifi-manager.h',
+        'minstrel-wifi-manager.h',
         'wifi-mac.h',
         'adhoc-wifi-mac.h',
         'nqsta-wifi-mac.h',
@@ -108,7 +111,6 @@
         'dcf-manager.h',
         'mac-rx-middle.h', 
         'mac-low.h',
-        'minstrel-wifi-manager.h',
         'dcf.h',
         ]
 
--- a/src/routing/aodv/aodv-routing-protocol.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/routing/aodv/aodv-routing-protocol.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -27,6 +27,7 @@
  */
 #include "aodv-routing-protocol.h"
 #include "ns3/log.h"
+#include "ns3/boolean.h"
 #include "ns3/random-variable.h"
 #include "ns3/inet-socket-address.h"
 #include "ns3/trace-source-accessor.h"
--- a/src/test/ns3wifi/wifi-interference-test-suite.cc	Wed Jan 06 16:25:53 2010 +0100
+++ b/src/test/ns3wifi/wifi-interference-test-suite.cc	Wed Jan 06 16:26:07 2010 +0100
@@ -28,6 +28,7 @@
 #include "ns3/config.h"
 #include "ns3/string.h"
 #include "ns3/uinteger.h"
+#include "ns3/double.h"
 #include "ns3/data-rate.h"
 #include "ns3/inet-socket-address.h"
 #include "ns3/internet-stack-helper.h"