rework MacStations to handle correctly Supported vs Basic rate sets and add IdealMacStations to build
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Tue, 09 Oct 2007 16:02:21 +0200
changeset 1930 ec22299cf6bb
parent 1929 437bba482899
child 1931 a59c53237a83
rework MacStations to handle correctly Supported vs Basic rate sets and add IdealMacStations to build
src/devices/wifi/aarf-mac-stations.cc
src/devices/wifi/aarf-mac-stations.h
src/devices/wifi/arf-mac-stations.cc
src/devices/wifi/arf-mac-stations.h
src/devices/wifi/cr-mac-stations.cc
src/devices/wifi/cr-mac-stations.h
src/devices/wifi/ideal-mac-stations.cc
src/devices/wifi/ideal-mac-stations.h
src/devices/wifi/mac-stations.cc
src/devices/wifi/mac-stations.h
src/devices/wifi/wscript
--- a/src/devices/wifi/aarf-mac-stations.cc	Tue Oct 09 12:42:45 2007 +0200
+++ b/src/devices/wifi/aarf-mac-stations.cc	Tue Oct 09 16:02:21 2007 +0200
@@ -31,19 +31,19 @@
 AarfMacStations::~AarfMacStations ()
 {}
 MacStation *
-AarfMacStations::CreateStation (WifiMode defaultTxMode)
+AarfMacStations::CreateStation (void)
 {
-  return new AarfMacStation (defaultTxMode, 2.0, 60, 2.0);
+  return new AarfMacStation (this, 2.0, 60, 2.0);
 }
 
 
 
 
-AarfMacStation::AarfMacStation (WifiMode defaultTxMode,
+AarfMacStation::AarfMacStation (AarfMacStations *stations,
                                 double successK,
                                 int maxSuccessThreshold,
                                 double timerK)
-  : ArfMacStation (defaultTxMode, 15, 10),
+  : ArfMacStation (stations, 15, 10),
     m_successK (successK),
     m_maxSuccessThreshold (maxSuccessThreshold),
     m_timerK (timerK)
--- a/src/devices/wifi/aarf-mac-stations.h	Tue Oct 09 12:42:45 2007 +0200
+++ b/src/devices/wifi/aarf-mac-stations.h	Tue Oct 09 16:02:21 2007 +0200
@@ -29,13 +29,13 @@
   AarfMacStations (WifiMode defaultTxMode);
   virtual ~AarfMacStations ();
 private:
-  virtual class MacStation *CreateStation (WifiMode defaultTxMode);
+  virtual class MacStation *CreateStation (void);
 };
 
 class AarfMacStation : public ArfMacStation
 {
 public:
-  AarfMacStation (WifiMode defaultTxMode,
+  AarfMacStation (AarfMacStations *stations,
                   double successK,
                   int maxSuccessThreshold,
                   double timerK);
--- a/src/devices/wifi/arf-mac-stations.cc	Tue Oct 09 12:42:45 2007 +0200
+++ b/src/devices/wifi/arf-mac-stations.cc	Tue Oct 09 16:02:21 2007 +0200
@@ -25,10 +25,10 @@
 
 namespace ns3 {
   
-ArfMacStation::ArfMacStation (WifiMode defaultTxMode,
+ArfMacStation::ArfMacStation (ArfMacStations *stations,
                               int minTimerTimeout,
                               int minSuccessThreshold)
-  : MacStation (defaultTxMode)
+  : m_stations (stations)
 {
   m_minTimerTimeout = minTimerTimeout;
   m_minSuccessThreshold = minSuccessThreshold;
@@ -48,7 +48,7 @@
 int 
 ArfMacStation::GetMaxRate (void)
 {
-  return GetNModes ();
+  return GetNSupportedModes ();
 }
 int 
 ArfMacStation::GetMinRate (void)
@@ -162,12 +162,14 @@
 WifiMode
 ArfMacStation::GetDataMode (uint32_t size)
 {
-  return GetMode (m_rate);
+  return GetSupportedMode (m_rate);
 }
 WifiMode
 ArfMacStation::GetRtsMode (void)
 {
-  return GetMode (0);
+  // XXX: we could/should implement the Arf algorithm for
+  // RTS only by picking a single rate within the BasicRateSet.
+  return GetSupportedMode (0);
 }
 
 void ArfMacStation::ReportRecoveryFailure (void)
@@ -200,6 +202,11 @@
   NS_ASSERT (successThreshold >= m_minSuccessThreshold);
   m_successThreshold = successThreshold;
 }
+ArfMacStations *
+ArfMacStation::GetStations (void) const
+{
+  return m_stations;
+}
 
 
 
@@ -211,9 +218,9 @@
 ArfMacStations::~ArfMacStations ()
 {}
 MacStation *
-ArfMacStations::CreateStation (WifiMode defaultTxMode)
+ArfMacStations::CreateStation (void)
 {
-  return new ArfMacStation (defaultTxMode, 15, 10);
+  return new ArfMacStation (this, 15, 10);
 }
 
 } // namespace ns3
--- a/src/devices/wifi/arf-mac-stations.h	Tue Oct 09 12:42:45 2007 +0200
+++ b/src/devices/wifi/arf-mac-stations.h	Tue Oct 09 16:02:21 2007 +0200
@@ -30,14 +30,14 @@
   virtual ~ArfMacStations ();
 
 private:
-  virtual class MacStation *CreateStation (WifiMode defaultTxMode);
+  virtual class MacStation *CreateStation (void);
 };
 
 
 class ArfMacStation : public MacStation
 {
 public:
-  ArfMacStation (WifiMode defaultTxMode,
+  ArfMacStation (ArfMacStations *stations,
                  int minTimerTimeout,
                  int minSuccessThreshold);
   virtual ~ArfMacStation ();
@@ -51,6 +51,8 @@
   virtual WifiMode GetRtsMode (void);
 
 private:
+  virtual ArfMacStations *GetStations (void) const;
+
   int m_timer;
   int m_success;
   int m_failed;
@@ -64,8 +66,11 @@
   
   int m_minTimerTimeout;
   int m_minSuccessThreshold;
+
+  ArfMacStations *m_stations;
   
 private:
+  // overriden by AarfMacStation.
   virtual void ReportRecoveryFailure (void);
   virtual void ReportFailure (void);
 
@@ -76,6 +81,7 @@
   bool NeedNormalFallback (void);
   
 protected:
+  // called by AarfMacStation.
   int GetMinTimerTimeout (void);
   int GetMinSuccessThreshold (void);
   
--- a/src/devices/wifi/cr-mac-stations.cc	Tue Oct 09 12:42:45 2007 +0200
+++ b/src/devices/wifi/cr-mac-stations.cc	Tue Oct 09 16:02:21 2007 +0200
@@ -25,15 +25,12 @@
 
 namespace ns3 {
 
-CrMacStation::CrMacStation (WifiMode dataMode, WifiMode ctlMode)
-  : MacStation (ctlMode),
-    m_dataMode (dataMode),
-    m_ctlMode (ctlMode)
+CrMacStation::CrMacStation (CrMacStations *stations)
+  : m_stations (stations)
 {}
 CrMacStation::~CrMacStation ()
 {}
 
-
 void 
 CrMacStation::ReportRxOk (double rxSnr, WifiMode txMode)
 {}
@@ -52,12 +49,17 @@
 WifiMode 
 CrMacStation::GetDataMode (uint32_t size)
 {
-  return m_dataMode;
+  return m_stations->GetDataMode ();
 }
 WifiMode 
 CrMacStation::GetRtsMode (void)
 {
-  return m_ctlMode;
+  return m_stations->GetCtlMode ();
+}
+CrMacStations *
+CrMacStation::GetStations (void) const
+{
+  return m_stations;
 }
 
 
@@ -70,10 +72,22 @@
 CrMacStations::~CrMacStations ()
 {}
 
+WifiMode 
+CrMacStations::GetDataMode (void) const
+{
+  return m_dataMode;
+}
+WifiMode 
+CrMacStations::GetCtlMode (void) const
+{
+  return m_ctlMode;
+}
+
+
 MacStation *
-CrMacStations::CreateStation (WifiMode defaultMode)
+CrMacStations::CreateStation (void)
 {
-  return new CrMacStation (m_dataMode, m_ctlMode);
+  return new CrMacStation (this);
 }
 
 } // namespace ns3
--- a/src/devices/wifi/cr-mac-stations.h	Tue Oct 09 12:42:45 2007 +0200
+++ b/src/devices/wifi/cr-mac-stations.h	Tue Oct 09 16:02:21 2007 +0200
@@ -26,15 +26,16 @@
 
 namespace ns3 {
 
-class CrMacStations : public MacStations {
+class CrMacStations : public MacStations 
+{
 public:
   CrMacStations (WifiMode dataMode, WifiMode ctlMode);
   virtual ~CrMacStations ();
 
-  uint8_t GetDataMode (void) const;
-  uint8_t GetCtlMode (void) const;
+  WifiMode GetDataMode (void) const;
+  WifiMode GetCtlMode (void) const;
 private:
-  virtual class MacStation *CreateStation (WifiMode defaultMode);
+  virtual class MacStation *CreateStation (void);
 
   WifiMode m_dataMode;
   WifiMode m_ctlMode;
@@ -44,9 +45,12 @@
 class CrMacStation : public MacStation
 {
 public:
-  CrMacStation (WifiMode dataMode, WifiMode ctlMode);
+  CrMacStation (CrMacStations *stations);
   virtual ~CrMacStation ();
 
+  WifiMode GetDataMode (void) const;
+  WifiMode GetCtlMode (void) const;
+
   virtual void ReportRxOk (double rxSnr, WifiMode txMode);
   virtual void ReportRtsFailed (void);
   virtual void ReportDataFailed (void);
@@ -55,8 +59,8 @@
   virtual WifiMode GetDataMode (uint32_t size);
   virtual WifiMode GetRtsMode (void);
 private:
-  WifiMode m_dataMode;
-  WifiMode m_ctlMode;
+  virtual CrMacStations *GetStations (void) const;
+  CrMacStations *m_stations;
 };
 
 } // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/ideal-mac-stations.cc	Tue Oct 09 16:02:21 2007 +0200
@@ -0,0 +1,148 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "ideal-mac-stations.h"
+#include "wifi-phy.h"
+#include <math.h>
+
+#define noIDEAL_DEBUG 1
+
+#ifdef IDEAL_DEBUG
+#include <iostream>
+#  define TRACE(x) \
+std::cout << "IDEAL TRACE " << x << std::endl;
+#else
+#  define TRACE(x)
+#endif
+
+
+namespace ns3 {
+
+IdealMacStations::IdealMacStations (WifiMode defaultTxMode)
+  : MacStations (defaultTxMode)
+{}
+IdealMacStations::~IdealMacStations ()
+{}
+
+MacStation *
+IdealMacStations::CreateStation (void)
+{
+  return new IdealMacStation (this);
+}
+
+double 
+IdealMacStations::GetSnrThreshold (WifiMode mode) const
+{
+  for (Thresholds::const_iterator i = m_thresholds.begin (); i != m_thresholds.end (); i++) 
+    {
+      if (mode == i->second)
+        {
+          return i->first;
+        }
+    }
+  NS_ASSERT (false);
+  return 0.0;
+}
+
+void 
+IdealMacStations::InitializeThresholds (const WifiPhy *phy, double ber)
+{
+  uint8_t nModes = phy->GetNModes ();
+  for (uint8_t i = 0; i < nModes; i++) 
+    {
+      WifiMode mode = phy->GetMode (i);
+      double snr = phy->CalculateSnr (mode, ber);
+      m_thresholds.push_back (std::make_pair (snr,mode));
+    }
+}
+
+IdealMacStation::IdealMacStation (IdealMacStations *stations)
+  : m_stations (stations)
+{}
+IdealMacStation::~IdealMacStation ()
+{}
+void 
+IdealMacStation::ReportRxOk (double rxSnr, WifiMode txMode)
+{}
+void 
+IdealMacStation::ReportRtsFailed (void)
+{}
+void 
+IdealMacStation::ReportDataFailed (void)
+{}
+void 
+IdealMacStation::ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+  TRACE ("got cts for rts snr="<<rtsSnr);
+  m_lastSnr = rtsSnr;
+}
+void 
+IdealMacStation::ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+{
+  TRACE ("got cts for rts snr="<<dataSnr);
+  m_lastSnr = dataSnr;
+}
+WifiMode
+IdealMacStation::GetDataMode (uint32_t size)
+{
+  // 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 mode = m_stations->GetDefaultMode ();
+  for (uint32_t i = 0; i < GetNSupportedModes (); i++)
+    {
+      double threshold = m_stations->GetSnrThreshold (GetSupportedMode (i));
+      if (threshold > maxThreshold && 
+          threshold < m_lastSnr)
+        {
+          maxThreshold = threshold;
+          mode = GetSupportedMode (i);
+        }
+    }
+  return mode;
+}
+WifiMode
+IdealMacStation::GetRtsMode (void)
+{
+  // 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 mode = m_stations->GetDefaultMode ();
+  for (uint32_t i = 0; i < GetNBasicModes (); i++)
+    {
+      double threshold = m_stations->GetSnrThreshold (GetBasicMode (i));
+      if (threshold > maxThreshold && 
+          threshold < m_lastSnr)
+        {
+          maxThreshold = threshold;
+          mode = GetBasicMode (i);
+        }
+    }
+  return mode;
+}
+IdealMacStations *
+IdealMacStation::GetStations (void) const
+{
+  return m_stations;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/ideal-mac-stations.h	Tue Oct 09 16:02:21 2007 +0200
@@ -0,0 +1,75 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef IDEAL_MAC_STATIONS_H
+#define IDEAL_MAC_STATIONS_H
+
+#include <stdint.h>
+#include <vector>
+#include "mac-stations.h"
+#include "wifi-mode.h"
+
+namespace ns3 {
+
+class WifiPhy;
+
+class IdealMacStations : public MacStations {
+public:
+  IdealMacStations (WifiMode defaultTxMode);
+  virtual ~IdealMacStations ();
+  WifiMode GetMode (double snr) const;
+  // return the min snr needed to successfully transmit
+  // data with this mode at the specified ber.
+  double GetSnrThreshold (WifiMode mode) const;
+  void InitializeThresholds (const WifiPhy *phy, double ber);
+private:
+  virtual class MacStation *CreateStation (void);
+
+  typedef std::vector<std::pair<double,WifiMode> > Thresholds;
+
+  Thresholds m_thresholds;
+  double m_minSnr;
+  double m_maxSnr;
+};
+
+class IdealMacStation : public MacStation 
+{
+public:
+  IdealMacStation (IdealMacStations *stations);
+
+  virtual ~IdealMacStation ();
+
+  virtual void ReportRxOk (double rxSnr, WifiMode txMode);
+  virtual void ReportRtsFailed (void);
+  virtual void ReportDataFailed (void);
+  virtual void ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual WifiMode GetDataMode (uint32_t size);
+  virtual WifiMode GetRtsMode (void);
+
+private:
+  virtual IdealMacStations *GetStations (void) const;
+  IdealMacStations *m_stations;
+  double m_lastSnr;
+};
+
+}; // namespace ns3
+
+#endif /* MAC_STA_H */
--- a/src/devices/wifi/mac-stations.cc	Tue Oct 09 12:42:45 2007 +0200
+++ b/src/devices/wifi/mac-stations.cc	Tue Oct 09 16:02:21 2007 +0200
@@ -33,7 +33,7 @@
 class NonUnicastMacStation : public MacStation
 {
 public:
-  NonUnicastMacStation (WifiMode defaultTxMode);
+  NonUnicastMacStation (MacStations *stations);
   virtual void ReportRxOk (double rxSnr, WifiMode txMode);
   virtual void ReportRtsFailed (void);
   virtual void ReportDataFailed (void);
@@ -41,10 +41,13 @@
   virtual void ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
   virtual WifiMode GetDataMode (uint32_t size);
   virtual WifiMode GetRtsMode (void);
+private:
+  virtual MacStations *GetStations (void) const;
+  MacStations *m_stations;
 };
 
-NonUnicastMacStation::NonUnicastMacStation (WifiMode defaultTxMode)
-  : MacStation (defaultTxMode)
+NonUnicastMacStation::NonUnicastMacStation (MacStations *stations)
+  : m_stations (stations)
 {}
 void 
 NonUnicastMacStation::ReportRxOk (double rxSnr, WifiMode txMode)
@@ -74,12 +77,17 @@
 WifiMode 
 NonUnicastMacStation::GetDataMode (uint32_t size)
 {
-  return GetMode (0);
+  return m_stations->GetBasicMode (0);
 }
 WifiMode 
 NonUnicastMacStation::GetRtsMode (void)
 {
-  return GetMode (0);
+  return m_stations->GetBasicMode (0);
+}
+MacStations *
+NonUnicastMacStation::GetStations (void) const
+{
+  return m_stations;
 }
 
 
@@ -88,13 +96,16 @@
 namespace ns3 {
 
 MacStations::MacStations (WifiMode defaultTxMode)
-  : m_nonUnicast (new NonUnicastMacStation (defaultTxMode)),
-    m_defaultTxMode (defaultTxMode)
-{}
+  : m_defaultTxMode (defaultTxMode),
+    m_nonUnicast (new NonUnicastMacStation (this))
+{
+  m_basicModes.push_back (m_defaultTxMode);
+  NS_ASSERT (m_defaultTxMode.IsMandatory ());
+}
 
 MacStations::~MacStations ()
 {
-  for (StationsI i = m_stations.begin (); i != m_stations.end (); i++) 
+  for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) 
     {
       delete (*i).second;
     }
@@ -110,14 +121,14 @@
     {
       return m_nonUnicast;
     }
-  for (StationsI i = m_stations.begin (); i != m_stations.end (); i++) 
+  for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) 
     {
       if ((*i).first == address)
         {
           return (*i).second;
         }
     }
-  MacStation *station = CreateStation (m_defaultTxMode);
+  MacStation *station = CreateStation ();
   m_stations.push_back (std::make_pair (address, station));
   return station;
 }
@@ -128,6 +139,34 @@
   return m_nonUnicast;
 }
 
+WifiMode 
+MacStations::GetDefaultMode (void) const
+{
+  return m_defaultTxMode;
+}
+uint32_t 
+MacStations::GetNBasicModes (void) const
+{
+  return m_basicModes.size ();
+}
+WifiMode 
+MacStations::GetBasicMode (uint32_t i) const
+{
+  NS_ASSERT (i > 0);
+  return m_basicModes[i-1];
+}
+MacStations::BasicModesIterator 
+MacStations::BeginBasicModes (void) const
+{
+  return m_basicModes.begin ();
+}
+MacStations::BasicModesIterator 
+MacStations::EndBasicModes (void) const
+{
+  return m_basicModes.end ();
+}
+
+
 } // namespace ns3
 
 /***************************************************************
@@ -136,17 +175,9 @@
 
 namespace ns3 {
 
-MacStation::WifiRate::WifiRate (WifiMode _mode, bool _isBasic)
-  : mode (_mode), isBasic (_isBasic)
+MacStation::MacStation ()
+  : m_state (DISASSOC)
 {}
-
-MacStation::MacStation (WifiMode txMode)
-  : m_state (DISASSOC),
-    m_defaultTxMode (txMode)
-{
-  NS_ASSERT (m_defaultTxMode.IsMandatory ());
-  ResetModes ();
-}
 MacStation::~MacStation ()
 {}
 
@@ -182,36 +213,27 @@
 }
 
 void 
-MacStation::ResetModes (void)
+MacStation::Reset (void)
 {
-  m_rates.clear ();
-  AddBasicMode (m_defaultTxMode);
+  m_modes.clear ();
+  AddSupportedMode (GetStations ()->GetDefaultMode ());
 }
 void 
-MacStation::AddBasicMode (WifiMode mode)
+MacStation::AddSupportedMode (WifiMode mode)
 {
   if (IsIn (mode))
     {
       return;
     }
-  m_rates.push_back (WifiRate (mode, true));
-}
-void 
-MacStation::AddExtendedMode (WifiMode mode)
-{
-  if (IsIn (mode))
-    {
-      return;
-    }
-  m_rates.push_back (WifiRate (mode, false));
+  m_modes.push_back (mode);
 }
 
 bool
 MacStation::IsIn (WifiMode mode) const
 {
-  for (WifiRates::const_iterator i = m_rates.begin (); i != m_rates.end (); i++)
+  for (SupportedModes::const_iterator i = m_modes.begin (); i != m_modes.end (); i++)
     {
-      if (i->mode == mode)
+      if ((*i) == mode)
         {
           return true;
         }
@@ -242,36 +264,23 @@
    * received frame, unless they conflict with the requirement to use 
    * the BSSBasicRateSet parameter.
    */
-  WifiMode mode = m_defaultTxMode;
+  WifiMode mode = GetStations ()->GetDefaultMode ();
   bool found = false;
 
   // First, search the BSS Basic Rate set
-  for (WifiRates::const_iterator i = m_rates.begin (); i != m_rates.end (); i++)
+  for (MacStations::BasicModesIterator i = GetStations ()->BeginBasicModes (); 
+       i != GetStations ()->EndBasicModes (); i++)
     {
-      if (i->mode.GetPhyRate () > mode.GetPhyRate () &&
-          i->mode.GetPhyRate () <= reqMode.GetPhyRate () &&
-          i->mode.GetModulationType () == reqMode.GetModulationType () &&
-          i->isBasic)
+      if (i->GetPhyRate () > mode.GetPhyRate () &&
+          i->GetPhyRate () <= reqMode.GetPhyRate () &&
+          i->GetModulationType () == reqMode.GetModulationType ())
         {
-          mode = i->mode;
+          mode = *i;
           found = true;
         }
     }
-  if (found)
-    {
-      return mode;
-    }
-  // Then, search the mandatory rates.
-  for (WifiRates::const_iterator i = m_rates.begin (); i != m_rates.end (); i++)
-    {
-      if (i->mode.GetPhyRate () > mode.GetPhyRate () &&
-          i->mode.GetPhyRate () <= reqMode.GetPhyRate () &&
-          i->mode.GetModulationType () == reqMode.GetModulationType () &&
-          i->mode.IsMandatory ())
-        {
-          mode = i->mode;
-        }
-    }
+  // no need to search Mandatory rate set because it is included
+  // within the Basic rate set.
   return mode;
 }
 
@@ -287,15 +296,15 @@
 }
 
 uint32_t 
-MacStation::GetNModes (void) const
+MacStation::GetNSupportedModes (void) const
 {
-  return m_rates.size ();
+  return m_modes.size ();
 }
 WifiMode 
-MacStation::GetMode (uint32_t i) const
+MacStation::GetSupportedMode (uint32_t i) const
 {
   NS_ASSERT (i > 0);
-  return m_rates[i-1].mode;
+  return m_modes[i-1];
 }
 
 
--- a/src/devices/wifi/mac-stations.h	Tue Oct 09 12:42:45 2007 +0200
+++ b/src/devices/wifi/mac-stations.h	Tue Oct 09 16:02:21 2007 +0200
@@ -20,7 +20,7 @@
 #ifndef MAC_STATIONS_H
 #define MAC_STATIONS_H
 
-#include <list>
+#include <vector>
 #include <utility>
 #include "ns3/mac48-address.h"
 #include "wifi-mode.h"
@@ -29,20 +29,41 @@
 
 class MacStation;
 
-class MacStations {
+class MacStations 
+{
+private:
+  typedef std::vector<WifiMode> BasicModes;
 public:
+  typedef BasicModes::const_iterator BasicModesIterator;
+
   MacStations (WifiMode defaultTxMode);
   virtual ~MacStations ();
   
+  // Invoked in a STA upon dis-association
+  // or in an AP upon reboot
+  void Reset (void);
+  // Invoked in a STA upon association to store
+  // the set of rates which belong to the 
+  // BSSBasicRateSet of the associated AP
+  // and which are supported locally.
+  // Invoked in an AP to configure the BSSBasicRateSet
+  void AddBasicMode (WifiMode mode);
+
+  WifiMode GetDefaultMode (void) const;
+  uint32_t GetNBasicModes (void) const;
+  WifiMode GetBasicMode (uint32_t i) const;
+  BasicModesIterator BeginBasicModes (void) const;
+  BasicModesIterator EndBasicModes (void) const;
+
   MacStation *Lookup (Mac48Address address);
   MacStation *LookupNonUnicast (void);
 private:
-  typedef std::list <std::pair<Mac48Address, MacStation *> > Stations;
-  typedef std::list <std::pair<Mac48Address, MacStation *> >::iterator StationsI;
-  virtual class MacStation *CreateStation (WifiMode mode) = 0;
+  typedef std::vector <std::pair<Mac48Address, MacStation *> > Stations;
+  virtual class MacStation *CreateStation (void) = 0;
   Stations m_stations;
+  WifiMode m_defaultTxMode;
   MacStation *m_nonUnicast;
-  WifiMode m_defaultTxMode;
+  BasicModes m_basicModes;
 };
 
 } // namespace ns3
@@ -51,12 +72,18 @@
 
 class MacStation {
 public:
-  MacStation (WifiMode defaultTxMode);
+  MacStation ();
   virtual ~MacStation ();
 
-  void ResetModes (void);
-  void AddBasicMode (WifiMode mode);
-  void AddExtendedMode (WifiMode mode);
+  // Invoked in an AP upon disassociation of a
+  // specific STA.
+  void Reset (void);
+  // Invoked in a STA or AP to store the set of 
+  // modes supported by a destination which is
+  // also supported locally.
+  // The set of supported modes includes
+  // the BSSBasicRateSet.
+  void AddSupportedMode (WifiMode mode);
 
   bool IsAssociated (void) const;
   bool IsWaitAssocTxOk (void) const;
@@ -80,15 +107,13 @@
   WifiMode GetAckMode (WifiMode dataMode);
 
 private:
-  struct WifiRate {
-    WifiRate (WifiMode mode, bool isBasic);
-    WifiMode mode; 
-    bool isBasic;
-  };
-  typedef std::vector<struct WifiRate> WifiRates;
+  typedef std::vector<WifiMode> SupportedModes;
+  virtual MacStations *GetStations (void) const = 0;
 protected:
-  uint32_t GetNModes (void) const;
-  WifiMode GetMode (uint32_t i) const;
+  uint32_t GetNSupportedModes (void) const;
+  uint32_t GetNBasicModes (void) const;
+  WifiMode GetSupportedMode (uint32_t i) const;
+  WifiMode GetBasicMode (uint32_t i) const;
 private:
   bool IsIn (WifiMode mode) const;
   WifiMode GetControlAnswerMode (WifiMode reqMode);
@@ -97,8 +122,7 @@
     WAIT_ASSOC_TX_OK,
     GOT_ASSOC_TX_OK
   } m_state;
-  WifiRates m_rates;
-  WifiMode m_defaultTxMode;
+  SupportedModes m_modes;
 };
 
 } // namespace ns3 
--- a/src/devices/wifi/wscript	Tue Oct 09 12:42:45 2007 +0200
+++ b/src/devices/wifi/wscript	Tue Oct 09 16:02:21 2007 +0200
@@ -22,6 +22,7 @@
         'mac-tx-middle.cc',
         'mac-rx-middle.cc',
         'dca-txop.cc',
+        'ideal-mac-stations.cc',
         ]
     headers = bld.create_obj('ns3header')
     headers.source = [