port wifi model to Attributes
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 01 Mar 2008 21:21:53 +0100
changeset 2524 db72c0e7743e
parent 2523 58182a1561cc
child 2525 50e66705ed7b
port wifi model to Attributes
samples/main-adhoc-wifi.cc
samples/wscript
src/devices/wifi/aarf-wifi-manager.cc
src/devices/wifi/aarf-wifi-manager.h
src/devices/wifi/adhoc-wifi-mac.cc
src/devices/wifi/adhoc-wifi-mac.h
src/devices/wifi/arf-wifi-manager.cc
src/devices/wifi/arf-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/dcf-manager-test.cc
src/devices/wifi/dcf-manager.cc
src/devices/wifi/dcf-manager.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/nqap-wifi-mac.cc
src/devices/wifi/nqap-wifi-mac.h
src/devices/wifi/nqsta-wifi-mac.cc
src/devices/wifi/nqsta-wifi-mac.h
src/devices/wifi/wifi-channel.cc
src/devices/wifi/wifi-channel.h
src/devices/wifi/wifi-helper.cc
src/devices/wifi/wifi-helper.h
src/devices/wifi/wifi-mac-queue.cc
src/devices/wifi/wifi-mac-queue.h
src/devices/wifi/wifi-mac.cc
src/devices/wifi/wifi-mac.h
src/devices/wifi/wifi-mode.cc
src/devices/wifi/wifi-mode.h
src/devices/wifi/wifi-net-device.cc
src/devices/wifi/wifi-net-device.h
src/devices/wifi/wifi-phy.cc
src/devices/wifi/wifi-phy.h
src/devices/wifi/wifi-remote-station-manager.cc
src/devices/wifi/wifi-remote-station-manager.h
src/devices/wifi/wscript
--- a/samples/main-adhoc-wifi.cc	Sat Mar 01 20:41:08 2008 +0100
+++ b/samples/main-adhoc-wifi.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -19,6 +19,9 @@
  */
 
 #include "ns3/wifi-net-device.h"
+#include "ns3/arf-wifi-manager.h"
+#include "ns3/adhoc-wifi-mac.h"
+#include "ns3/wifi-phy.h"
 #include "ns3/wifi-channel.h"
 #include "ns3/simulator.h"
 #include "ns3/callback.h"
@@ -34,50 +37,67 @@
 #include "ns3/command-line.h"
 #include "ns3/gnuplot.h"
 #include "ns3/uinteger.h"
+#include "ns3/string.h"
+#include "ns3/config.h"
+#include "ns3/wifi-helper.h"
+#include "ns3/mobility-helper.h"
+#include "ns3/log.h"
 
 
 #include <iostream>
 
-using namespace ns3;
-static uint32_t g_bytesTotal = 0;
-static GnuplotDataset *g_output = 0;
+NS_LOG_COMPONENT_DEFINE ("Main");
 
-static Ptr<Node>
-CreateAdhocNode (Ptr<WifiChannel> channel,
-                 Vector position, const char *address)
+using namespace ns3;
+
+class Experiment
 {
-  Ptr<Node> node = CreateObject<Node> ();  
-  Ptr<AdhocWifiNetDevice> device = CreateObject<AdhocWifiNetDevice> (node, Mac48Address (address));
-  node->AddDevice (device);
-  device->Attach (channel);
-  Ptr<MobilityModel> mobility = CreateObject<StaticMobilityModel> ();
-  mobility->SetPosition (position);
-  node->AggregateObject (mobility);
-  
-  return node;
+public:
+  Experiment ();
+  Experiment (std::string name);
+  GnuplotDataset Run (const WifiHelper &wifi);
+private:
+  void ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &address);
+  void SetPosition (Ptr<Node> node, Vector position);
+  Vector GetPosition (Ptr<Node> node);
+  void AdvancePosition (Ptr<Node> node);
+  Ptr<Socket> SetupPacketReceive (Ptr<Node> node);
+
+  uint32_t m_bytesTotal;
+  GnuplotDataset m_output;
+};
+
+Experiment::Experiment ()
+  : m_output ()
+{}
+
+Experiment::Experiment (std::string name)
+  : m_output (name)
+{
+  m_output.SetStyle (GnuplotDataset::LINES);
 }
 
-static void
-SetPosition (Ptr<Node> node, Vector position)
+void
+Experiment::SetPosition (Ptr<Node> node, Vector position)
 {
   Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
   mobility->SetPosition (position);
 }
 
-static Vector
-GetPosition (Ptr<Node> node)
+Vector
+Experiment::GetPosition (Ptr<Node> node)
 {
   Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
   return mobility->GetPosition ();
 }
 
-static void 
-AdvancePosition (Ptr<Node> node) 
+void 
+Experiment::AdvancePosition (Ptr<Node> node) 
 {
   Vector pos = GetPosition (node);
-  double mbs = ((g_bytesTotal * 8.0) / 1000000);
-  g_bytesTotal = 0;
-  g_output->Add (pos.x, mbs);
+  double mbs = ((m_bytesTotal * 8.0) / 1000000);
+  m_bytesTotal = 0;
+  m_output.Add (pos.x, mbs);
   pos.x += 1.0;
   if (pos.x >= 210.0) 
     {
@@ -85,63 +105,70 @@
     }
   SetPosition (node, pos);
   //std::cout << "x="<<pos.x << std::endl;
-  Simulator::Schedule (Seconds (1.0), &AdvancePosition, node);
+  Simulator::Schedule (Seconds (1.0), &Experiment::AdvancePosition, this, node);
 }
 
-static void
-ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &address)
+void
+Experiment::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &address)
 {
-  g_bytesTotal += packet->GetSize ();
+  m_bytesTotal += packet->GetSize ();
 }
 
-static Ptr<Socket>
-SetupPacketReceive (Ptr<Node> node, uint16_t port)
+Ptr<Socket>
+Experiment::SetupPacketReceive (Ptr<Node> node)
 {
   TypeId tid = TypeId::LookupByName ("Packet");
   Ptr<SocketFactory> socketFactory = node->GetObject<SocketFactory> (tid);
   Ptr<Socket> sink = socketFactory->CreateSocket ();
   sink->Bind ();
-  sink->SetRecvCallback (MakeCallback (&ReceivePacket));
+  sink->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));
   return sink;
 }
 
-static void
-RunOneExperiment (void)
+GnuplotDataset
+Experiment::Run (const WifiHelper &wifi)
 {
-  g_bytesTotal = 0;
+  m_bytesTotal = 0;
 
-  Ptr<WifiChannel> channel = CreateObject<WifiChannel> ();
+  NodeContainer c;
+  c.Create (2);
 
-  Ptr<Node> a = CreateAdhocNode (channel, 
-                                 Vector (5.0,0.0,0.0),
-                                 "00:00:00:00:00:01");
-  Ptr<Node> b = CreateAdhocNode (channel,
-                                 Vector (0.0, 0.0, 0.0),
-                                 "00:00:00:00:00:02");
+  NetDeviceContainer devices = wifi.Build (c);
+
+  MobilityHelper mobility;
+  Ptr<ListPositionAllocator> positionAlloc = CreateObjectWith<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
+  positionAlloc->Add (Vector (5.0, 0.0, 0.0));
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.SetMobilityModel ("StaticMobilityModel");
+
+  mobility.Layout (c.Begin (), c.End ());
 
   PacketSocketAddress destination = PacketSocketAddress ();
   destination.SetProtocol (1);
   destination.SetSingleDevice (0);
-  destination.SetPhysicalAddress (Mac48Address ("00:00:00:00:00:02"));
+  destination.SetPhysicalAddress (devices.Get (1)->GetAddress ());
   Ptr<Application> app = 
-    CreateObjectWith<OnOffApplication> ("Node", a, 
+    CreateObjectWith<OnOffApplication> ("Node", c.Get (0), 
                                         "Remote", Address (destination),
                                         "Protocol", TypeId::LookupByName ("Packet"),
                                         "OnTime", ConstantVariable (250),
                                         "OffTime", ConstantVariable (0),
                                         "DataRate", DataRate (60000000),
                                         "PacketSize", Uinteger (2000));
-  a->AddApplication (app);
+  c.Get (0)->AddApplication (app);
 
   app->Start (Seconds (0.5));
   app->Stop (Seconds (250.0));
 
-  Simulator::Schedule (Seconds (1.5), &AdvancePosition, b);
-  Ptr<Socket> recvSink = SetupPacketReceive (b, 10);
+  Simulator::Schedule (Seconds (1.5), &Experiment::AdvancePosition, this, c.Get (1));
+  Ptr<Socket> recvSink = SetupPacketReceive (c.Get (1));
 
   Simulator::Run ();
 
   Simulator::Destroy ();
+
+  return m_output;
 }
 
 int main (int argc, char *argv[])
@@ -149,106 +176,101 @@
   Simulator::SetLinkedList ();
 
   // disable fragmentation
-  DefaultValue::Bind ("WifiFragmentationThreshold", "2200");
+  Config::SetDefault ("WifiRemoteStationManager::FragmentationThreshold", String ("2200"));
+  Config::SetDefault ("WifiRemoteStationManager::RtsCtsThreshold", String ("2200"));
+
   CommandLine::Parse (argc, argv);
 
   Gnuplot gnuplot = Gnuplot ("reference-rates.png");
 
-  DefaultValue::Bind ("WifiRtsCtsThreshold", "2200");
+  Experiment experiment;
+  WifiHelper wifi;
+  GnuplotDataset dataset;
+
+  wifi.SetMac ("AdhocWifiMac");
+  wifi.SetPhy ("WifiPhy");
 
-  g_output = new GnuplotDataset ("54mb");
-  g_output->SetStyle (GnuplotDataset::LINES);
-  DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
-  DefaultValue::Bind ("WifiConstantDataRate", "54mb");
-  RunOneExperiment ();
-  gnuplot.AddDataset (*g_output);
-  delete g_output;
+  NS_LOG_DEBUG ("54");
+  experiment = Experiment ("54mb");
+  wifi.SetRemoteStationManager ("ConstantRateWifiManager",
+                                "DataMode", String ("wifia-54mbs"));
+  dataset = experiment.Run (wifi);
+  gnuplot.AddDataset (dataset);
 
-  g_output = new GnuplotDataset ("48mb");
-  g_output->SetStyle (GnuplotDataset::LINES);
-  DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
-  DefaultValue::Bind ("WifiConstantDataRate", "48mb");
-  RunOneExperiment ();
-  gnuplot.AddDataset (*g_output);
-  delete g_output;
+  NS_LOG_DEBUG ("48");
+  experiment = Experiment ("48mb");
+  wifi.SetRemoteStationManager ("ConstantRateWifiManager",
+                                "DataMode", String ("wifia-48mbs"));
+  dataset = experiment.Run (wifi);
+  gnuplot.AddDataset (dataset);
 
-  g_output = new GnuplotDataset ("36mb");
-  g_output->SetStyle (GnuplotDataset::LINES);
-  DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
-  DefaultValue::Bind ("WifiConstantDataRate", "36mb");
-  RunOneExperiment ();
-  gnuplot.AddDataset (*g_output);
-  delete g_output;
+  NS_LOG_DEBUG ("36");
+  experiment = Experiment ("36mb");
+  wifi.SetRemoteStationManager ("ConstantRateWifiManager",
+                                "DataMode", String ("wifia-36mbs"));
+  dataset = experiment.Run (wifi);
+  gnuplot.AddDataset (dataset);
 
-  g_output = new GnuplotDataset ("24mb");
-  g_output->SetStyle (GnuplotDataset::LINES);
-  DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
-  DefaultValue::Bind ("WifiConstantDataRate", "24mb");
-  RunOneExperiment ();
-  gnuplot.AddDataset (*g_output);
-  delete g_output;
+  NS_LOG_DEBUG ("24");
+  experiment = Experiment ("24mb");
+  wifi.SetRemoteStationManager ("ConstantRateWifiManager",
+                                "DataMode", String ("wifia-24mbs"));
+  dataset = experiment.Run (wifi);
+  gnuplot.AddDataset (dataset);
 
-  g_output = new GnuplotDataset ("18mb");
-  g_output->SetStyle (GnuplotDataset::LINES);
-  DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
-  DefaultValue::Bind ("WifiConstantDataRate", "18mb");
-  RunOneExperiment ();
-  gnuplot.AddDataset (*g_output);
-  delete g_output;
+  NS_LOG_DEBUG ("18");
+  experiment = Experiment ("18mb");
+  wifi.SetRemoteStationManager ("ConstantRateWifiManager",
+                                "DataMode", String ("wifia-18mbs"));
+  dataset = experiment.Run (wifi);
+  gnuplot.AddDataset (dataset);
 
-  g_output = new GnuplotDataset ("12mb");
-  g_output->SetStyle (GnuplotDataset::LINES);
-  DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
-  DefaultValue::Bind ("WifiConstantDataRate", "12mb");
-  RunOneExperiment ();
-  gnuplot.AddDataset (*g_output);
-  delete g_output;
+  NS_LOG_DEBUG ("12");
+  experiment = Experiment ("12mb");
+  wifi.SetRemoteStationManager ("ConstantRateWifiManager",
+                                "DataMode", String ("wifia-12mbs"));
+  dataset = experiment.Run (wifi);
+  gnuplot.AddDataset (dataset);
 
-  g_output = new GnuplotDataset ("9mb");
-  g_output->SetStyle (GnuplotDataset::LINES);
-  DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
-  DefaultValue::Bind ("WifiConstantDataRate", "9mb");
-  RunOneExperiment ();
-  gnuplot.AddDataset (*g_output);
-  delete g_output;
+  NS_LOG_DEBUG ("9");
+  experiment = Experiment ("9mb");
+  wifi.SetRemoteStationManager ("ConstantRateWifiManager",
+                                "DataMode", String ("wifia-9mbs"));
+  dataset = experiment.Run (wifi);
+  gnuplot.AddDataset (dataset);
 
-  g_output = new GnuplotDataset ("6mb");
-  g_output->SetStyle (GnuplotDataset::LINES);
-  DefaultValue::Bind ("WifiRateControlAlgorithm", "ConstantRate");
-  DefaultValue::Bind ("WifiConstantDataRate", "6mb");
-  RunOneExperiment ();
-  gnuplot.AddDataset (*g_output);
-  delete g_output;
+  NS_LOG_DEBUG ("6");
+  experiment = Experiment ("6mb");
+  wifi.SetRemoteStationManager ("ConstantRateWifiManager",
+                                "DataMode", String ("wifia-6mbs"));
+  dataset = experiment.Run (wifi);
+  gnuplot.AddDataset (dataset);
 
   gnuplot.GenerateOutput (std::cout);
 
-  gnuplot = Gnuplot ("rate-control.png");
+
 
-  DefaultValue::Bind ("WifiPhyStandard", "holland");
+  gnuplot = Gnuplot ("rate-control.png");
+  Config::SetDefault ("WifiPhy::Standard", String ("holland"));
+
 
-  g_output = new GnuplotDataset ("arf");
-  g_output->SetStyle (GnuplotDataset::LINES);
-  DefaultValue::Bind ("WifiRtsCtsThreshold", "2200");
-  DefaultValue::Bind ("WifiRateControlAlgorithm", "Arf");
-  RunOneExperiment ();
-  gnuplot.AddDataset (*g_output);
-  delete g_output;
+  NS_LOG_DEBUG ("arf");
+  experiment = Experiment ("arf");
+  wifi.SetRemoteStationManager ("ArfWifiManager");
+  dataset = experiment.Run (wifi);
+  gnuplot.AddDataset (dataset);
 
-  g_output = new GnuplotDataset ("aarf");
-  g_output->SetStyle (GnuplotDataset::LINES);
-  DefaultValue::Bind ("WifiRtsCtsThreshold", "2200");
-  DefaultValue::Bind ("WifiRateControlAlgorithm", "Aarf");
-  RunOneExperiment ();
-  gnuplot.AddDataset (*g_output);
-  delete g_output;
+  NS_LOG_DEBUG ("aarf");
+  experiment = Experiment ("aarf");
+  wifi.SetRemoteStationManager ("AarfWifiManager");
+  dataset = experiment.Run (wifi);
+  gnuplot.AddDataset (dataset);
 
-  g_output = new GnuplotDataset ("ideal");
-  g_output->SetStyle (GnuplotDataset::LINES);
-  DefaultValue::Bind ("WifiRtsCtsThreshold", "2200");
-  DefaultValue::Bind ("WifiRateControlAlgorithm", "Ideal");
-  RunOneExperiment ();
-  gnuplot.AddDataset (*g_output);
-  delete g_output;
+  NS_LOG_DEBUG ("ideal");
+  experiment = Experiment ("ideal");
+  wifi.SetRemoteStationManager ("IdealWifiManager");
+  dataset = experiment.Run (wifi);
+  gnuplot.AddDataset (dataset);
 
   gnuplot.GenerateOutput (std::cout);
 
--- a/samples/wscript	Sat Mar 01 20:41:08 2008 +0100
+++ b/samples/wscript	Sat Mar 01 21:21:53 2008 +0100
@@ -39,9 +39,9 @@
                                  ['core', 'simulator', 'mobility', 'wifi'])
     obj.source = 'main-adhoc-wifi.cc'
 
-    obj = bld.create_ns3_program('main-ap-wifi',
-                                 ['core', 'simulator', 'mobility', 'wifi'])
-    obj.source = 'main-ap-wifi.cc'
+#    obj = bld.create_ns3_program('main-ap-wifi',
+#                                 ['core', 'simulator', 'mobility', 'wifi'])
+#    obj.source = 'main-ap-wifi.cc'
     
     obj = bld.create_ns3_program('main-random-walk',
                                  ['core', 'simulator', 'mobility'])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/aarf-wifi-manager.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,116 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004,2005,2006 INRIA
+ *
+ * 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 "aarf-wifi-manager.h"
+
+#include "ns3/double.h"
+#include "ns3/uinteger.h"
+
+#define Min(a,b) ((a<b)?a:b)
+#define Max(a,b) ((a>b)?a:b)
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (AarfWifiManager);
+
+TypeId 
+AarfWifiManager::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("AarfWifiManager")
+    .SetParent<ArfWifiManager> ()
+    .AddConstructor<AarfWifiManager> ()
+    .AddAttribute ("SuccessK", "Multiplication factor for the success threshold in the AARF algorithm.",
+                   Double (2.0),
+                   MakeDoubleAccessor (&AarfWifiManager::m_successK),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TimerK",
+                   "Multiplication factor for the timer threshold in the AARF algorithm.",
+                   Double (2.0),
+                   MakeDoubleAccessor (&AarfWifiManager::m_timerK),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("MaxSuccessThreshold",
+                   "Maximum value of the success threshold in the AARF algorithm.",
+                   Uinteger (60),
+                   MakeUintegerAccessor (&AarfWifiManager::m_maxSuccessThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MinTimerThreshold",
+                   "The minimum value for the 'timer' threshold in the AARF algorithm.",
+                   Uinteger (15),
+                   MakeUintegerAccessor (&AarfWifiManager::m_minTimerThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MinSuccessThreshold",
+                   "The minimum value for the success threshold in the AARF algorithm.",
+                   Uinteger (10),
+                   MakeUintegerAccessor (&AarfWifiManager::m_minSuccessThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+  return tid;
+}
+
+AarfWifiManager::AarfWifiManager ()
+{}
+AarfWifiManager::~AarfWifiManager ()
+{}
+WifiRemoteStation *
+AarfWifiManager::CreateStation (void)
+{
+  return new AarfWifiRemoteStation (this, m_minTimerThreshold,
+                                    m_minSuccessThreshold,
+                                    m_successK,
+                                    m_maxSuccessThreshold,
+                                    m_timerK);
+}
+
+
+
+
+AarfWifiRemoteStation::AarfWifiRemoteStation (Ptr<AarfWifiManager> stations,
+                                              uint32_t minTimerThreshold,
+                                              uint32_t minSuccessThreshold,
+                                              double successK,
+                                              uint32_t maxSuccessThreshold,
+                                              double timerK)
+  : ArfWifiRemoteStation (stations, minTimerThreshold, minSuccessThreshold),
+    m_successK (successK),
+    m_maxSuccessThreshold (maxSuccessThreshold),
+    m_timerK (timerK)
+{}
+
+
+AarfWifiRemoteStation::~AarfWifiRemoteStation ()
+{}
+
+void 
+AarfWifiRemoteStation::ReportRecoveryFailure (void)
+{
+  SetSuccessThreshold ((int)(Min (GetSuccessThreshold () * m_successK,
+                                  m_maxSuccessThreshold)));
+  SetTimerTimeout ((int)(Max (GetMinTimerTimeout (),
+                              GetSuccessThreshold () * m_timerK)));
+}
+
+void 
+AarfWifiRemoteStation::ReportFailure (void)
+{
+  SetTimerTimeout (GetMinTimerTimeout ());
+  SetSuccessThreshold (GetMinSuccessThreshold ());
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/aarf-wifi-manager.h	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,73 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * 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 AARF_MAC_STATIONS_H
+#define AARF_MAC_STATIONS_H
+
+#include "arf-wifi-manager.h"
+
+namespace ns3 {
+
+/**
+ * \brief AARF Rate control algorithm
+ *
+ * This class implements the AARF rate control algorithm which
+ * was initially described in <i>IEEE 802.11 Rate Adaptation:
+ * A Practical Approach</i>, by M. Lacage, M.H. Manshaei, and 
+ * T. Turletti.
+ */
+class AarfWifiManager : public ArfWifiManager 
+{
+public:
+  static TypeId GetTypeId (void);
+  AarfWifiManager ();
+  virtual ~AarfWifiManager ();
+private:
+  virtual class WifiRemoteStation *CreateStation (void);
+  uint32_t m_minTimerThreshold;
+  uint32_t m_minSuccessThreshold;
+  double m_successK;
+  uint32_t m_maxSuccessThreshold;
+  double m_timerK;
+};
+
+class AarfWifiRemoteStation : public ArfWifiRemoteStation
+{
+public:
+  AarfWifiRemoteStation (Ptr<AarfWifiManager> stations,
+                         uint32_t minTimerThreshold,
+                         uint32_t minSuccessThreshold,
+                         double successK,
+                         uint32_t maxSuccessThreshold,
+                         double timerK);
+  virtual ~AarfWifiRemoteStation ();
+
+private:
+  virtual void ReportRecoveryFailure (void);
+  virtual void ReportFailure (void);
+
+  double m_successK;
+  uint32_t m_maxSuccessThreshold;
+  double m_timerK;
+};
+
+} // namespace ns3
+
+
+#endif /* AARF_MAC_STATIONS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/adhoc-wifi-mac.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,191 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ *
+ * 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 "adhoc-wifi-mac.h"
+#include "dca-txop.h"
+#include "mac-low.h"
+#include "mac-rx-middle.h"
+#include "wifi-phy.h"
+#include "dcf-manager.h"
+#include "ns3/packet.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("AdhocWifiMac");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (AdhocWifiMac);
+
+TypeId 
+AdhocWifiMac::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("AdhocWifiMac")
+    .SetParent<WifiMac> ()
+    .AddConstructor<AdhocWifiMac> ()
+    ;
+  return tid;
+}
+
+AdhocWifiMac::AdhocWifiMac ()
+{
+  m_rxMiddle = new MacRxMiddle ();
+  m_rxMiddle->SetForwardCallback (MakeCallback (&AdhocWifiMac::ForwardUp, this));
+
+  m_low = new MacLow ();
+  m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle));
+  m_low->SetMac (this);
+
+  m_dcfManager = new DcfManager ();
+  m_dcfManager->SetupLowListener (m_low);
+
+  m_dca = CreateObject<DcaTxop> ();
+  m_dca->SetLow (m_low);
+  m_dca->SetManager (m_dcfManager);
+}
+AdhocWifiMac::~AdhocWifiMac ()
+{}
+
+void
+AdhocWifiMac::DoDispose (void)
+{
+  delete m_rxMiddle;
+  delete m_low;
+  m_rxMiddle = 0;
+  m_low = 0;
+  m_phy = 0;
+  WifiMac::DoDispose ();
+}
+
+void 
+AdhocWifiMac::SetSlot (Time slotTime)
+{
+  m_dcfManager->SetSlot (slotTime);
+  WifiMac::SetSlot (slotTime);
+}
+void 
+AdhocWifiMac::SetSifs (Time sifs)
+{
+  m_dcfManager->SetSifs (sifs);
+  WifiMac::SetSifs (sifs);
+}
+void 
+AdhocWifiMac::SetEifsNoDifs (Time eifsNoDifs)
+{
+  m_dcfManager->SetEifsNoDifs (eifsNoDifs);
+  WifiMac::SetEifsNoDifs (eifsNoDifs);
+}
+
+void 
+AdhocWifiMac::SetWifiPhy (Ptr<WifiPhy> phy)
+{
+  m_phy = phy;
+  m_dcfManager->SetupPhyListener (phy);
+  m_low->SetPhy (phy);
+}
+void 
+AdhocWifiMac::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager)
+{
+  m_stationManager = stationManager;
+  m_dca->SetWifiRemoteStationManager (stationManager);
+  m_low->SetWifiRemoteStationManager (stationManager);
+}
+void 
+AdhocWifiMac::SetForwardUpCallback (Callback<void,Ptr<Packet>, const Mac48Address &> upCallback)
+{
+  m_upCallback = upCallback;
+}
+void 
+AdhocWifiMac::SetLinkUpCallback (Callback<void> linkUp)
+{
+  // an Adhoc network is always UP.
+  linkUp ();
+}
+void 
+AdhocWifiMac::SetLinkDownCallback (Callback<void> linkDown)
+{
+  //XXX
+}
+Mac48Address 
+AdhocWifiMac::GetAddress (void) const
+{
+  return m_address;
+}
+Ssid 
+AdhocWifiMac::GetSsid (void) const
+{
+  return m_ssid;
+}
+Mac48Address 
+AdhocWifiMac::GetBssid (void) const
+{
+  // XXX the bssid should be generated by the procedure
+  // described in ieee802.11 section 11.1.3
+  return Mac48Address::GetBroadcast ();
+}
+void 
+AdhocWifiMac::SetAddress (Mac48Address address)
+{
+  m_address = address;
+}
+void 
+AdhocWifiMac::SetSsid (Ssid ssid)
+{
+  // XXX: here, we should start a special adhoc network
+  m_ssid = ssid;
+}
+
+void 
+AdhocWifiMac::Enqueue (Ptr<const Packet> packet, Mac48Address to)
+{
+  NS_LOG_DEBUG ("enqueue size="<<packet->GetSize ()<<", to="<<to);
+  WifiMacHeader hdr;
+  hdr.SetType (WIFI_MAC_DATA);
+  hdr.SetAddr1 (to);
+  hdr.SetAddr2 (GetAddress ());
+  hdr.SetAddr3 (GetBssid ());
+  hdr.SetDsNotFrom ();
+  hdr.SetDsNotTo ();
+
+  WifiRemoteStation *destination = m_stationManager->Lookup (to);
+  if (destination->IsBrandNew ())
+    {
+      // in adhoc mode, we assume that every destination
+      // supports all the rates we support.
+      for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+        {
+          destination->AddSupportedMode (m_phy->GetMode (i));
+        }
+      destination->RecordDisassociated ();
+    }
+
+  m_dca->Queue (packet, hdr);
+}
+
+void 
+AdhocWifiMac::ForwardUp (Ptr<Packet> packet, WifiMacHeader const *hdr)
+{
+  NS_LOG_DEBUG ("received size="<<packet->GetSize ()<<", from="<<hdr->GetAddr2 ());
+  if (hdr->GetAddr1 ().IsBroadcast () || hdr->GetAddr1 () == GetAddress ())
+    {
+      m_upCallback (packet, hdr->GetAddr2 ());
+    }
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/adhoc-wifi-mac.h	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,89 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ *
+ * 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 ADHOC_WIFI_MAC_H
+#define ADHOC_WIFI_MAC_H
+
+#include "ns3/mac48-address.h"
+#include "ns3/callback.h"
+#include "ns3/packet.h"
+#include "wifi-mac.h"
+
+namespace ns3 {
+
+class DcaTxop;
+class Packet;
+class WifiMacHeader;
+class WifiPhy;
+class DcfManager;
+class MacLow;
+class MacRxMiddle;
+
+/**
+ * \brief the Adhoc state machine
+ *
+ * For now, this class is really empty but it should contain
+ * the code for the distributed generation of beacons in an adhoc 
+ * network.
+ */
+class AdhocWifiMac : public WifiMac 
+{
+public:
+  typedef Callback<void, Ptr<Packet>, const Mac48Address &> ForwardCallback;
+
+  static TypeId GetTypeId (void);
+
+  AdhocWifiMac ();
+  ~AdhocWifiMac ();
+
+  virtual void SetSlot (Time slotTime);
+  virtual void SetSifs (Time sifs);
+  virtual void SetEifsNoDifs (Time eifsNoDifs);
+  virtual void SetWifiPhy (Ptr<WifiPhy> phy);
+  virtual void SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager);
+  virtual void Enqueue (Ptr<const Packet> packet, Mac48Address to);
+  virtual void SetForwardUpCallback (Callback<void,Ptr<Packet>, const Mac48Address &> upCallback);
+  virtual void SetLinkUpCallback (Callback<void> linkUp);
+  virtual void SetLinkDownCallback (Callback<void> linkDown);
+  virtual Mac48Address GetAddress (void) const;
+  virtual Ssid GetSsid (void) const;
+  virtual Mac48Address GetBssid (void) const;
+  virtual void SetAddress (Mac48Address address);
+  virtual void SetSsid (Ssid ssid);
+
+
+private:
+  virtual void DoDispose (void);
+  /* invoked by the MacLows. */
+  void ForwardUp (Ptr<Packet> packet, WifiMacHeader const*hdr);
+
+  Ptr<DcaTxop> m_dca;
+  Callback<void,Ptr<Packet>,const Mac48Address &> m_upCallback;
+  Ptr<WifiRemoteStationManager> m_stationManager;
+  Ptr<WifiPhy> m_phy;
+  DcfManager *m_dcfManager;
+  MacRxMiddle *m_rxMiddle;
+  MacLow *m_low;
+  Mac48Address m_address;
+  Ssid m_ssid;
+};
+
+} // namespace ns3
+
+#endif /* ADHOC_WIFI_MAC_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/arf-wifi-manager.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,254 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004,2005,2006 INRIA
+ *
+ * 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 "mac-stations.h"
+#include "arf-wifi-manager.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/uinteger.h"
+
+NS_LOG_COMPONENT_DEFINE ("ArfWifiManager");
+
+
+namespace ns3 {
+  
+ArfWifiRemoteStation::ArfWifiRemoteStation (Ptr<ArfWifiManager> stations,
+                                            int minTimerTimeout,
+                                            int minSuccessThreshold)
+  : m_stations (stations)
+{
+  m_minTimerTimeout = minTimerTimeout;
+  m_minSuccessThreshold = minSuccessThreshold;
+  m_successThreshold = m_minSuccessThreshold;
+  m_timerTimeout = m_minTimerTimeout;
+  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::ReportRtsFailed (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::ReportDataFailed (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::ReportRxOk (double rxSnr, WifiMode txMode)
+{}
+void ArfWifiRemoteStation::ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+  NS_LOG_DEBUG ("self="<<this<<" rts ok");
+}
+void ArfWifiRemoteStation::ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+{
+  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::ReportFinalRtsFailed (void)
+{}
+void 
+ArfWifiRemoteStation::ReportFinalDataFailed (void)
+{}
+
+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_minTimerTimeout;
+}
+uint32_t ArfWifiRemoteStation::GetMinSuccessThreshold (void)
+{
+  return m_minSuccessThreshold;
+}
+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_minTimerTimeout);
+  m_timerTimeout = timerTimeout;
+}
+void ArfWifiRemoteStation::SetSuccessThreshold (uint32_t successThreshold)
+{
+  NS_ASSERT (successThreshold >= m_minSuccessThreshold);
+  m_successThreshold = successThreshold;
+}
+Ptr<WifiRemoteStationManager>
+ArfWifiRemoteStation::GetManager (void) const
+{
+  return m_stations;
+}
+
+NS_OBJECT_ENSURE_REGISTERED (ArfWifiManager);
+
+TypeId 
+ArfWifiManager::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ArfWifiManager")
+    .SetParent<WifiRemoteStationManager> ()
+    .AddConstructor<ArfWifiManager> ()
+    .AddAttribute ("TimerThreshold", "The 'timer' threshold in the ARF algorithm.",
+                   Uinteger (15),
+                   MakeUintegerAccessor (&ArfWifiManager::m_timerThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("SuccessThreshold",
+                   "The minimum number of sucessfull transmissions to try a new rate.",
+                   Uinteger (10),
+                   MakeUintegerAccessor (&ArfWifiManager::m_successThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+  return tid;
+}
+
+ArfWifiManager::ArfWifiManager ()
+{}
+ArfWifiManager::~ArfWifiManager ()
+{}
+WifiRemoteStation *
+ArfWifiManager::CreateStation (void)
+{
+  return new ArfWifiRemoteStation (this, m_timerThreshold, m_successThreshold);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/arf-wifi-manager.h	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,117 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * 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 ARF_WIFI_MANAGER_H
+#define ARF_WIFI_MANAGER_H
+
+#include "wifi-remote-station-manager.h"
+
+namespace ns3 {
+
+/**
+ * \brief ARF Rate control algorithm
+ *
+ * This class implements the so-called ARF algorithm which was
+ * initially described in <i>WaveLAN-II: A High-performance wireless 
+ * LAN for the unlicensed band</i>, by A. Kamerman and L. Monteban. in
+ * Bell Lab Technical Journal, pages 118-133, Summer 1997.
+ *
+ * This implementation differs from the initial description in that it
+ * uses a packet-based timer rather than a time-based timer as described 
+ * in XXX (I cannot find back the original paper which described how
+ * the time-based timer could be easily replaced with a packet-based 
+ * timer.)
+ */
+class ArfWifiManager : public WifiRemoteStationManager
+{
+public:
+  static TypeId GetTypeId (void);
+  ArfWifiManager ();
+  virtual ~ArfWifiManager ();
+
+private:
+  virtual class WifiRemoteStation *CreateStation (void);
+  uint32_t m_timerThreshold;
+  uint32_t m_successThreshold;
+};
+
+
+class ArfWifiRemoteStation : public WifiRemoteStation
+{
+public:
+  ArfWifiRemoteStation (Ptr<ArfWifiManager> stations,
+                        int minTimerTimeout,
+                        int minSuccessThreshold);
+  virtual ~ArfWifiRemoteStation ();
+
+  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 void ReportFinalRtsFailed (void);
+  virtual void ReportFinalDataFailed (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;
+  
+  uint32_t m_minTimerTimeout;
+  uint32_t m_minSuccessThreshold;
+
+  Ptr<ArfWifiManager> m_stations;
+  
+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 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/constant-rate-wifi-manager.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,115 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004,2005 INRIA
+ *
+ * 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 "constant-rate-wifi-manager.h"
+
+#include "ns3/string.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+ConstantRateWifiRemoteStation::ConstantRateWifiRemoteStation (Ptr<ConstantRateWifiManager> manager)
+  : m_manager (manager)
+{}
+ConstantRateWifiRemoteStation::~ConstantRateWifiRemoteStation ()
+{}
+
+void 
+ConstantRateWifiRemoteStation::ReportRxOk (double rxSnr, WifiMode txMode)
+{}
+void 
+ConstantRateWifiRemoteStation::ReportRtsFailed (void)
+{}
+void 
+ConstantRateWifiRemoteStation::ReportDataFailed (void)
+{}
+void 
+ConstantRateWifiRemoteStation::ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{}
+void 
+ConstantRateWifiRemoteStation::ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+{}
+void 
+ConstantRateWifiRemoteStation::ReportFinalRtsFailed (void)
+{}
+void 
+ConstantRateWifiRemoteStation::ReportFinalDataFailed (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 
+ConstantRateWifiManager::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ConstantRateWifiManager")
+    .SetParent<WifiRemoteStationManager> ()
+    .AddConstructor<ConstantRateWifiManager> ()
+    .AddAttribute ("DataMode", "XXX",
+                   String ("wifia-6mbs"),
+                   MakeWifiModeAccessor (&ConstantRateWifiManager::m_dataMode),
+                   MakeWifiModeChecker ())
+    .AddAttribute ("ControlMode", "XXX",
+                   String ("wifia-6mbs"),
+                   MakeWifiModeAccessor (&ConstantRateWifiManager::m_ctlMode),
+                   MakeWifiModeChecker ())
+    ;
+  return tid;
+}
+
+ConstantRateWifiManager::ConstantRateWifiManager ()
+{}
+ConstantRateWifiManager::~ConstantRateWifiManager ()
+{}
+
+WifiMode 
+ConstantRateWifiManager::GetDataMode (void) const
+{
+  return m_dataMode;
+}
+WifiMode 
+ConstantRateWifiManager::GetCtlMode (void) const
+{
+  return m_ctlMode;
+}
+
+
+WifiRemoteStation *
+ConstantRateWifiManager::CreateStation (void)
+{
+  return new ConstantRateWifiRemoteStation (this);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/constant-rate-wifi-manager.h	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,77 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * 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 CONSTANT_RATE_WIFI_MANAGER_H
+#define CONSTANT_RATE_WIFI_MANAGER_H
+
+#include <stdint.h>
+
+#include "wifi-remote-station-manager.h"
+
+namespace ns3 {
+
+/**
+ * \brief use constant rates for data and control transmissions
+ *
+ * This class uses always the same transmission rate for every
+ * packet sent.
+ */
+class ConstantRateWifiManager : public WifiRemoteStationManager
+{
+public:
+  static TypeId GetTypeId (void);
+  ConstantRateWifiManager ();
+  virtual ~ConstantRateWifiManager ();
+
+  WifiMode GetDataMode (void) const;
+  WifiMode GetCtlMode (void) const;
+private:
+  virtual class WifiRemoteStation *CreateStation (void);
+
+  WifiMode m_dataMode;
+  WifiMode m_ctlMode;
+};
+
+
+class ConstantRateWifiRemoteStation : public WifiRemoteStation
+{
+public:
+  ConstantRateWifiRemoteStation (Ptr<ConstantRateWifiManager> stations);
+  virtual ~ConstantRateWifiRemoteStation ();
+
+  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 void ReportFinalRtsFailed (void);
+  virtual void ReportFinalDataFailed (void);
+
+private:
+  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
+  virtual WifiMode DoGetDataMode (uint32_t size);
+  virtual WifiMode DoGetRtsMode (void);
+  Ptr<ConstantRateWifiManager> m_manager;
+};
+
+} // namespace ns3
+
+
+
+#endif /* CONSTANT_RATE_WIFI_MANAGER_H */
--- a/src/devices/wifi/dca-txop.cc	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/dca-txop.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -22,26 +22,23 @@
 #include "ns3/packet.h"
 #include "ns3/log.h"
 #include "ns3/simulator.h"
-#include "ns3/net-device.h"
 #include "ns3/node.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
 
 #include "dca-txop.h"
 #include "dcf-manager.h"
-#include "wifi-mac-parameters.h"
 #include "mac-low.h"
 #include "wifi-mac-queue.h"
 #include "mac-tx-middle.h"
 #include "wifi-mac-trailer.h"
-#include "mac-stations.h"
-#include "wifi-phy.h"
+#include "wifi-mac.h"
 #include "random-stream.h"
-#include "ns3/composite-trace-resolver.h"
 
 NS_LOG_COMPONENT_DEFINE ("DcaTxop");
 
 #define MY_DEBUG(x) \
-  NS_LOG_DEBUG (Simulator::Now () << " " << m_low->GetDevice ()->GetNode ()->GetId () << ":" << \
-                m_low->GetDevice ()->GetIfIndex () << " " << x)
+  NS_LOG_DEBUG (Simulator::Now () << " " << m_low->GetMac ()->GetAddress () << " " << x)
 
 
 namespace ns3 {
@@ -97,8 +94,37 @@
   DcaTxop *m_txop;
 };
 
-DcaTxop::DcaTxop (uint32_t minCw, uint32_t maxCw, uint32_t aifsn, DcfManager *manager)
-  : m_manager (manager),
+TypeId 
+DcaTxop::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("DcaTxop")
+    .SetParent<Object> ()
+    .AddConstructor<DcaTxop> ()
+    .AddAttribute ("MinCw", "XXX",
+                   Uinteger (15),
+                   MakeUintegerAccessor (&DcaTxop::SetMinCw,
+                                         &DcaTxop::GetMinCw),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MaxCw", "XXX",
+                   Uinteger (1023),
+                   MakeUintegerAccessor (&DcaTxop::SetMaxCw,
+                                         &DcaTxop::GetMaxCw),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("Aifsn", "XXX",
+                   Uinteger (2),
+                   MakeUintegerAccessor (&DcaTxop::SetAifsn,
+                                         &DcaTxop::GetAifsn),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddTraceSource ("Ssrc", "XXX",
+                     MakeTraceSourceAccessor (&DcaTxop::m_ssrc))
+    .AddTraceSource ("Slrc", "XXX",
+                     MakeTraceSourceAccessor (&DcaTxop::m_slrc))
+    ;
+  return tid;
+}
+
+DcaTxop::DcaTxop ()
+  : m_manager (0),
     m_currentPacket (0),
     m_ssrc (0),
     m_slrc (0)
@@ -106,23 +132,29 @@
 {
   m_transmissionListener = new DcaTxop::TransmissionListener (this);
   m_dcf = new DcaTxop::Dcf (this);
-  m_dcf->SetCwBounds (minCw, maxCw);
-  m_dcf->SetAifsn (aifsn);
-  m_manager->Add (m_dcf);
-  m_queue = new WifiMacQueue ();
+  m_queue = CreateObjectWith<WifiMacQueue> ();
   m_rng = new RealRandomStream ();
+  m_txMiddle = new MacTxMiddle ();
 }
 
 DcaTxop::~DcaTxop ()
 {
   delete m_transmissionListener;
-  delete m_queue;
   delete m_dcf;
   delete m_rng;
+  delete m_txMiddle;
   m_transmissionListener = 0;
   m_queue = 0;
   m_dcf = 0;
   m_rng = 0;
+  m_txMiddle = 0;
+}
+
+void
+DcaTxop::SetManager (DcfManager *manager)
+{
+  m_manager = manager;
+  m_manager->Add (m_dcf);
 }
 
 void 
@@ -131,19 +163,9 @@
   m_low = low;
 }
 void 
-DcaTxop::SetParameters (WifiMacParameters *parameters)
-{
-  m_parameters = parameters;
-}
-void
-DcaTxop::SetStations (MacStations *stations)
+DcaTxop::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> remoteManager)
 {
-  m_stations = stations;
-}
-void 
-DcaTxop::SetTxMiddle (MacTxMiddle *txMiddle)
-{
-  m_txMiddle = txMiddle;
+  m_stationManager = remoteManager;
 }
 void 
 DcaTxop::SetTxOkCallback (TxOk callback)
@@ -166,22 +188,52 @@
 {
   m_queue->SetMaxDelay (delay);
 }
+void 
+DcaTxop::SetMinCw (uint32_t minCw)
+{
+  m_dcf->SetCwMin (minCw);
+}
+void 
+DcaTxop::SetMaxCw (uint32_t maxCw)
+{
+  m_dcf->SetCwMax (maxCw);
+}
+void 
+DcaTxop::SetAifsn (uint32_t aifsn)
+{
+  m_dcf->SetAifsn (aifsn);
+}
+uint32_t 
+DcaTxop::GetMinCw (void) const
+{
+  return m_dcf->GetCwMin ();
+}
+uint32_t 
+DcaTxop::GetMaxCw (void) const
+{
+  return m_dcf->GetCwMax ();
+}
+uint32_t 
+DcaTxop::GetAifsn (void) const
+{
+  return m_dcf->GetAifsn ();
+}
 
 void 
 DcaTxop::Queue (Ptr<const Packet> packet, WifiMacHeader const &hdr)
 {
   WifiMacTrailer fcs;
   uint32_t fullPacketSize = hdr.GetSerializedSize () + packet->GetSize () + fcs.GetSerializedSize ();
-  MacStation *station = m_stations->Lookup (hdr.GetAddr1 ());
+  WifiRemoteStation *station = GetStation (hdr.GetAddr1 ());
   station->PrepareForQueue (packet, fullPacketSize);
   m_queue->Enqueue (packet, hdr);
   StartAccessIfNeeded ();
 }
 
-MacStation *
+WifiRemoteStation *
 DcaTxop::GetStation (Mac48Address ad) const
 {
-  return m_stations->Lookup (ad);
+  return m_stationManager->Lookup (ad);
 }
 
 void
@@ -213,31 +265,24 @@
   return m_low;
 }
 
-WifiMacParameters *
-DcaTxop::Parameters (void)
-{
-  return m_parameters;
-}
-
-
 bool
 DcaTxop::NeedRts (void)
 {
-  MacStation *station = GetStation (m_currentHdr.GetAddr1 ());
+  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
   return station->NeedRts (m_currentPacket);
 }
 
 bool
 DcaTxop::NeedFragmentation (void)
 {
-  MacStation *station = GetStation (m_currentHdr.GetAddr1 ());
+  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
   return station->NeedFragmentation (m_currentPacket);
 }
 
 uint32_t
 DcaTxop::GetNFragments (void)
 {
-  MacStation *station = GetStation (m_currentHdr.GetAddr1 ());
+  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
   return station->GetNFragments (m_currentPacket);
 }
 void
@@ -249,20 +294,20 @@
 uint32_t
 DcaTxop::GetFragmentSize (void)
 {
-  MacStation *station = GetStation (m_currentHdr.GetAddr1 ());
+  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
   return station->GetFragmentSize (m_currentPacket, m_fragmentNumber);
 }
 bool
 DcaTxop::IsLastFragment (void) 
 {
-  MacStation *station = GetStation (m_currentHdr.GetAddr1 ());
+  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
   return station->IsLastFragment (m_currentPacket, m_fragmentNumber);
 }
 
 uint32_t
 DcaTxop::GetNextFragmentSize (void) 
 {
-  MacStation *station = GetStation (m_currentHdr.GetAddr1 ());
+  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
   return station->GetFragmentSize (m_currentPacket, m_fragmentNumber + 1);
 }
 
@@ -289,13 +334,13 @@
 uint32_t
 DcaTxop::GetMaxSsrc (void) const
 {
-  MacStation *station = GetStation (m_currentHdr.GetAddr1 ());
+  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
   return station->GetMaxSsrc (m_currentPacket);
 }
 uint32_t
 DcaTxop::GetMaxSlrc (void) const
 {
-  MacStation *station = GetStation (m_currentHdr.GetAddr1 ());
+  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
   return station->GetMaxSlrc (m_currentPacket);
 }
 
@@ -409,10 +454,9 @@
 {
   MY_DEBUG ("missed cts");
   m_ssrc++;
-  m_ctstimeoutTrace (m_ssrc);
   if (m_ssrc > GetMaxSsrc ()) 
     {
-      MacStation *station = m_stations->Lookup (m_currentHdr.GetAddr1 ());
+      WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
       station->ReportFinalRtsFailed ();
       // to reset the dcf.
       m_currentPacket = 0;
@@ -456,10 +500,9 @@
 {
   MY_DEBUG ("missed ack");
   m_slrc++;
-  m_acktimeoutTrace (m_slrc);
   if (m_slrc > GetMaxSlrc ()) 
     {
-      MacStation *station = m_stations->Lookup (m_currentHdr.GetAddr1 ());
+      WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
       station->ReportFinalDataFailed ();
       // to reset the dcf.    
       m_currentPacket = 0;
@@ -531,21 +574,4 @@
    */
 }
 
-Ptr<TraceResolver> 
-DcaTxop::GetTraceResolver (void) const
-{
-  Ptr<CompositeTraceResolver> resolver =
-    Create<CompositeTraceResolver> ();
-  resolver->AddSource ("ackTimeout",
-                       TraceDoc ("ACK timeout",
-                                 "uint32_t", "Number of transmission attemps"),
-                       m_acktimeoutTrace);
-  resolver->AddSource ("ctsTimeout",
-                       TraceDoc ("CTS timeout",
-                                 "uint32_t", "Number of transmission attemps"),
-                       m_ctstimeoutTrace);
-  resolver->SetParentResolver (Object::GetTraceResolver ());
-  return resolver;
-}
-
 } // namespace ns3
--- a/src/devices/wifi/dca-txop.h	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/dca-txop.h	Sat Mar 01 21:21:53 2008 +0100
@@ -24,11 +24,12 @@
 #include <stdint.h>
 #include "ns3/callback.h"
 #include "ns3/packet.h"
-#include "ns3/callback-trace-source.h"
 #include "ns3/nstime.h"
 #include "ns3/object.h"
+#include "ns3/traced-value.h"
 #include "wifi-mac-header.h"
 #include "wifi-mode.h"
+#include "wifi-remote-station-manager.h"
 
 namespace ns3 {
 
@@ -65,26 +66,18 @@
 class DcaTxop : public Object
 {
 public:
+  static TypeId GetTypeId (void);
+
   typedef Callback <void, WifiMacHeader const&> TxOk;
   typedef Callback <void, WifiMacHeader const&> TxFailed;
 
-  /**
-   * \param cwMin forwarded to ns3::DcfState constructor
-   * \param cwMax forwarded to ns3::DcfState constructor
-   * \param aifsn forwarded to ns3::DcfState constructor
-   * \param manager the manager which will be responsible
-   *        for controlling access to this DcaTxop.
-   *
-   * Initialized from \valueref{WifiMaxSsrc}, \valueref{WifiMaxSlrc},
-   * \valueref{WifiRtsCtsThreshold}, and, \valueref{WifiFragmentationThreshold}.
-   */
-  DcaTxop (uint32_t cwMin, uint32_t cwMax, uint32_t aifsn, DcfManager *manager);
+  DcaTxop ();
   ~DcaTxop ();
 
   void SetLow (Ptr<MacLow> low);
-  void SetParameters (WifiMacParameters *parameters);
-  void SetStations (MacStations *stations);
-  void SetTxMiddle (MacTxMiddle *txMiddle);
+  void SetManager (DcfManager *manager);
+  void SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> remoteManager);
+
   /**
    * \param callback the callback to invoke when a 
    * packet transmission was completed successfully.
@@ -98,6 +91,12 @@
 
   void SetMaxQueueSize (uint32_t size);
   void SetMaxQueueDelay (Time delay);
+  void SetMinCw (uint32_t minCw);
+  void SetMaxCw (uint32_t maxCw);
+  void SetAifsn (uint32_t aifsn);
+  uint32_t GetMinCw (void) const;
+  uint32_t GetMaxCw (void) const;
+  uint32_t GetAifsn (void) const;
 
   /**
    * \param packet packet to send
@@ -117,9 +116,7 @@
   friend class TransmissionListener;
 
   // Inherited from ns3::Object
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;  
   Ptr<MacLow> Low (void);
-  WifiMacParameters *Parameters (void);
 
   /* dcf notifications forwarded here */
   bool NeedsAccess (void) const;
@@ -141,7 +138,7 @@
   uint32_t GetNFragments (void);
   uint32_t GetNextFragmentSize (void);
   uint32_t GetFragmentSize (void);
-  MacStation *GetStation (Mac48Address to) const;
+  WifiRemoteStation *GetStation (Mac48Address to) const;
   uint32_t GetMaxSsrc (void) const;
   uint32_t GetMaxSlrc (void) const;
   bool IsLastFragment (void);
@@ -152,11 +149,10 @@
   DcfManager *m_manager;
   TxOk m_txOkCallback;
   TxFailed m_txFailedCallback;
-  WifiMacQueue *m_queue;
+  Ptr<WifiMacQueue> m_queue;
   MacTxMiddle *m_txMiddle;
   Ptr <MacLow> m_low;
-  MacStations *m_stations;
-  WifiMacParameters *m_parameters;
+  Ptr<WifiRemoteStationManager> m_stationManager;
   TransmissionListener *m_transmissionListener;
   RandomStream *m_rng;
   
@@ -164,18 +160,9 @@
   bool m_accessOngoing;
   Ptr<const Packet> m_currentPacket;
   WifiMacHeader m_currentHdr;
-  uint32_t m_ssrc;
-  uint32_t m_slrc;
+  TracedValue<uint32_t> m_ssrc;
+  TracedValue<uint32_t> m_slrc;
   uint8_t m_fragmentNumber;
-
-  /* 80211-dca-acktimeout
-   * param1: slrc
-   */
-  CallbackTraceSource<uint32_t> m_acktimeoutTrace;
-  /* 80211-dca-ctstimeout
-   * param1: ssrc
-   */
-  CallbackTraceSource<uint32_t> m_ctstimeoutTrace;
 };
 
 } //namespace ns3
--- a/src/devices/wifi/dcf-manager-test.cc	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/dcf-manager-test.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -51,7 +51,7 @@
 
 
 private:
-  void StartTest (uint64_t slotTime, uint64_t sifs, uint64_t ackTxDuration);
+  void StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs);
   void AddDcfState (uint32_t aifsn);
   void EndTest (void);
   void ExpectInternalCollision (uint64_t time, uint32_t from, uint32_t nSlots);
@@ -171,12 +171,12 @@
 }
 
 void
-DcfManagerTest::StartTest (uint64_t slotTime, uint64_t sifs, uint64_t ackTxDuration)
+DcfManagerTest::StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs)
 {
   m_dcfManager = new DcfManager ();
-  m_dcfManager->SetSlotTime (MicroSeconds (slotTime));
+  m_dcfManager->SetSlot (MicroSeconds (slotTime));
   m_dcfManager->SetSifs (MicroSeconds (sifs));
-  m_dcfManager->SetAckTxDuration (MicroSeconds (ackTxDuration));
+  m_dcfManager->SetEifsNoDifs (MicroSeconds (eifsNoDifsNoSifs+sifs));
 }
 
 void
--- a/src/devices/wifi/dcf-manager.cc	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/dcf-manager.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -6,7 +6,9 @@
 #include <math.h>
 
 #include "dcf-manager.h"
-#include "wifi-mac-parameters.h"
+#include "wifi-phy.h"
+#include "wifi-mac.h"
+#include "mac-low.h"
 
 NS_LOG_COMPONENT_DEFINE ("DcfManager");
 
@@ -22,6 +24,9 @@
 DcfState::DcfState ()
   : m_backoffSlots (0),
     m_backoffStart (Seconds (0.0)),
+    m_cwMin (0),
+    m_cwMax (0),
+    m_cw (0),
     m_accessRequested (false)
 {}
 
@@ -33,14 +38,33 @@
 {
   m_aifsn = aifsn;
 }
-
 void 
-DcfState::SetCwBounds (uint32_t minCw, uint32_t maxCw)
+DcfState::SetCwMin (uint32_t minCw)
 {
   m_cwMin = minCw;
+  ResetCw ();
+}
+void 
+DcfState::SetCwMax (uint32_t maxCw)
+{
   m_cwMax = maxCw;
   ResetCw ();
 }
+uint32_t 
+DcfState::GetAifsn (void) const
+{
+  return m_aifsn;
+}
+uint32_t
+DcfState::GetCwMin (void) const
+{
+  return m_cwMin;
+}
+uint32_t 
+DcfState::GetCwMax (void) const
+{
+  return m_cwMax;
+}
 
 void 
 DcfState::ResetCw (void)
@@ -72,11 +96,6 @@
   m_backoffStart = Simulator::Now ();
 }
 
-uint32_t 
-DcfState::GetAifsn (void) const
-{
-  return m_aifsn;
-}
 uint32_t
 DcfState::GetCw (void) const
 {
@@ -121,6 +140,53 @@
 }
 
 
+/***************************************************************
+ *         Listener for Nav events. Forwards to DcfManager
+ ***************************************************************/
+
+class LowNavListener : public ns3::MacLowNavListener {
+public:
+  LowNavListener (ns3::DcfManager *dcf)
+    : m_dcf (dcf) {}
+  virtual ~LowNavListener () {}
+  virtual void NavStart (Time duration) {
+    m_dcf->NotifyNavStartNow (duration);
+  }
+  virtual void NavReset (Time duration) {
+    m_dcf->NotifyNavResetNow (duration);
+  }
+private:
+  ns3::DcfManager *m_dcf;
+};
+
+/***************************************************************
+ *         Listener for PHY events. Forwards to DcfManager
+ ***************************************************************/
+
+class PhyListener : public ns3::WifiPhyListener {
+public:
+  PhyListener (ns3::DcfManager *dcf)
+    : m_dcf (dcf) {}
+  virtual ~PhyListener () {}
+  virtual void NotifyRxStart (Time duration) {
+    m_dcf->NotifyRxStartNow (duration);
+  }
+  virtual void NotifyRxEndOk (void) {
+    m_dcf->NotifyRxEndOkNow ();
+  }
+  virtual void NotifyRxEndError (void) {
+    m_dcf->NotifyRxEndErrorNow ();
+  }
+  virtual void NotifyTxStart (Time duration) {
+    m_dcf->NotifyTxStartNow (duration);
+  }
+  virtual void NotifyCcaBusyStart (Time duration) {
+    m_dcf->NotifyCcaBusyStartNow (duration);
+  }
+private:
+  ns3::DcfManager *m_dcf;
+};
+
 /****************************************************************
  *      Implement the DCF manager of all DCF state holders
  ****************************************************************/
@@ -138,11 +204,34 @@
     m_lastBusyDuration (MicroSeconds (0)),
     m_rxing (false),
     m_slotTime (Seconds (0.0)),
-    m_sifs (Seconds (0.0))
+    m_sifs (Seconds (0.0)),
+    m_phyListener (0),
+    m_lowListener (0)
 {}
 
+DcfManager::~DcfManager ()
+{
+  delete m_phyListener;
+  delete m_lowListener;
+  m_phyListener = 0;
+  m_lowListener = 0;
+}
+
 void 
-DcfManager::SetSlotTime (Time slotTime)
+DcfManager::SetupPhyListener (Ptr<WifiPhy> phy)
+{
+  m_phyListener = new PhyListener (this);
+  phy->RegisterListener (m_phyListener);
+}
+void 
+DcfManager::SetupLowListener (Ptr<MacLow> low)
+{
+  m_lowListener = new LowNavListener (this);
+  low->RegisterNavListener (m_lowListener);
+}
+
+void 
+DcfManager::SetSlot (Time slotTime)
 {
   m_slotTime = slotTime;
 }
@@ -151,11 +240,10 @@
 {
   m_sifs = sifs;
 }
-
 void 
-DcfManager::SetAckTxDuration (Time ackTxDuration)
+DcfManager::SetEifsNoDifs (Time eifsNoDifs)
 {
-  m_ackTxTime = ackTxDuration;
+  m_eifsNoDifs = eifsNoDifs;
 }
 
 void 
@@ -302,12 +390,15 @@
   Time rxAccessStart;
   if (m_lastRxEnd >= m_lastRxStart) 
     {
-      rxAccessStart = m_lastRxEnd + m_sifs;
+      rxAccessStart = m_lastRxEnd;
       if (!m_lastRxReceivedOk)
         {
-          /* to handle EIFS */
-          rxAccessStart += m_ackTxTime;
-        } 
+          rxAccessStart += m_eifsNoDifs;
+        }
+      else
+        {
+          rxAccessStart += m_sifs;
+        }
     } 
   else 
     {
--- a/src/devices/wifi/dcf-manager.h	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/dcf-manager.h	Sat Mar 01 21:21:53 2008 +0100
@@ -6,6 +6,10 @@
 
 namespace ns3 {
 
+class WifiPhy;
+class WifiMac;
+class MacLow;
+
 /**
  * \brief keep track of the state needed for a single DCF 
  * function.
@@ -29,13 +33,11 @@
    * Calling this method after DcfManager::Add has been called is not recommended.
    */
   void SetAifsn (uint32_t aifsn);
-  /**
-   * \param minCw the minimum value for the CW variable.
-   * \param maxCw the maximum value for the CW variable.
-   *
-   * Calling this method after DcfManager::Add has been called is not recommended.
-   */
-  void SetCwBounds (uint32_t minCw, uint32_t maxCw);
+  void SetCwMin (uint32_t minCw);
+  void SetCwMax (uint32_t maxCw);
+  uint32_t GetAifsn (void) const;
+  uint32_t GetCwMin (void) const;
+  uint32_t GetCwMax (void) const;
   /**
    * Update the value of the CW variable to take into account
    * a transmission success or a transmission abort (stop transmission
@@ -70,7 +72,6 @@
 private:
   friend class DcfManager;
 
-  uint32_t GetAifsn (void) const;
   uint32_t GetBackoffSlots (void) const;
   Time GetBackoffStart (void) const;
   void UpdateBackoffSlotsNow (uint32_t nSlots, Time backoffUpdateBound);
@@ -139,6 +140,10 @@
 {
 public:
   DcfManager ();
+  ~DcfManager ();
+
+  void SetupPhyListener (Ptr<WifiPhy> phy);
+  void SetupLowListener (Ptr<MacLow> low);
 
   /**
    * \param slotTime the duration of a slot.
@@ -146,7 +151,7 @@
    * It is a bad idea to call this method after RequestAccess or
    * one of the Notify methods has been invoked.
    */
-  void SetSlotTime (Time slotTime);
+  void SetSlot (Time slotTime);
   /**
    * \param sifs the duration of a SIFS.
    *
@@ -156,13 +161,12 @@
   void SetSifs (Time sifs);
 
   /**
-   * \param ackTxDuration time to transmit an ACK at the lowest mandatory rate
+   * \param eifsNoDifs the duration of a EIFS minus the duration of DIFS.
    *
-   * This value is used for the calculation of the EIFS duration.
    * It is a bad idea to call this method after RequestAccess or
    * one of the Notify methods has been invoked.
    */
-  void SetAckTxDuration (Time ackTxDuration);
+  void SetEifsNoDifs (Time eifsNoDifs);
 
   /**
    * \param dcf a new DcfState.
@@ -265,10 +269,12 @@
   Time m_lastBusyDuration;
   bool m_rxing;
   bool m_sleeping;
-  Time m_ackTxTime;
+  Time m_eifsNoDifs;
   EventId m_accessTimeout;
   Time m_slotTime;
   Time m_sifs;
+  class PhyListener *m_phyListener;
+  class LowNavListener *m_lowListener;
 };
 
 } // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/ideal-wifi-manager.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,182 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ *
+ * 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-wifi-manager.h"
+#include "wifi-phy.h"
+#include "ns3/assert.h"
+#include "ns3/double.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 {
+
+NS_OBJECT_ENSURE_REGISTERED (IdealWifiManager);
+
+TypeId 
+IdealWifiManager::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("IdealWifiManager")
+    .SetParent<WifiRemoteStationManager> ()
+    .AddConstructor<IdealWifiManager> ()
+    .AddAttribute ("BerThreshold",
+                   "The maximum Bit Error Rate acceptable at any transmission mode",
+                   Double (10e-6),
+                   MakeDoubleAccessor (&IdealWifiManager::m_ber),
+                   MakeDoubleChecker<double> ())
+    ;
+  return tid;
+}
+
+IdealWifiManager::IdealWifiManager ()
+{}
+IdealWifiManager::~IdealWifiManager ()
+{}
+
+void 
+IdealWifiManager::SetupPhy (Ptr<WifiPhy> phy)
+{
+  uint32_t nModes = phy->GetNModes ();
+  for (uint32_t i = 0; i < nModes; i++) 
+    {
+      WifiMode mode = phy->GetMode (i);
+      AddModeSnrThreshold (mode, phy->CalculateSnr (mode, m_ber));
+    }
+  
+  WifiRemoteStationManager::SetupPhy (phy);
+}
+
+WifiRemoteStation *
+IdealWifiManager::CreateStation (void)
+{
+  return new IdealWifiRemoteStation (this);
+}
+
+double 
+IdealWifiManager::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 
+IdealWifiManager::AddModeSnrThreshold (WifiMode mode, double snr)
+{
+  m_thresholds.push_back (std::make_pair (snr,mode));
+}
+
+IdealWifiRemoteStation::IdealWifiRemoteStation (Ptr<IdealWifiManager> manager)
+  : m_manager (manager),
+    m_lastSnr (0.0)
+{}
+IdealWifiRemoteStation::~IdealWifiRemoteStation ()
+{}
+void 
+IdealWifiRemoteStation::ReportRxOk (double rxSnr, WifiMode txMode)
+{}
+void 
+IdealWifiRemoteStation::ReportRtsFailed (void)
+{}
+void 
+IdealWifiRemoteStation::ReportDataFailed (void)
+{}
+void 
+IdealWifiRemoteStation::ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+  TRACE ("got cts for rts snr="<<rtsSnr);
+  m_lastSnr = rtsSnr;
+}
+void 
+IdealWifiRemoteStation::ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+{
+  TRACE ("got cts for rts snr="<<dataSnr);
+  m_lastSnr = dataSnr;
+}
+void 
+IdealWifiRemoteStation::ReportFinalRtsFailed (void)
+{}
+void 
+IdealWifiRemoteStation::ReportFinalDataFailed (void)
+{}
+
+WifiMode
+IdealWifiRemoteStation::DoGetDataMode (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 maxMode = m_manager->GetDefaultMode ();
+  for (uint32_t i = 0; i < GetNSupportedModes (); i++)
+    {
+      WifiMode mode = GetSupportedMode (i);
+      double threshold = m_manager->GetSnrThreshold (mode);
+      if (threshold > maxThreshold && 
+          threshold < m_lastSnr)
+        {
+          maxThreshold = threshold;
+          maxMode = mode;
+        }
+    }
+  return maxMode;
+}
+WifiMode
+IdealWifiRemoteStation::DoGetRtsMode (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 maxMode = m_manager->GetDefaultMode ();
+  for (uint32_t i = 0; i < m_manager->GetNBasicModes (); i++)
+    {
+      WifiMode mode = m_manager->GetBasicMode (i);
+      double threshold = m_manager->GetSnrThreshold (mode);
+      if (threshold > maxThreshold && 
+          threshold < m_lastSnr)
+        {
+          maxThreshold = threshold;
+          maxMode = mode;
+        }
+    }
+  return maxMode;
+}
+Ptr<WifiRemoteStationManager>
+IdealWifiRemoteStation::GetManager (void) const
+{
+  return m_manager;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/ideal-wifi-manager.h	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,95 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ *
+ * 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 "wifi-mode.h"
+#include "wifi-remote-station-manager.h"
+
+namespace ns3 {
+
+/**
+ * \brief Ideal rate control algorithm
+ *
+ * This class implements an 'ideal' rate control algorithm
+ * similar to RBAR in spirit (see <i>A rate-adaptive MAC
+ * protocol for multihop wireless networks</i> by G. Holland,
+ * N. Vaidya, and P. Bahl.): every station keeps track of the
+ * snr of every packet received and sends back this snr to the
+ * original transmitter by an out-of-band mechanism. Each 
+ * transmitter keeps track of the last snr sent back by a receiver
+ * and uses it to pick a transmission mode based on a set
+ * of snr thresholds built from a target ber and transmission 
+ * mode-specific snr/ber curves.
+ */
+class IdealWifiManager : public WifiRemoteStationManager 
+{
+public:
+  static TypeId GetTypeId (void);
+  IdealWifiManager ();
+  virtual ~IdealWifiManager ();
+
+  virtual void SetupPhy (Ptr<WifiPhy> phy);
+
+  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 AddModeSnrThreshold (WifiMode mode, double ber);
+private:
+  virtual class WifiRemoteStation *CreateStation (void);
+
+  typedef std::vector<std::pair<double,WifiMode> > Thresholds;
+
+  double m_ber;
+  Thresholds m_thresholds;
+  double m_minSnr;
+  double m_maxSnr;
+};
+
+class IdealWifiRemoteStation : public WifiRemoteStation
+{
+public:
+  IdealWifiRemoteStation (Ptr<IdealWifiManager> stations);
+
+  virtual ~IdealWifiRemoteStation ();
+
+  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 void ReportFinalRtsFailed (void);
+  virtual void ReportFinalDataFailed (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 */
--- a/src/devices/wifi/mac-low.cc	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/mac-low.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -28,7 +28,7 @@
 #include "mac-low.h"
 #include "wifi-phy.h"
 #include "wifi-mac-trailer.h"
-#include "wifi-net-device.h"
+#include "wifi-mac.h"
 #include "mac-stations.h"
 #include "wifi-mac-parameters.h"
 #include "ns3/composite-trace-resolver.h"
@@ -36,8 +36,7 @@
 NS_LOG_COMPONENT_DEFINE ("MacLow");
 
 #define MY_DEBUG(x) \
-  NS_LOG_DEBUG (Simulator::Now () << " " << m_device->GetNode ()->GetId () << ":" << \
-                m_device->GetIfIndex () << " " << x)
+  NS_LOG_DEBUG (Simulator::Now () << " " << m_mac->GetAddress () << " " << x)
 
 namespace ns3 {
 
@@ -300,37 +299,30 @@
     }
 }
 
-/****************************************************************************
- *  API methods below.
- ****************************************************************************/
-
-void
-MacLow::SetDevice (Ptr<WifiNetDevice> device)
-{
-  m_device = device;
-}
-Ptr<NetDevice> 
-MacLow::GetDevice (void) const
-{
-  return m_device;
-}
 void
 MacLow::SetPhy (Ptr<WifiPhy> phy)
 {
   m_phy = phy;
+  m_phy->SetReceiveOkCallback (MakeCallback (&MacLow::ReceiveOk, this));
+  m_phy->SetReceiveErrorCallback (MakeCallback (&MacLow::ReceiveError, this));
 }
-void 
-MacLow::SetParameters (WifiMacParameters *parameters)
+void
+MacLow::SetMac (Ptr<WifiMac> mac)
 {
-  m_parameters = parameters;
+  m_mac = mac;
 }
 void 
-MacLow::SetStations (MacStations *stations)
+MacLow::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> manager)
 {
-  m_stations = stations;
+  m_stationManager = manager;
+}
+Ptr<WifiMac> 
+MacLow::GetMac (void)
+{
+  return m_mac;
 }
 void 
-MacLow::SetRxCallback (MacLowRxCallback callback)
+MacLow::SetRxCallback (Callback<void,Ptr<Packet>,const WifiMacHeader *> callback)
 {
   m_rxCallback = callback;
 }
@@ -389,7 +381,6 @@
 MacLow::ReceiveError (Ptr<Packet> packet, double rxSnr)
 {
   MY_DEBUG ("rx failed ");
-  m_dropError (packet);
   if (m_txParams.MustWaitFastAck ()) 
     {
       NS_ASSERT (m_fastAckFailedTimeoutEvent.IsExpired ());
@@ -422,11 +413,11 @@
        * that STA shall not respond to the RTS frame.
        */
       if (isPrevNavZero &&
-          hdr.GetAddr1 () == m_device->GetSelfAddress ()) 
+          hdr.GetAddr1 () == m_mac->GetAddress ()) 
         {
           MY_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
           NS_ASSERT (m_sendCtsEvent.IsExpired ());
-          MacStation *station = m_stations->Lookup (hdr.GetAddr2 ());
+          WifiRemoteStation *station = GetStation (hdr.GetAddr2 ());
           station->ReportRxOk (rxSnr, txMode);
           m_sendCtsEvent = Simulator::Schedule (GetSifs (),
                                                 &MacLow::SendCtsAfterRts, this,
@@ -441,14 +432,14 @@
         }
     } 
   else if (hdr.IsCts () &&
-           hdr.GetAddr1 () == m_device->GetSelfAddress () &&
+           hdr.GetAddr1 () == m_mac->GetAddress () &&
            m_ctsTimeoutEvent.IsRunning () &&
            m_currentPacket != 0) 
     {
       MY_DEBUG ("receive cts from="<<m_currentHdr.GetAddr1 ());
       SnrTag tag;
       packet->PeekTag (tag);
-      MacStation *station = GetStation (m_currentHdr.GetAddr1 ());
+      WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
       station->ReportRxOk (rxSnr, txMode);
       station->ReportRtsOk (rxSnr, txMode, tag.Get ());
       
@@ -462,7 +453,7 @@
                                              txMode);
     } 
   else if (hdr.IsAck () &&
-           hdr.GetAddr1 () == m_device->GetSelfAddress () &&
+           hdr.GetAddr1 () == m_mac->GetAddress () &&
            (m_normalAckTimeoutEvent.IsRunning () || 
             m_fastAckTimeoutEvent.IsRunning () ||
             m_superFastAckTimeoutEvent.IsRunning ()) &&
@@ -471,7 +462,7 @@
       MY_DEBUG ("receive ack from="<<m_currentHdr.GetAddr1 ());
       SnrTag tag;
       packet->PeekTag (tag);
-      MacStation *station = GetStation (m_currentHdr.GetAddr1 ());
+      WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
       station->ReportRxOk (rxSnr, txMode);
       station->ReportDataOk (rxSnr, txMode, tag.Get ());
       bool gotAck = false;
@@ -501,9 +492,9 @@
     {
       MY_DEBUG ("rx drop " << hdr.GetTypeString ());
     } 
-  else if (hdr.GetAddr1 () == m_device->GetSelfAddress ()) 
+  else if (hdr.GetAddr1 () == m_mac->GetAddress ()) 
     {
-      MacStation *station = GetStation (hdr.GetAddr2 ());
+      WifiRemoteStation *station = GetStation (hdr.GetAddr2 ());
       station->ReportRxOk (rxSnr, txMode);
       
       if (hdr.IsQosData () && hdr.IsQosNoAck ()) 
@@ -583,22 +574,27 @@
 Time
 MacLow::GetSifs (void) const
 {
-  return m_parameters->GetSifs ();
+  return m_mac->GetSifs ();
+}
+Time
+MacLow::GetSlotTime (void) const
+{
+  return m_mac->GetSlot ();
 }
 Time
 MacLow::GetPifs (void) const
 {
-  return m_parameters->GetPifs ();
+  return m_mac->GetPifs ();
 }
 Time
 MacLow::GetAckTimeout (void) const
 {
-  return m_parameters->GetAckTimeout ();
+  return m_mac->GetAckTimeout ();
 }
 Time
 MacLow::GetCtsTimeout (void) const
 {
-  return m_parameters->GetCtsTimeout ();
+  return m_mac->GetCtsTimeout ();
 }
 uint32_t 
 MacLow::GetSize (Ptr<const Packet> packet, const WifiMacHeader *hdr) const
@@ -680,7 +676,7 @@
   Time duration = hdr.GetDuration ();
 
   if (hdr.IsCfpoll () &&
-      hdr.GetAddr2 () == m_device->GetBssid ()) 
+      hdr.GetAddr2 () == m_mac->GetBssid ()) 
     {
       // see section 9.3.2.2 802.11-1999
       DoNavResetNow (duration);
@@ -688,7 +684,7 @@
     }
   // XXX Note that we should also handle CF_END specially here
   // but we don't for now because we do not generate them.
-  else if (hdr.GetAddr1 () != m_device->GetSelfAddress ())
+  else if (hdr.GetAddr1 () != m_mac->GetAddress ())
     {
       // see section 9.2.5.4 802.11-1999
       bool navUpdated = DoNavStartNow (duration);
@@ -706,7 +702,7 @@
           cts.SetType (WIFI_MAC_CTL_CTS);
           Time navCounterResetCtsMissedDelay = 
             m_phy->CalculateTxDuration (cts.GetSerializedSize (), txMode, preamble) +
-            Scalar (2) * m_parameters->GetSifs () + Scalar (2) * m_parameters->GetSlotTime ();
+            Scalar (2) * GetSifs () + Scalar (2) * GetSlotTime ();
           m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay,
                                                             &MacLow::NavCounterResetCtsMissed, this,
                                                             Simulator::Now ());
@@ -778,7 +774,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.
-  MacStation *station = GetStation (m_currentHdr.GetAddr1 ());
+  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
   station->ReportRtsFailed ();
   m_currentPacket = 0;
   MacLowTransmissionListener *listener = m_listener;
@@ -792,7 +788,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.
-  MacStation *station = GetStation (m_currentHdr.GetAddr1 ());
+  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
   station->ReportDataFailed ();
   MacLowTransmissionListener *listener = m_listener;
   m_listener = 0;
@@ -801,7 +797,7 @@
 void
 MacLow::FastAckTimeout (void)
 {
-  MacStation *station = GetStation (m_currentHdr.GetAddr1 ());
+  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
   station->ReportDataFailed ();
   MacLowTransmissionListener *listener = m_listener;
   m_listener = 0;
@@ -818,7 +814,7 @@
 void
 MacLow::SuperFastAckTimeout ()
 {
-  MacStation *station = GetStation (m_currentHdr.GetAddr1 ());
+  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
   station->ReportDataFailed ();
   MacLowTransmissionListener *listener = m_listener;
   m_listener = 0;
@@ -843,7 +839,7 @@
   rts.SetDsNotFrom ();
   rts.SetDsNotTo ();
   rts.SetAddr1 (m_currentHdr.GetAddr1 ());
-  rts.SetAddr2 (m_device->GetSelfAddress ());
+  rts.SetAddr2 (m_mac->GetAddress ());
   WifiMode rtsTxMode = GetRtsTxMode (m_currentPacket, &m_currentHdr);
   Time duration = Seconds (0);
   if (m_txParams.HasDurationId ()) 
@@ -968,10 +964,10 @@
     }
 }
 
-MacStation *
+WifiRemoteStation *
 MacLow::GetStation (Mac48Address ad) const
 {
-  return m_stations->Lookup (ad);
+  return m_stationManager->Lookup (ad);
 }
 
 void
@@ -1077,17 +1073,4 @@
   ForwardDown (packet, &ack, ackTxMode);
 }
 
-Ptr<TraceResolver> 
-MacLow::GetTraceResolver (void) const
-{
-  Ptr<CompositeTraceResolver> resolver =
-    Create<CompositeTraceResolver> ();
-  resolver->AddSource ("error",
-                       TraceDoc ("Receive a packet with errors",
-                                 "Packet", "the packet received"),
-                       m_dropError);
-  resolver->SetParentResolver (Object::GetTraceResolver ());
-  return resolver;
-}
-
 } // namespace ns3
--- a/src/devices/wifi/mac-low.h	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/mac-low.h	Sat Mar 01 21:21:53 2008 +0100
@@ -26,9 +26,9 @@
 #include "wifi-mac-header.h"
 #include "wifi-mode.h"
 #include "wifi-preamble.h"
+#include "wifi-remote-station-manager.h"
 #include "ns3/mac48-address.h"
 #include "ns3/callback.h"
-#include "ns3/callback-trace-source.h"
 #include "ns3/event-id.h"
 #include "ns3/packet.h"
 #include "ns3/nstime.h"
@@ -37,10 +37,7 @@
 
 class WifiNetDevice;
 class WifiPhy;
-class PacketLogger;
-class MacStations;
-class MacStation;
-class WifiMacParameters;
+class WifiMac;
 
 /**
  * \brief listen to events coming from ns3::MacLow.
@@ -277,18 +274,19 @@
   MacLow ();
   virtual ~MacLow ();
 
-  void SetDevice (Ptr<WifiNetDevice> device);
   void SetPhy (Ptr<WifiPhy> phy);
-  void SetStations (MacStations *stations);
-  void SetParameters (WifiMacParameters *parameters);
-  Ptr<NetDevice> GetDevice (void) const;
+  void SetMac (Ptr<WifiMac> mac);
+  void SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> manager);
+
+  Ptr<WifiMac> GetMac (void);
+
   /**
    * \param callback the callback which receives every incoming packet.
    *
    * This callback typically forwards incoming packets to
    * an instance of ns3::MacRxMiddle.
    */
-  void SetRxCallback (MacLowRxCallback callback);
+  void SetRxCallback (Callback<void,Ptr<Packet>,const WifiMacHeader *> callback);
   /**
    * \param listener listen to NAV events for every incoming
    *        and outgoing packet.
@@ -340,19 +338,18 @@
    */
   void ReceiveError (Ptr<Packet> packet, double rxSnr);
 private:
-  // Inherited from ns3::Object.
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
   void CancelAllEvents (void);
   uint32_t GetAckSize (void) const;
   uint32_t GetRtsSize (void) const;
   uint32_t GetCtsSize (void) const;
   Time GetSifs (void) const;
   Time GetPifs (void) const;
+  Time GetSlotTime (void) const;
   Time GetAckTimeout (void) const;
   Time GetCtsTimeout (void) const;
   uint32_t GetSize (Ptr<const Packet> packet, const WifiMacHeader *hdr) const;
   Time NowUs (void) const;
-  MacStation *GetStation (Mac48Address to) const;
+  WifiRemoteStation *GetStation (Mac48Address to) const;
   void ForwardDown (Ptr<const Packet> packet, WifiMacHeader const *hdr, 
                     WifiMode txMode);
   Time CalculateOverallTxTime (Ptr<const Packet> packet,
@@ -386,10 +383,9 @@
   void SendCurrentTxPacket (void);
   void StartDataTxTimers (void);
 
-  Ptr<WifiNetDevice> m_device;
   Ptr<WifiPhy> m_phy;
-  MacStations *m_stations;
-  WifiMacParameters *m_parameters;
+  Ptr<WifiMac> m_mac;
+  Ptr<WifiRemoteStationManager> m_stationManager;
   MacLowRxCallback m_rxCallback;
   typedef std::vector<MacLowNavListener *>::const_iterator NavListenersCI;
   typedef std::vector<MacLowNavListener *> NavListeners;
@@ -413,8 +409,6 @@
 
   Time m_lastNavStart;
   Time m_lastNavDuration;
-
-  CallbackTraceSource<Ptr<const Packet> > m_dropError;
 };
 
 } // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/nqap-wifi-mac.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,408 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * 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 "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/node.h"
+
+#include "nqap-wifi-mac.h"
+#include "dca-txop.h"
+#include "wifi-mac-header.h"
+#include "mgt-headers.h"
+#include "wifi-phy.h"
+#include "dcf-manager.h"
+#include "mac-rx-middle.h"
+#include "mac-low.h"
+
+NS_LOG_COMPONENT_DEFINE ("NqapWifiMac");
+
+#define TRACE(x) \
+  NS_LOG_DEBUG(Simulator::Now () << " " << GetAddress () << " " << x);
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (NqapWifiMac);
+
+TypeId 
+NqapWifiMac::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("NqapWifiMac")
+    .SetParent<WifiMac> ()
+    .AddConstructor<NqapWifiMac> ()
+    .AddAttribute ("BeaconInterval", "Delay between two beacons",
+                   Seconds (1.0),
+                   MakeTimeAccessor (&NqapWifiMac::m_beaconInterval),
+                   MakeTimeChecker ())
+    ;
+  return tid;
+}
+
+NqapWifiMac::NqapWifiMac ()
+{
+  m_dcfManager = new DcfManager ();
+
+  m_rxMiddle = new MacRxMiddle ();
+  m_rxMiddle->SetForwardCallback (MakeCallback (&NqapWifiMac::Receive, this));
+
+  m_low = new MacLow ();
+  m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle));
+
+  m_dca = CreateObject<DcaTxop> ();
+  m_dca->SetLow (m_low);
+  m_dca->SetManager (m_dcfManager);
+  m_dca->SetTxOkCallback (MakeCallback (&NqapWifiMac::TxOk, this));
+  m_dca->SetTxFailedCallback (MakeCallback (&NqapWifiMac::TxFailed, this));
+
+  m_beaconDca = CreateObject<DcaTxop> ();
+  m_beaconDca->SetLow (m_low);
+  m_beaconDca->SetManager (m_dcfManager);
+}
+NqapWifiMac::~NqapWifiMac ()
+{}
+
+void
+NqapWifiMac::DoDispose (void)
+{
+  delete m_rxMiddle;
+  delete m_low;
+  m_rxMiddle = 0;
+  m_low = 0;
+  m_phy = 0;
+  m_dca = 0;
+  m_beaconDca = 0;
+  WifiMac::DoDispose ();
+}
+
+
+void 
+NqapWifiMac::SetWifiPhy (Ptr<WifiPhy> phy)
+{
+  m_phy = phy;
+}
+void 
+NqapWifiMac::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager)
+{
+  m_stationManager = stationManager;
+}
+void 
+NqapWifiMac::SetForwardUpCallback (Callback<void,Ptr<Packet>, const Mac48Address &> upCallback)
+{
+  m_upCallback = upCallback;
+}
+void 
+NqapWifiMac::SetLinkUpCallback (Callback<void> linkUp)
+{
+
+}
+void 
+NqapWifiMac::SetLinkDownCallback (Callback<void> linkDown)
+{
+
+}
+Mac48Address 
+NqapWifiMac::GetAddress (void) const
+{
+  return m_address;
+}
+Ssid 
+NqapWifiMac::GetSsid (void) const
+{
+  return m_ssid;
+}
+Mac48Address 
+NqapWifiMac::GetBssid (void) const
+{
+  return m_address;
+}
+void 
+NqapWifiMac::SetAddress (Mac48Address address)
+{
+  m_address = address;
+}
+void 
+NqapWifiMac::SetSsid (Ssid ssid)
+{
+  m_ssid = ssid;
+}
+
+
+void 
+NqapWifiMac::SetBeaconInterval (Time interval)
+{
+  m_beaconInterval = interval;
+}
+void
+NqapWifiMac::StartBeaconing (void)
+{
+  SendOneBeacon ();
+}
+void 
+NqapWifiMac::ForwardUp (Ptr<Packet> packet, Mac48Address from)
+{
+  m_upCallback (packet, from);
+}
+void 
+NqapWifiMac::ForwardDown (Ptr<const Packet> packet, Mac48Address from, Mac48Address to)
+{
+  WifiMacHeader hdr;
+  hdr.SetTypeData ();
+  hdr.SetAddr1 (to);
+  hdr.SetAddr2 (GetAddress ());
+  hdr.SetAddr3 (from);
+  hdr.SetDsFrom ();
+  hdr.SetDsNotTo ();
+  m_dca->Queue (packet, hdr);  
+}
+void 
+NqapWifiMac::Enqueue (Ptr<const Packet> packet, Mac48Address to)
+{
+  ForwardDown (packet, GetAddress (), to);
+}
+SupportedRates
+NqapWifiMac::GetSupportedRates (void) const
+{
+  // send the set of supported rates and make sure that we indicate
+  // the Basic Rate set in this set of supported rates.
+  SupportedRates rates;
+  for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+    {
+      WifiMode mode = m_phy->GetMode (i);
+      rates.AddSupportedRate (mode.GetDataRate ());
+    }
+  // set the basic rates
+  for (uint32_t j = 0; j < m_stationManager->GetNBasicModes (); j++)
+    {
+      WifiMode mode = m_stationManager->GetBasicMode (j);
+      rates.SetBasicRate (mode.GetDataRate ());
+    }
+  return rates;
+}
+void
+NqapWifiMac::SendProbeResp (Mac48Address to)
+{
+  TRACE ("send probe response to="<<to);
+  WifiMacHeader hdr;
+  hdr.SetProbeResp ();
+  hdr.SetAddr1 (to);
+  hdr.SetAddr2 (GetAddress ());
+  hdr.SetAddr3 (GetAddress ());
+  hdr.SetDsNotFrom ();
+  hdr.SetDsNotTo ();
+  Ptr<Packet> packet = Create<Packet> ();
+  MgtProbeResponseHeader probe;
+  probe.SetSsid (GetSsid ());
+  probe.SetSupportedRates (GetSupportedRates ());
+  probe.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ());
+  packet->AddHeader (probe);
+
+  m_dca->Queue (packet, hdr);
+}
+void
+NqapWifiMac::SendAssocResp (Mac48Address to, bool success)
+{
+  TRACE ("send assoc response to="<<to);
+  WifiMacHeader hdr;
+  hdr.SetAssocResp ();
+  hdr.SetAddr1 (to);
+  hdr.SetAddr2 (GetAddress ());
+  hdr.SetAddr3 (GetAddress ());
+  hdr.SetDsNotFrom ();
+  hdr.SetDsNotTo ();
+  Ptr<Packet> packet = Create<Packet> ();
+  MgtAssocResponseHeader assoc;
+  StatusCode code;
+  if (success)
+    {
+      code.SetSuccess ();
+    }
+  else
+    {
+      code.SetFailure ();
+    }
+  assoc.SetSupportedRates (GetSupportedRates ());
+  assoc.SetStatusCode (code);
+  packet->AddHeader (assoc);
+  
+  m_dca->Queue (packet, hdr);
+}
+void
+NqapWifiMac::SendOneBeacon (void)
+{
+  TRACE ("send beacon to="<<Mac48Address::GetBroadcast ());
+  WifiMacHeader hdr;
+  hdr.SetBeacon ();
+  hdr.SetAddr1 (Mac48Address::GetBroadcast ());
+  hdr.SetAddr2 (GetAddress ());
+  hdr.SetAddr3 (GetAddress ());
+  hdr.SetDsNotFrom ();
+  hdr.SetDsNotTo ();
+  Ptr<Packet> packet = Create<Packet> ();
+  MgtBeaconHeader beacon;
+  beacon.SetSsid (GetSsid ());
+  beacon.SetSupportedRates (GetSupportedRates ());
+  beacon.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ());
+  packet->AddHeader (beacon);
+
+  m_beaconDca->Queue (packet, hdr);
+  Simulator::Schedule (m_beaconInterval, &NqapWifiMac::SendOneBeacon, this);
+}
+void 
+NqapWifiMac::TxOk (WifiMacHeader const &hdr)
+{
+  WifiRemoteStation *station = m_stationManager->Lookup (hdr.GetAddr1 ());
+  if (hdr.IsAssocResp () && 
+      station->IsWaitAssocTxOk ()) 
+    {
+      TRACE ("associated with sta="<<hdr.GetAddr1 ());
+      station->RecordGotAssocTxOk ();
+    }
+}
+void 
+NqapWifiMac::TxFailed (WifiMacHeader const &hdr)
+{
+  WifiRemoteStation *station = m_stationManager->Lookup (hdr.GetAddr1 ());
+  if (hdr.IsAssocResp () && 
+      station->IsWaitAssocTxOk ()) 
+    {
+      TRACE ("assoc failed with sta="<<hdr.GetAddr1 ());
+      station->RecordGotAssocTxFailed ();
+    }
+}
+void 
+NqapWifiMac::Receive (Ptr<Packet> packet, WifiMacHeader const *hdr)
+{
+  WifiRemoteStation *station = m_stationManager->Lookup (hdr->GetAddr2 ());
+
+  if (hdr->IsData ()) 
+    {
+      if (!hdr->IsFromDs () && 
+          hdr->IsToDs () &&
+          hdr->GetAddr1 () == GetAddress () &&
+          station->IsAssociated ()) 
+        {
+          if (hdr->GetAddr3 () == GetAddress ()) 
+            {
+              TRACE ("frame for me from="<<hdr->GetAddr2 ());
+              ForwardUp (packet, hdr->GetAddr2 ());
+            } 
+          else 
+            {
+              TRACE ("forwarding frame from="<<hdr->GetAddr2 ()<<", to="<<hdr->GetAddr3 ());
+              Ptr<Packet> copy = packet->Copy ();
+              ForwardDown (packet,
+                           hdr->GetAddr2 (), 
+                           hdr->GetAddr3 ());
+              ForwardUp (copy, hdr->GetAddr2 ());
+            }
+        } 
+      else if (hdr->IsFromDs () &&
+               hdr->IsToDs ()) 
+        {
+          // this is an AP-to-AP frame
+          // we ignore for now.
+        } 
+      else 
+        {
+          // we can ignore these frames since 
+          // they are not targeted at the AP
+        }
+    } 
+  else if (hdr->IsMgt ()) 
+    {
+      if (hdr->IsProbeReq ()) 
+        {
+          NS_ASSERT (hdr->GetAddr1 ().IsBroadcast ());
+          SendProbeResp (hdr->GetAddr2 ());
+        } 
+      else if (hdr->GetAddr1 () == GetAddress ()) 
+        {
+          if (hdr->IsAssocReq ()) 
+            {
+              // first, verify that the the station's supported
+              // rate set is compatible with our Basic Rate set
+              MgtAssocRequestHeader assocReq;
+              packet->RemoveHeader (assocReq);
+              SupportedRates rates = assocReq.GetSupportedRates ();
+              bool problem = false;
+              for (uint32_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
+                {
+                  WifiMode mode = m_stationManager->GetBasicMode (i);
+                  if (!rates.IsSupportedRate (mode.GetDataRate ()))
+                    {
+                      problem = true;
+                      break;
+                    }
+                }
+              if (problem)
+                {
+                  // one of the Basic Rate set mode is not
+                  // supported by the station. So, we return an assoc
+                  // response with an error status.
+                  SendAssocResp (hdr->GetAddr2 (), false);
+                }
+              else
+                {
+                  // station supports all rates in Basic Rate Set.
+                  // record all its supported modes in its associated WifiRemoteStation
+                  for (uint32_t j = 0; j < m_phy->GetNModes (); j++)
+                    {
+                      WifiMode mode = m_phy->GetMode (j);
+                      if (rates.IsSupportedRate (mode.GetDataRate ()))
+                        {
+                          station->AddSupportedMode (mode);
+                        }
+                    }
+                  station->RecordWaitAssocTxOk ();
+                  // send assoc response with success status.
+                  SendAssocResp (hdr->GetAddr2 (), true);
+                }
+            } 
+          else if (hdr->IsDisassociation ()) 
+            {
+              station->RecordDisassociated ();
+            } 
+          else if (hdr->IsReassocReq ()) 
+            {
+              /* we don't support reassoc frames for now */
+            } 
+          else if (hdr->IsAuthentication () ||
+                   hdr->IsDeauthentication ()) 
+            {
+              /*
+               */
+            } 
+          else 
+            {
+              /* unknown mgt frame
+               */
+            }
+        }
+    } 
+  else 
+    {
+    /* damn, what could this be ? a control frame ?
+     * control frames should never reach the MacHigh so,
+     * this is likely to be a bug. assert.
+     */
+      NS_ASSERT (false);
+    }  
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/nqap-wifi-mac.h	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,110 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * 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 MAC_HIGH_NQAP_H
+#define MAC_HIGH_NQAP_H
+
+#include <stdint.h>
+#include "ns3/mac48-address.h"
+#include "ns3/callback.h"
+#include "ns3/packet.h"
+#include "ns3/nstime.h"
+#include "supported-rates.h"
+#include "wifi-remote-station-manager.h"
+#include "wifi-mac.h"
+
+namespace ns3 {
+
+class WifiMacHeader;
+class DcaTxop;
+class WifiPhy;
+class DcfManager;
+class MacRxMiddle;
+class MacLow;
+
+/**
+ * \brief non-QoS AP state machine
+ *
+ * Handle association, dis-association and authentication,
+ * of STAs within an IBSS.
+ * This class uses two output queues, each of which is server by
+ * a single DCF
+ *   - the highest priority DCF serves the queue which contains
+ *     only beacons.
+ *   - the lowest priority DCF serves the queue which contains all
+ *     other frames, including user data frames.
+ */
+class NqapWifiMac : public WifiMac
+{
+public:
+  static TypeId GetTypeId (void);
+
+  NqapWifiMac ();
+  ~NqapWifiMac ();
+
+  virtual void SetWifiPhy (Ptr<WifiPhy> phy);
+  virtual void SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager);
+  virtual void Enqueue (Ptr<const Packet> packet, Mac48Address to);
+  virtual void SetForwardUpCallback (Callback<void,Ptr<Packet>, const Mac48Address &> upCallback);
+  virtual void SetLinkUpCallback (Callback<void> linkUp);
+  virtual void SetLinkDownCallback (Callback<void> linkDown);
+  virtual Mac48Address GetAddress (void) const;
+  virtual Ssid GetSsid (void) const;
+  virtual Mac48Address GetBssid (void) const;
+  virtual void SetAddress (Mac48Address address);
+  virtual void SetSsid (Ssid ssid);
+
+
+  void SetBeaconInterval (Time interval);
+  Time GetBeaconInterval (void) const;
+  /**
+   * Start beacon transmission immediately.
+   */
+  void StartBeaconing (void);
+
+private:
+  void Receive (Ptr<Packet> packet, WifiMacHeader const *hdr);
+  void ForwardUp (Ptr<Packet> packet, Mac48Address from);
+  void ForwardDown (Ptr<const Packet> packet, Mac48Address from, Mac48Address to);
+  void TxOk (WifiMacHeader const &hdr);
+  void TxFailed (WifiMacHeader const &hdr);
+  void SendProbeResp (Mac48Address to);
+  void SendAssocResp (Mac48Address to, bool success);
+  void SendOneBeacon (void);
+  SupportedRates GetSupportedRates (void) const;
+  virtual void DoDispose (void);
+
+  Ptr<DcaTxop> m_dca;
+  Ptr<DcaTxop> m_beaconDca;
+  Ptr<WifiRemoteStationManager> m_stationManager;
+  Ptr<WifiPhy> m_phy;
+  Callback<void, Ptr<Packet>,const Mac48Address &> m_upCallback;
+  Time m_beaconInterval;
+
+  DcfManager *m_dcfManager;
+  MacRxMiddle *m_rxMiddle;
+  MacLow *m_low;
+  Mac48Address m_address;
+  Ssid m_ssid;
+};
+
+} // namespace ns3
+
+
+#endif /* MAC_HIGH_NQAP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/nqsta-wifi-mac.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,471 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * 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 "ns3/packet.h"
+#include "ns3/simulator.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/node.h"
+#include "ns3/uinteger.h"
+
+#include "nqsta-wifi-mac.h"
+#include "wifi-mac-header.h"
+#include "mgt-headers.h"
+#include "wifi-phy.h"
+#include "dca-txop.h"
+#include "mac-low.h"
+#include "dcf-manager.h"
+#include "mac-rx-middle.h"
+
+NS_LOG_COMPONENT_DEFINE ("NqstaWifiMac");
+
+#define TRACE(x) \
+  NS_LOG_DEBUG (Simulator::Now () << " " << GetAddress () << " " << x);
+
+/*
+ * The state machine for this NQSTA is:
+ --------------            -----------
+ | Associated |   <--------------------      ------->    | Refused |
+ --------------      \    /      -----------
+    \           \  /
+     \    -----------------     -----------------------------
+      \-> | Beacon Missed | --> | Wait Association Response |
+    -----------------     -----------------------------
+    \           ^
+     \          |
+      \    -----------------------
+       \-> | Wait Probe Response |
+           -----------------------
+ */
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (NqstaWifiMac);
+
+TypeId 
+NqstaWifiMac::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("NqstaWifiMac")
+    .SetParent<WifiMac> ()
+    .AddConstructor<NqstaWifiMac> ()
+    .AddAttribute ("ProbeRequestTimeout", "XXX",
+                   Seconds (0.5),
+                   MakeTimeAccessor (&NqstaWifiMac::m_probeRequestTimeout),
+                   MakeTimeChecker ())
+    .AddAttribute ("AssocRequestTimeout", "XXX",
+                   Seconds (0.5),
+                   MakeTimeAccessor (&NqstaWifiMac::m_assocRequestTimeout),
+                   MakeTimeChecker ())
+    .AddAttribute ("MaxMissedBeacons", 
+                   "Number of beacons which much be consecutively missed before "
+                   "we attempt to restart association.",
+                   Uinteger (10),
+                   MakeUintegerAccessor (&NqstaWifiMac::m_maxMissedBeacons),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+  return tid;
+}
+
+
+NqstaWifiMac::NqstaWifiMac ()
+  : m_state (BEACON_MISSED),
+    m_probeRequestEvent (),
+    m_assocRequestEvent (),
+    m_beaconWatchdogEnd (Seconds (0.0))
+{
+  m_dcfManager = new DcfManager ();
+
+  m_rxMiddle = new MacRxMiddle ();
+  m_rxMiddle->SetForwardCallback (MakeCallback (&NqstaWifiMac::Receive, this));
+
+  m_low = new MacLow ();
+  m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle));
+
+  m_dca = CreateObject<DcaTxop> ();
+  m_dca->SetLow (m_low);
+  m_dca->SetManager (m_dcfManager);
+}
+
+NqstaWifiMac::~NqstaWifiMac ()
+{}
+
+void
+NqstaWifiMac::DoDispose (void)
+{
+  delete m_rxMiddle;
+  delete m_low;
+  m_rxMiddle = 0;
+  m_low = 0;
+  m_phy = 0;
+  m_dca = 0;
+  WifiMac::DoDispose ();
+}
+
+void 
+NqstaWifiMac::SetWifiPhy (Ptr<WifiPhy> phy)
+{
+  m_phy = phy;
+}
+void 
+NqstaWifiMac::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager)
+{
+  m_stationManager = stationManager;
+}
+void 
+NqstaWifiMac::SetForwardUpCallback (Callback<void,Ptr<Packet>, const Mac48Address &> upCallback)
+{
+  m_forwardUp = upCallback;
+}
+void 
+NqstaWifiMac::SetLinkUpCallback (Callback<void> linkUp)
+{
+  m_linkUp = linkUp;
+}
+void 
+NqstaWifiMac::SetLinkDownCallback (Callback<void> linkDown)
+{
+  m_linkDown = linkDown;
+}
+Mac48Address 
+NqstaWifiMac::GetAddress (void) const
+{
+  return m_address;
+}
+Ssid 
+NqstaWifiMac::GetSsid (void) const
+{
+  return m_ssid;
+}
+Mac48Address 
+NqstaWifiMac::GetBssid (void) const
+{
+  return m_bssid;
+}
+void 
+NqstaWifiMac::SetAddress (Mac48Address address)
+{
+  m_address = address;
+}
+void 
+NqstaWifiMac::SetSsid (Ssid ssid)
+{
+  m_ssid = ssid;
+}
+
+void 
+NqstaWifiMac::SetMaxMissedBeacons (uint32_t missed)
+{
+  m_maxMissedBeacons = missed;
+}
+void 
+NqstaWifiMac::SetProbeRequestTimeout (Time timeout)
+{
+  m_probeRequestTimeout = timeout;
+}
+void 
+NqstaWifiMac::SetAssocRequestTimeout (Time timeout)
+{
+  m_assocRequestTimeout = timeout;
+}
+
+void 
+NqstaWifiMac::StartActiveAssociation (void)
+{
+  TryToEnsureAssociated ();
+}
+
+Mac48Address
+NqstaWifiMac::GetBroadcastBssid (void)
+{
+  return Mac48Address::GetBroadcast ();
+}
+
+void 
+NqstaWifiMac::SetBssid (Mac48Address bssid)
+{
+  m_bssid = bssid;
+}
+void 
+NqstaWifiMac::ForwardUp (Ptr<Packet> packet, const Mac48Address &address)
+{
+  m_forwardUp (packet, address);
+}
+void
+NqstaWifiMac::SendProbeRequest (void)
+{
+  TRACE ("send probe request");
+  WifiMacHeader hdr;
+  hdr.SetProbeReq ();
+  hdr.SetAddr1 (GetBroadcastBssid ());
+  hdr.SetAddr2 (GetAddress ());
+  hdr.SetAddr3 (GetBroadcastBssid ());
+  hdr.SetDsNotFrom ();
+  hdr.SetDsNotTo ();
+  Ptr<Packet> packet = Create<Packet> ();
+  MgtProbeRequestHeader probe;
+  probe.SetSsid (GetSsid ());
+  probe.SetSupportedRates (GetSupportedRates ());
+  packet->AddHeader (probe);
+  
+  m_dca->Queue (packet, hdr);
+
+  m_probeRequestEvent = Simulator::Schedule (m_probeRequestTimeout,
+                                             &NqstaWifiMac::ProbeRequestTimeout, this);
+}
+
+void
+NqstaWifiMac::SendAssociationRequest (void)
+{
+  TRACE ("send assoc request to=" << GetBssid ());
+  WifiMacHeader hdr;
+  hdr.SetAssocReq ();
+  hdr.SetAddr1 (GetBssid ());
+  hdr.SetAddr2 (GetAddress ());
+  hdr.SetAddr3 (GetBssid ());
+  hdr.SetDsNotFrom ();
+  hdr.SetDsNotTo ();
+  Ptr<Packet> packet = Create<Packet> ();
+  MgtAssocRequestHeader assoc;
+  assoc.SetSsid (GetSsid ());
+  assoc.SetSupportedRates (GetSupportedRates ());
+  packet->AddHeader (assoc);
+  
+  m_dca->Queue (packet, hdr);
+
+  m_assocRequestEvent = Simulator::Schedule (m_assocRequestTimeout,
+                                             &NqstaWifiMac::AssocRequestTimeout, this);
+}
+void
+NqstaWifiMac::TryToEnsureAssociated (void)
+{
+  switch (m_state) {
+  case ASSOCIATED:
+    return;
+    break;
+  case WAIT_PROBE_RESP:
+    /* we have sent a probe request earlier so we
+       do not need to re-send a probe request immediately.
+       We just need to wait until probe-request-timeout
+       or until we get a probe response
+     */
+    break;
+  case BEACON_MISSED:
+    /* we were associated but we missed a bunch of beacons
+     * so we should assume we are not associated anymore.
+     * We try to initiate a probe request now.
+     */
+    m_linkDown ();
+    m_state = WAIT_PROBE_RESP;
+    SendProbeRequest ();
+    break;
+  case WAIT_ASSOC_RESP:
+    /* we have sent an assoc request so we do not need to
+       re-send an assoc request right now. We just need to
+       wait until either assoc-request-timeout or until
+       we get an assoc response.
+     */
+    break;
+  case REFUSED:
+    /* we have sent an assoc request and received a negative
+       assoc resp. We wait until someone restarts an 
+       association with a given ssid.
+     */
+    break;
+  }
+}
+
+void
+NqstaWifiMac::AssocRequestTimeout (void)
+{
+  TRACE ("assoc request timeout");
+  m_state = WAIT_ASSOC_RESP;
+  SendAssociationRequest ();
+}
+void
+NqstaWifiMac::ProbeRequestTimeout (void)
+{
+  TRACE ("probe request timeout");
+  m_state = WAIT_PROBE_RESP;
+  SendProbeRequest ();
+}
+void 
+NqstaWifiMac::MissedBeacons (void)
+{
+  if (m_beaconWatchdogEnd > Simulator::Now ())
+    {
+      m_beaconWatchdog = Simulator::Schedule (m_beaconWatchdogEnd - Simulator::Now (),
+                                              &NqstaWifiMac::MissedBeacons, this);
+      return;
+    }
+  TRACE ("beacon missed");
+  m_state = BEACON_MISSED;
+  TryToEnsureAssociated ();
+}
+void 
+NqstaWifiMac::RestartBeaconWatchdog (Time delay)
+{
+  m_beaconWatchdogEnd = std::max (Simulator::Now () + delay, m_beaconWatchdogEnd);
+  if (Simulator::GetDelayLeft (m_beaconWatchdog) < delay &&
+      m_beaconWatchdog.IsExpired ())
+    {
+      m_beaconWatchdog = Simulator::Schedule (delay, &NqstaWifiMac::MissedBeacons, this);
+    }
+}
+bool
+NqstaWifiMac::IsAssociated (void)
+{
+  return (m_state == ASSOCIATED)?true:false;
+}
+
+void 
+NqstaWifiMac::Enqueue (Ptr<const Packet> packet, Mac48Address to)
+{
+  if (!IsAssociated ()) 
+    {
+      TryToEnsureAssociated ();
+      return;
+    }
+  //TRACE ("enqueue size="<<packet->GetSize ()<<", to="<<to);
+  WifiMacHeader hdr;
+  hdr.SetTypeData ();
+  hdr.SetAddr1 (GetBssid ());
+  hdr.SetAddr2 (GetAddress ());
+  hdr.SetAddr3 (to);
+  hdr.SetDsNotFrom ();
+  hdr.SetDsTo ();
+  m_dca->Queue (packet, hdr);
+}
+
+void 
+NqstaWifiMac::Receive (Ptr<Packet> packet, WifiMacHeader const *hdr)
+{
+  NS_ASSERT (!hdr->IsCtl ());
+  if (hdr->GetAddr1 () != GetAddress () &&
+      !hdr->GetAddr1 ().IsBroadcast ()) 
+    {
+      // packet is not for us
+    } 
+  else if (hdr->IsData ()) 
+    {
+      ForwardUp (packet, hdr->GetAddr2 ());
+    } 
+  else if (hdr->IsProbeReq () ||
+           hdr->IsAssocReq ()) 
+    {
+      /* this is a frame aimed at an AP.
+       * so we can safely ignore it.
+       */
+    } 
+  else if (hdr->IsBeacon ()) 
+    {
+      MgtBeaconHeader beacon;
+      packet->RemoveHeader (beacon);
+      bool goodBeacon = false;
+      if (GetSsid ().IsBroadcast () ||
+          beacon.GetSsid ().IsEqual (GetSsid ()))
+        {
+          Time delay = MicroSeconds (beacon.GetBeaconIntervalUs () * m_maxMissedBeacons);
+          RestartBeaconWatchdog (delay);
+          goodBeacon = true;
+        }
+      if (goodBeacon) 
+        {
+          SetBssid (hdr->GetAddr3 ());
+        }
+      if (goodBeacon && m_state == BEACON_MISSED) 
+        {
+          m_state = WAIT_ASSOC_RESP;
+          SendAssociationRequest ();
+        }
+  } 
+  else if (hdr->IsProbeResp ()) 
+    {
+      if (m_state == WAIT_PROBE_RESP) 
+        {
+          MgtProbeResponseHeader probeResp;
+          packet->RemoveHeader (probeResp);
+          if (!probeResp.GetSsid ().IsEqual (GetSsid ()))
+            {
+              //not a probe resp for our ssid.
+              return;
+            }
+          SetBssid (hdr->GetAddr3 ());
+          Time delay = MicroSeconds (probeResp.GetBeaconIntervalUs () * m_maxMissedBeacons);
+          RestartBeaconWatchdog (delay);
+          if (m_probeRequestEvent.IsRunning ()) 
+            {
+              m_probeRequestEvent.Cancel ();
+            }
+          m_state = WAIT_ASSOC_RESP;
+          SendAssociationRequest ();
+        }
+    } 
+  else if (hdr->IsAssocResp ()) 
+    {
+      if (m_state == WAIT_ASSOC_RESP) 
+        {
+          MgtAssocResponseHeader assocResp;
+          packet->RemoveHeader (assocResp);
+          if (m_assocRequestEvent.IsRunning ()) 
+            {
+              m_assocRequestEvent.Cancel ();
+            }
+          if (assocResp.GetStatusCode ().IsSuccess ()) 
+            {
+              m_state = ASSOCIATED;
+              TRACE ("assoc completed"); 
+              SupportedRates rates = assocResp.GetSupportedRates ();
+              WifiRemoteStation *ap = m_stationManager->Lookup (hdr->GetAddr2 ());
+              for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+                {
+                  WifiMode mode = m_phy->GetMode (i);
+                  if (rates.IsSupportedRate (mode.GetDataRate ()))
+                    {
+                      ap->AddSupportedMode (mode);
+                      if (rates.IsBasicRate (mode.GetDataRate ()))
+                        {
+                          m_stationManager->AddBasicMode (mode);
+                        }
+                    }
+                }
+              m_linkUp ();
+            } 
+          else 
+            {
+              TRACE ("assoc refused");
+              m_state = REFUSED;
+            }
+        }
+    }
+}
+
+SupportedRates
+NqstaWifiMac::GetSupportedRates (void) const
+{
+  SupportedRates rates;
+  for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+    {
+      WifiMode mode = m_phy->GetMode (i);
+      rates.AddSupportedRate (mode.GetDataRate ());
+    }
+  return rates;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/nqsta-wifi-mac.h	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,147 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * 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 NQSTA_WIFI_MAC_H
+#define NQSTA_WIFI_MAC_H
+
+#include <stdint.h>
+
+#include "ns3/mac48-address.h"
+#include "ns3/callback.h"
+#include "ns3/event-id.h"
+#include "ns3/packet.h"
+#include "ns3/nstime.h"
+
+#include "wifi-mac.h"
+#include "supported-rates.h"
+
+namespace ns3 {
+
+class WifiMacHeader;
+class DcaTxop;
+class WifiPhy;
+class DcfManager;
+class MacLow;
+class MacRxMiddle;
+
+/**
+ * \brief a non-QoS STA state machine
+ *
+ * This state machine handles association, disassociation,
+ * authentication and beacon monitoring. It does not perform
+ * channel scanning.
+ * If the station detects a certain number of missed beacons
+ * while associated, it automatically attempts a new association
+ * sequence.
+ */
+class NqstaWifiMac : public WifiMac
+{
+public:
+  static TypeId GetTypeId (void);
+
+  NqstaWifiMac ();
+  ~NqstaWifiMac ();
+
+  virtual void SetWifiPhy (Ptr<WifiPhy> phy);
+  virtual void SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager);
+  virtual void Enqueue (Ptr<const Packet> packet, Mac48Address to);
+  virtual void SetForwardUpCallback (Callback<void,Ptr<Packet>, const Mac48Address &> upCallback);
+  virtual void SetLinkUpCallback (Callback<void> linkUp);
+  virtual void SetLinkDownCallback (Callback<void> linkDown);
+  virtual Mac48Address GetAddress (void) const;
+  virtual Ssid GetSsid (void) const;
+  virtual Mac48Address GetBssid (void) const;
+  virtual void SetAddress (Mac48Address address);
+  virtual void SetSsid (Ssid ssid);
+
+
+  /**
+   * \param missed the number of beacons which must be missed
+   * before a new association sequence is started.
+   */
+  void SetMaxMissedBeacons (uint32_t missed);
+  /**
+   * \param timeout
+   *
+   * If no probe response is received within the specified
+   * timeout, the station sends a new probe request.
+   */
+  void SetProbeRequestTimeout (Time timeout);
+  /**
+   * \param timeout
+   *
+   * If no association response is received within the specified
+   * timeout, the station sends a new association request.
+   */
+  void SetAssocRequestTimeout (Time timeout);
+
+  /**
+   * Start an active association sequence immediately.
+   */
+  void StartActiveAssociation (void);
+
+private:
+  void SetBssid (Mac48Address bssid);
+  void ForwardUp (Ptr<Packet> packet, const Mac48Address &address);
+  void Receive (Ptr<Packet> packet, WifiMacHeader const *hdr);
+  Mac48Address GetBroadcastBssid (void);
+  void SendProbeRequest (void);
+  void SendAssociationRequest (void);
+  void TryToEnsureAssociated (void);
+  void AssocRequestTimeout (void);
+  void ProbeRequestTimeout (void);
+  bool IsAssociated (void);
+  void MissedBeacons (void);
+  void RestartBeaconWatchdog (Time delay);
+  SupportedRates GetSupportedRates (void) const;
+  virtual void DoDispose (void);
+
+  enum {
+    ASSOCIATED,
+    WAIT_PROBE_RESP,
+    WAIT_ASSOC_RESP,
+    BEACON_MISSED,
+    REFUSED
+  } m_state;
+  Time m_probeRequestTimeout;
+  Time m_assocRequestTimeout;
+  EventId m_probeRequestEvent;
+  EventId m_assocRequestEvent;
+  Callback<void, Ptr<Packet>,const Mac48Address &> m_forwardUp;
+  Callback<void> m_linkUp;
+  Callback<void> m_linkDown;
+  Ptr<DcaTxop> m_dca;
+  EventId m_beaconWatchdog;
+  Time m_beaconWatchdogEnd;
+  Mac48Address m_bssid;
+  uint32_t m_maxMissedBeacons;
+
+  Ptr<WifiPhy> m_phy;
+  Ptr<WifiRemoteStationManager> m_stationManager;
+  DcfManager *m_dcfManager;
+  MacRxMiddle *m_rxMiddle;
+  MacLow *m_low;
+  Mac48Address m_address;
+  Ssid m_ssid;
+};
+
+} // namespace ns3
+
+
+#endif /* NQSTA_WIFI_MAC_H */
--- a/src/devices/wifi/wifi-channel.cc	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/wifi-channel.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -52,19 +52,28 @@
 }
 
 void 
-WifiChannel::Add (Ptr<NetDevice> device,  ReceiveCallback callback)
+WifiChannel::Add (Ptr<NetDevice> device, Ptr<WifiPhy> phy)
 {
-  m_deviceList.push_back (std::make_pair (device, callback));
+  m_deviceList.push_back (std::make_pair (device, phy));
 }
 void 
-WifiChannel::Send (Ptr<NetDevice> sender, Ptr<const Packet> packet, double txPowerDbm,
+WifiChannel::Send (Ptr<WifiPhy> sender, Ptr<const Packet> packet, double txPowerDbm,
                    WifiMode wifiMode, WifiPreamble preamble) const
 {
-  Ptr<MobilityModel> senderMobility = sender->GetNode ()->GetObject<MobilityModel> ();
+  Ptr<MobilityModel> senderMobility = 0;
+  for (DeviceList::const_iterator i = m_deviceList.begin (); i != m_deviceList.end (); i++)
+    {
+      if (sender == i->second)
+        {
+          senderMobility = i->first->GetNode ()->GetObject<MobilityModel> ();
+          break;
+        }
+    }
+  NS_ASSERT (senderMobility != 0);
   uint32_t j = 0;
   for (DeviceList::const_iterator i = m_deviceList.begin (); i != m_deviceList.end (); i++)
     {
-      if (sender != i->first)
+      if (sender != i->second)
         {
           Ptr<MobilityModel> receiverMobility = i->first->GetNode ()->GetObject<MobilityModel> ();
           Time delay = m_delay->GetDelay (senderMobility, receiverMobility);
@@ -83,7 +92,7 @@
 WifiChannel::Receive (uint32_t i, Ptr<Packet> packet, double rxPowerDbm,
                       WifiMode txMode, WifiPreamble preamble) const
 {
-  m_deviceList[i].second (packet, rxPowerDbm, txMode, preamble);
+  m_deviceList[i].second->StartReceivePacket (packet, rxPowerDbm, txMode, preamble);
 }
 
 uint32_t 
--- a/src/devices/wifi/wifi-channel.h	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/wifi-channel.h	Sat Mar 01 21:21:53 2008 +0100
@@ -26,6 +26,7 @@
 #include "ns3/channel.h"
 #include "wifi-mode.h"
 #include "wifi-preamble.h"
+#include "wifi-phy.h"
 
 namespace ns3 {
 
@@ -83,7 +84,7 @@
    * This method should not be invoked by normal users. It is 
    * currently invoked only from WifiPhy::SetChannel.
    */
-  void Add (Ptr<NetDevice> device,  ReceiveCallback callback);
+  void Add (Ptr<NetDevice> device,  Ptr<WifiPhy> phy);
   /**
    * \param sender the device from which the packet is originating.
    * \param packet the packet to send
@@ -94,11 +95,11 @@
    * This method should not be invoked by normal users. It is 
    * currently invoked only from WifiPhy::Send.
    */
-  void Send (Ptr<NetDevice> sender, Ptr<const Packet> packet, double txPowerDbm,
+  void Send (Ptr<WifiPhy> sender, Ptr<const Packet> packet, double txPowerDbm,
              WifiMode wifiMode, WifiPreamble preamble) const;
 
 private:
-  typedef std::vector<std::pair<Ptr<NetDevice>, ReceiveCallback> > DeviceList;
+  typedef std::vector<std::pair<Ptr<NetDevice>, Ptr<WifiPhy> > > DeviceList;
   void Receive (uint32_t i, Ptr<Packet> packet, double rxPowerDbm,
                 WifiMode txMode, WifiPreamble preamble) const;
   /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/wifi-helper.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,114 @@
+#include "wifi-helper.h"
+#include "wifi-net-device.h"
+#include "wifi-mac.h"
+#include "wifi-phy.h"
+#include "wifi-remote-station-manager.h"
+#include "wifi-channel.h"
+#include "ns3/mobility-model.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("WifiHelper");
+
+namespace ns3 {
+
+WifiHelper::WifiHelper ()
+{
+  m_stationManager.SetTypeId ("ArfWifiManager");
+  m_phy.SetTypeId ("WifiPhy");
+  m_mac.SetTypeId ("AdhocWifiMac");
+}
+
+void 
+WifiHelper::SetRemoteStationManager (std::string type,
+				     std::string n0, Attribute v0,
+				     std::string n1, Attribute v1,
+				     std::string n2, Attribute v2,
+				     std::string n3, Attribute v3,
+				     std::string n4, Attribute v4,
+				     std::string n5, Attribute v5,
+				     std::string n6, Attribute v6,
+				     std::string n7, Attribute v7)
+{
+  m_stationManager = ObjectFactory ();
+  m_stationManager.SetTypeId (type);
+  m_stationManager.Set (n0, v0);
+  m_stationManager.Set (n1, v1);
+  m_stationManager.Set (n2, v2);
+  m_stationManager.Set (n3, v3);
+  m_stationManager.Set (n4, v4);
+  m_stationManager.Set (n5, v5);
+  m_stationManager.Set (n6, v6);
+  m_stationManager.Set (n7, v7);
+}
+
+void 
+WifiHelper::SetMac (std::string type,
+		    std::string n0, Attribute v0,
+		    std::string n1, Attribute v1,
+		    std::string n2, Attribute v2,
+		    std::string n3, Attribute v3,
+		    std::string n4, Attribute v4,
+		    std::string n5, Attribute v5,
+		    std::string n6, Attribute v6,
+		    std::string n7, Attribute v7)
+{
+  m_mac = ObjectFactory ();
+  m_mac.SetTypeId (type);
+  m_mac.Set (n0, v0);
+  m_mac.Set (n1, v1);
+  m_mac.Set (n2, v2);
+  m_mac.Set (n3, v3);
+  m_mac.Set (n4, v4);
+  m_mac.Set (n5, v5);
+  m_mac.Set (n6, v6);
+  m_mac.Set (n7, v7);
+}
+
+void 
+WifiHelper::SetPhy (std::string type,
+		    std::string n0, Attribute v0,
+		    std::string n1, Attribute v1,
+		    std::string n2, Attribute v2,
+		    std::string n3, Attribute v3,
+		    std::string n4, Attribute v4,
+		    std::string n5, Attribute v5,
+		    std::string n6, Attribute v6,
+		    std::string n7, Attribute v7)
+{
+  m_phy = ObjectFactory ();
+  m_phy.SetTypeId (type);
+  m_phy.Set (n0, v0);
+  m_phy.Set (n1, v1);
+  m_phy.Set (n2, v2);
+  m_phy.Set (n3, v3);
+  m_phy.Set (n4, v4);
+  m_phy.Set (n5, v5);
+  m_phy.Set (n6, v6);
+  m_phy.Set (n7, v7);
+}
+
+NetDeviceContainer
+WifiHelper::Build (NodeContainer c) const
+{
+  Ptr<WifiChannel> channel = CreateObjectWith<WifiChannel> ();
+  return Build (c, channel);
+}
+NetDeviceContainer
+WifiHelper::Build (NodeContainer c, Ptr<WifiChannel> channel) const
+{
+  NetDeviceContainer devices;
+  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); i++)
+    {
+      Ptr<Node> node = *i;
+      Ptr<WifiNetDevice> device = CreateObject<WifiNetDevice> ();
+      Ptr<WifiRemoteStationManager> manager = m_stationManager.Create<WifiRemoteStationManager> ();
+      Ptr<WifiMac> mac = m_mac.Create<WifiMac> ();
+      Ptr<WifiPhy> phy = m_phy.Create<WifiPhy> ();
+      device->Setup (node, mac, phy, manager, channel);
+      node->AddDevice (device);
+      devices.Add (device);
+      NS_LOG_DEBUG ("node="<<node<<", mob="<<node->GetObject<MobilityModel> ());
+    }
+  return devices;
+}
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/wifi-helper.h	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,60 @@
+#ifndef WIFI_HELPER_H
+#define WIFI_HELPER_H
+
+#include <string>
+#include "ns3/attribute.h"
+#include "ns3/object-factory.h"
+#include "ns3/node-container.h"
+#include "ns3/net-device-container.h"
+
+namespace ns3 {
+
+class WifiChannel;
+
+class WifiHelper
+{
+public:
+  WifiHelper ();
+
+  void SetRemoteStationManager (std::string type,
+				std::string n0 = "", Attribute v0 = Attribute (),
+				std::string n1 = "", Attribute v1 = Attribute (),
+				std::string n2 = "", Attribute v2 = Attribute (),
+				std::string n3 = "", Attribute v3 = Attribute (),
+				std::string n4 = "", Attribute v4 = Attribute (),
+				std::string n5 = "", Attribute v5 = Attribute (),
+				std::string n6 = "", Attribute v6 = Attribute (),
+				std::string n7 = "", Attribute v7 = Attribute ());
+
+  void SetMac (std::string type,
+	       std::string n0 = "", Attribute v0 = Attribute (),
+	       std::string n1 = "", Attribute v1 = Attribute (),
+	       std::string n2 = "", Attribute v2 = Attribute (),
+	       std::string n3 = "", Attribute v3 = Attribute (),
+	       std::string n4 = "", Attribute v4 = Attribute (),
+	       std::string n5 = "", Attribute v5 = Attribute (),
+	       std::string n6 = "", Attribute v6 = Attribute (),
+	       std::string n7 = "", Attribute v7 = Attribute ());
+
+  void SetPhy (std::string phyType,
+	       std::string n0 = "", Attribute v0 = Attribute (),
+	       std::string n1 = "", Attribute v1 = Attribute (),
+	       std::string n2 = "", Attribute v2 = Attribute (),
+	       std::string n3 = "", Attribute v3 = Attribute (),
+	       std::string n4 = "", Attribute v4 = Attribute (),
+	       std::string n5 = "", Attribute v5 = Attribute (),
+	       std::string n6 = "", Attribute v6 = Attribute (),
+	       std::string n7 = "", Attribute v7 = Attribute ());
+
+  NetDeviceContainer Build (NodeContainer c) const;
+  NetDeviceContainer Build (NodeContainer c, Ptr<WifiChannel> channel) const;
+
+private:
+  ObjectFactory m_stationManager;
+  ObjectFactory m_mac;
+  ObjectFactory m_phy;
+};
+
+} // namespace ns3
+
+#endif /* WIFI_HELPER_H */
--- a/src/devices/wifi/wifi-mac-queue.cc	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/wifi-mac-queue.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -20,6 +20,7 @@
 
 #include "ns3/simulator.h"
 #include "ns3/packet.h"
+#include "ns3/uinteger.h"
 
 #include "wifi-mac-queue.h"
 
@@ -33,6 +34,24 @@
   : packet (packet), hdr (hdr), tstamp (tstamp)
 {}
 
+TypeId 
+WifiMacQueue::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("WifiMacQueue")
+    .SetParent<Object> ()
+    .AddConstructor<WifiMacQueue> ()
+    .AddAttribute ("MaxPacketNumber", "XXX",
+                   Uinteger (400),
+                   MakeUintegerAccessor (&WifiMacQueue::m_maxSize),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MaxDelay", "XXX",
+                   Seconds (10.0),
+                   MakeTimeAccessor (&WifiMacQueue::m_maxDelay),
+                   MakeTimeChecker ())
+    ;
+  return tid;
+}
+
 WifiMacQueue::WifiMacQueue ()
   : m_size (0)
 {}
@@ -52,6 +71,17 @@
 {
   m_maxDelay = delay;
 }
+uint32_t 
+WifiMacQueue::GetMaxSize (void) const
+{
+  return m_maxSize;
+}
+Time 
+WifiMacQueue::GetMaxDelay (void) const
+{
+  return m_maxDelay;
+}
+
 void 
 WifiMacQueue::Enqueue (Ptr<const Packet> packet, WifiMacHeader const &hdr)
 {
--- a/src/devices/wifi/wifi-mac-queue.h	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/wifi-mac-queue.h	Sat Mar 01 21:21:53 2008 +0100
@@ -24,6 +24,7 @@
 #include <utility>
 #include "ns3/packet.h"
 #include "ns3/nstime.h"
+#include "ns3/object.h"
 #include "wifi-mac-header.h"
 
 namespace ns3 {
@@ -45,13 +46,17 @@
  * dot11EDCATableMSDULifetime has elapsed, it is dropped.
  * Otherwise, it is returned to the caller.
  */
-class WifiMacQueue {
+class WifiMacQueue : public Object
+{
 public:
+  static TypeId GetTypeId (void);
   WifiMacQueue ();
   ~WifiMacQueue ();
 
   void SetMaxSize (uint32_t maxSize);
   void SetMaxDelay (Time delay);
+  uint32_t GetMaxSize (void) const;
+  Time GetMaxDelay (void) const;
 
   void Enqueue (Ptr<const Packet> packet, WifiMacHeader const &hdr);
   Ptr<const Packet> Dequeue (WifiMacHeader *hdr);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/wifi-mac.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,180 @@
+#include "wifi-mac.h"
+#include "ns3/uinteger.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (WifiMac);
+
+Time
+WifiMac::GetDefaultMaxPropagationDelay (void)
+{
+  // 1000m 
+  return Seconds (1000.0 / 300000000.0);
+}
+Time
+WifiMac::GetDefaultSlot (void)
+{
+  // 802.11-a specific
+  return MicroSeconds (9);
+}
+Time
+WifiMac::GetDefaultSifs (void)
+{
+  // 802.11-a specific
+  return MicroSeconds (16);
+}
+Time
+WifiMac::GetDefaultEifsNoDifs (void)
+{
+  return GetDefaultSifs () + GetDefaultCtsAckDelay ();
+}
+Time
+WifiMac::GetDefaultCtsAckDelay (void)
+{
+  // 802.11-a specific: 6mb/s
+  return MicroSeconds (44);
+}
+Time
+WifiMac::GetDefaultCtsAckTimeout (void)
+{
+  /* Cts_Timeout and Ack_Timeout are specified in the Annex C 
+     (Formal description of MAC operation, see details on the 
+     Trsp timer setting at page 346)
+  */
+  Time ctsTimeout = GetDefaultSifs ();
+  ctsTimeout += GetDefaultCtsAckDelay ();
+  ctsTimeout += GetDefaultMaxPropagationDelay () * Scalar (2);
+  ctsTimeout += GetDefaultSlot ();
+  return ctsTimeout;
+}
+
+
+TypeId 
+WifiMac::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("WifiMac")
+    .SetParent<Object> ()
+    .AddAttribute ("CtsTimeout", "XXX",
+                   GetDefaultCtsAckTimeout (),
+                   MakeTimeAccessor (&WifiMac::m_ctsTimeout),
+                   MakeTimeChecker ())
+    .AddAttribute ("AckTimeout", "XXX",
+                   GetDefaultCtsAckTimeout (),
+                   MakeTimeAccessor (&WifiMac::m_ackTimeout),
+                   MakeTimeChecker ())
+    .AddAttribute ("Sifs", "XXX",
+                   GetDefaultSifs (),
+                   MakeTimeAccessor (&WifiMac::SetSifs,
+				     &WifiMac::GetSifs),
+                   MakeTimeChecker ())
+    .AddAttribute ("EifsNoDifs", "XXX",
+		   GetDefaultEifsNoDifs (),
+		   MakeTimeAccessor (&WifiMac::SetEifsNoDifs,
+				     &WifiMac::GetEifsNoDifs),
+		   MakeTimeChecker ())
+    .AddAttribute ("Slot", "XXX",
+                   GetDefaultSlot (),
+                   MakeTimeAccessor (&WifiMac::SetSlot,
+				     &WifiMac::GetSlot),
+                   MakeTimeChecker ())
+    .AddAttribute ("Pifs", "XXX",
+                   GetDefaultSifs () + GetDefaultSlot (),
+                   MakeTimeAccessor (&WifiMac::m_pifs),
+                   MakeTimeChecker ())
+    .AddAttribute ("MaxPropagationDelay", "XXX",
+                   GetDefaultMaxPropagationDelay (),
+                   MakeTimeAccessor (&WifiMac::m_maxPropagationDelay),
+                   MakeTimeChecker ())
+    .AddAttribute ("MaxMsduSize", "XXX",
+		   Uinteger (2304),
+		   MakeUintegerAccessor (&WifiMac::GetMaxMsduSize),
+		   MakeUintegerChecker (1,2304))
+    ;
+  return tid;
+}
+
+void 
+WifiMac::SetSlot (Time slotTime)
+{
+  m_slot = slotTime;
+}
+void
+WifiMac::SetEifsNoDifs (Time eifsNoDifs)
+{
+  m_eifsNoDifs = eifsNoDifs;
+}
+void
+WifiMac::SetSifs (Time sifs)
+{
+  m_sifs = sifs;
+}
+void
+WifiMac::SetPifs (Time pifs)
+{
+  m_pifs = pifs;
+}
+void 
+WifiMac::SetCtsTimeout (Time ctsTimeout)
+{
+  m_ctsTimeout = ctsTimeout;
+}
+void 
+WifiMac::SetAckTimeout (Time ackTimeout)
+{
+  m_ackTimeout = ackTimeout;
+}
+void 
+WifiMac::SetMaxPropagationDelay (Time delay)
+{
+  m_maxPropagationDelay = delay;
+}
+Time
+WifiMac::GetPifs (void) const
+{
+  return m_pifs;
+}
+Time
+WifiMac::GetSifs (void) const
+{
+  return m_sifs;
+}
+Time
+WifiMac::GetSlot (void) const
+{
+  return m_slot;
+}
+Time 
+WifiMac::GetEifsNoDifs (void) const
+{
+  return m_eifsNoDifs;
+}
+Time
+WifiMac::GetCtsTimeout (void) const
+{
+  return m_ctsTimeout;
+}
+Time
+WifiMac::GetAckTimeout (void) const
+{
+  return m_ackTimeout;
+}
+
+Time
+WifiMac::GetMsduLifetime (void) const
+{
+  return Seconds (10);
+}
+Time
+WifiMac::GetMaxPropagationDelay (void) const
+{
+  return m_maxPropagationDelay;
+}
+
+uint32_t 
+WifiMac::GetMaxMsduSize (void) const
+{
+  return m_maxMsduSize;
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/wifi-mac.h	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,72 @@
+#ifndef WIFI_MAC_H
+#define WIFI_MAC_H
+
+#include "ns3/packet.h"
+#include "ns3/mac48-address.h"
+
+#include "wifi-phy.h"
+#include "wifi-remote-station-manager.h"
+#include "ssid.h"
+
+namespace ns3 {
+
+class WifiMac : public Object
+{
+public:
+  static TypeId GetTypeId (void);
+  
+  virtual void SetSlot (Time slotTime);
+  virtual void SetSifs (Time sifs);
+  virtual void SetEifsNoDifs (Time eifsNoDifs);
+  void SetPifs (Time pifs);
+  void SetCtsTimeout (Time ctsTimeout);
+  void SetAckTimeout (Time ackTimeout);
+  void SetMsduLifetime (Time msduLifetime);
+  void SetMaxPropagationDelay (Time delay);
+
+  Time GetPifs (void) const;
+  Time GetSifs (void) const;
+  Time GetSlot (void) const;
+  Time GetEifsNoDifs (void) const;
+  Time GetCtsTimeout (void) const;
+  Time GetAckTimeout (void) const;
+  Time GetMsduLifetime (void) const;
+  Time GetMaxPropagationDelay (void) const;
+  uint32_t GetMaxMsduSize (void) const;
+
+  virtual Mac48Address GetAddress (void) const = 0;
+  virtual Ssid GetSsid (void) const = 0;
+  virtual Mac48Address GetBssid (void) const = 0;
+  virtual void SetAddress (Mac48Address address) = 0;
+  virtual void SetSsid (Ssid ssid) = 0;
+
+private:
+  friend class WifiNetDevice;
+  virtual void Enqueue (Ptr<const Packet> packet, Mac48Address to) = 0;
+  virtual void SetWifiPhy (Ptr<WifiPhy> phy) = 0;
+  virtual void SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager) = 0;
+  virtual void SetForwardUpCallback (Callback<void,Ptr<Packet>, const Mac48Address &> upCallback) = 0;
+  virtual void SetLinkUpCallback (Callback<void> linkUp) = 0;
+  virtual void SetLinkDownCallback (Callback<void> linkDown) = 0;
+
+
+  static Time GetDefaultMaxPropagationDelay (void);
+  static Time GetDefaultSlot (void);
+  static Time GetDefaultSifs (void);
+  static Time GetDefaultEifsNoDifs (void);
+  static Time GetDefaultCtsAckDelay (void);
+  static Time GetDefaultCtsAckTimeout (void);
+
+  Time m_slot;
+  Time m_pifs;
+  Time m_sifs;
+  Time m_eifsNoDifs;
+  Time m_ctsTimeout;
+  Time m_ackTimeout;
+  Time m_maxPropagationDelay;
+  uint32_t m_maxMsduSize;
+};
+
+} // namespace ns3
+
+#endif /* WIFI_MAC_H */
--- a/src/devices/wifi/wifi-mode.cc	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/wifi-mode.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -31,6 +31,16 @@
   os << mode.GetUniqueName ();
   return os;
 }
+std::istream & operator >> (std::istream &is, WifiMode &mode)
+{
+  std::string str;
+  is >> str;
+  if (!WifiModeFactory::GetFactory ()->Search (str, &mode))
+    {
+      is.setstate (std::ios_base::badbit);
+    }
+  return is;
+}
 
 uint32_t 
 WifiMode::GetBandwidth (void) const
@@ -98,6 +108,8 @@
   : m_uid (uid)
 {}
 
+VALUE_HELPER_CPP (WifiMode);
+
 WifiModeFactory::WifiModeFactory ()
 {}
 
@@ -141,6 +153,23 @@
   return WifiMode (uid);
 }
 
+bool 
+WifiModeFactory::Search (std::string name, WifiMode *mode)
+{
+  uint32_t j = 0;
+  for (WifiModeItemList::const_iterator i = m_itemList.begin ();
+       i != m_itemList.end (); i++)
+    {
+      if (i->uniqueUid == name)
+	{
+          *mode = WifiMode (j);
+	  return true;
+	}
+      j++;
+    }
+  return false;
+}
+
 uint32_t
 WifiModeFactory::AllocateUid (std::string uniqueUid)
 {
@@ -169,7 +198,13 @@
 WifiModeFactory *
 WifiModeFactory::GetFactory (void)
 {
+  static bool isFirstTime = true;
   static WifiModeFactory factory;
+  if (isFirstTime)
+    {
+      factory.AllocateUid ("Invalid-WifiMode");
+      isFirstTime = false;
+    }
   return &factory;
 }
 
--- a/src/devices/wifi/wifi-mode.h	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/wifi-mode.h	Sat Mar 01 21:21:53 2008 +0100
@@ -24,6 +24,7 @@
 #include <string>
 #include <vector>
 #include <ostream>
+#include "ns3/attribute-helper.h"
 
 namespace ns3 {
 
@@ -105,6 +106,8 @@
    * its initialization.
    */
   WifiMode ();
+
+  VALUE_HELPER_HEADER_1 (WifiMode);
 private:
   friend class WifiModeFactory;
   WifiMode (uint32_t uid);
@@ -113,6 +116,9 @@
 
 bool operator == (const WifiMode &a, const WifiMode &b);
 std::ostream & operator << (std::ostream & os, const WifiMode &mode);
+std::istream & operator >> (std::istream &is, WifiMode &mode);
+
+VALUE_HELPER_HEADER_2 (WifiMode);
 
 /**
  * \brief create WifiMode class instances and keep track of them.
@@ -159,8 +165,10 @@
 			     uint32_t dataRate,
 			     uint32_t phyRate,
 			     uint8_t constellationSize);
+
 private:
   friend class WifiMode;  
+  friend std::istream & operator >> (std::istream &is, WifiMode &mode);
   static WifiModeFactory *GetFactory ();
   WifiModeFactory ();
 
@@ -179,6 +187,7 @@
     bool isMandatory;
   };
 
+  bool Search (std::string name, WifiMode *mode);
   uint32_t AllocateUid (std::string uniqueName);
   WifiModeItem *Get (uint32_t uid);
 
--- a/src/devices/wifi/wifi-net-device.cc	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/wifi-net-device.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -17,345 +17,74 @@
  *
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
-#include "ns3/packet.h"
-#include "ns3/llc-snap-header.h"
-#include "ns3/node.h"
-#include "ns3/composite-trace-resolver.h"
-
 #include "wifi-net-device.h"
+#include "wifi-mac.h"
 #include "wifi-phy.h"
+#include "wifi-remote-station-manager.h"
 #include "wifi-channel.h"
-#include "mac-stations.h"
-#include "mac-low.h"
-#include "wifi-mac-parameters.h"
-#include "mac-rx-middle.h"
-#include "mac-tx-middle.h"
-#include "mac-high-adhoc.h"
-#include "mac-high-nqsta.h"
-#include "mac-high-nqap.h"
-#include "dca-txop.h"
-#include "dcf-manager.h"
-#include "wifi-default-parameters.h"
-#include "arf-mac-stations.h"
-#include "aarf-mac-stations.h"
-#include "ideal-mac-stations.h"
-#include "cr-mac-stations.h"
-#include "onoe-mac-stations.h"
-#include "amrr-mac-stations.h"
-#include "rraa-mac-stations.h"
+#include "ns3/llc-snap-header.h"
+#include "ns3/packet.h"
+#include "ns3/uinteger.h"
+#include "ns3/node.h"
+#include "ns3/trace-source-accessor.h"
 
 namespace ns3 {
 
-/***************************************************************
- *         hold an enumeration of the trace types
- ***************************************************************/
-
-WifiNetDeviceTraceType::WifiNetDeviceTraceType ()
-  : m_type (RX)
-{}
-
-WifiNetDeviceTraceType::WifiNetDeviceTraceType (enum Type type)
-  : m_type (type)
-{}
-enum WifiNetDeviceTraceType::Type 
-WifiNetDeviceTraceType::Get (void) const
-{
-  return m_type;
-}
-uint16_t 
-WifiNetDeviceTraceType::GetUid (void)
-{
-  static uint16_t uid = AllocateUid<WifiNetDeviceTraceType> ("ns3::WifiNetDeviceTraceType");
-  return uid;
-}
-void 
-WifiNetDeviceTraceType::Print (std::ostream &os) const
+TypeId 
+WifiNetDevice::GetTypeId (void)
 {
-  os << "event=";
-  switch (m_type) {
-  case RX: 
-    os << "rx"; 
-    break;
-  case TX: 
-    os << "tx";
-    break;
-  }
-}
-std::string 
-WifiNetDeviceTraceType::GetTypeName (void) const
-{
-   return "ns3::WifiNetDeviceTraceType";
-}
-
-/***************************************************************
- *         a static helper
- ***************************************************************/
-
-static WifiMode 
-GetWifiModeForPhyMode (Ptr<WifiPhy> phy, enum WifiDefaultParameters::PhyModeParameter mode)
-{
-  uint32_t phyRate = (uint32_t)mode;
-  for (uint32_t i= 0; i < phy->GetNModes (); i++)
-    {
-      WifiMode mode = phy->GetMode (i);
-      if (mode.GetDataRate () == phyRate)
-        {
-          return mode;
-        }
-    }
-  NS_ASSERT (false);
-  return WifiMode ();
+  static TypeId tid = TypeId ("WifiNetDevice")
+    .SetParent<NetDevice> ()
+    .AddTraceSource ("Rx", "XXX",
+                     MakeTraceSourceAccessor (&WifiNetDevice::m_rxLogger))
+    .AddTraceSource ("Tx", "XXX",
+                     MakeTraceSourceAccessor (&WifiNetDevice::m_txLogger))
+    ;
+  return tid;
 }
 
-/***************************************************************
- *         Listener for Nav events. Forwards to DcfManager
- ***************************************************************/
-
-class WifiNetDevice::NavListener : public ns3::MacLowNavListener {
-public:
-  NavListener (ns3::DcfManager *dcf)
-    : m_dcf (dcf) {}
-  virtual ~NavListener () {}
-  virtual void NavStart (Time duration) {
-    m_dcf->NotifyNavStartNow (duration);
-  }
-  virtual void NavReset (Time duration) {
-    m_dcf->NotifyNavResetNow (duration);
-  }
-private:
-  ns3::DcfManager *m_dcf;
-};
-
-/***************************************************************
- *         Listener for PHY events. Forwards to DcfManager
- ***************************************************************/
-
-class WifiNetDevice::PhyListener : public ns3::WifiPhyListener {
-public:
-  PhyListener (ns3::DcfManager *dcf)
-    : m_dcf (dcf) {}
-  virtual ~PhyListener () {}
-  virtual void NotifyRxStart (Time duration) {
-    m_dcf->NotifyRxStartNow (duration);
-  }
-  virtual void NotifyRxEndOk (void) {
-    m_dcf->NotifyRxEndOkNow ();
-  }
-  virtual void NotifyRxEndError (void) {
-    m_dcf->NotifyRxEndErrorNow ();
-  }
-  virtual void NotifyTxStart (Time duration) {
-    m_dcf->NotifyTxStartNow (duration);
-  }
-  virtual void NotifyCcaBusyStart (Time duration) {
-    m_dcf->NotifyCcaBusyStartNow (duration);
-  }
-private:
-  ns3::DcfManager *m_dcf;
-};
-
-/***************************************************************
- *              The NetDevice itself
- ***************************************************************/
-
-
-
-WifiNetDevice::WifiNetDevice (Ptr<Node> node, Mac48Address self)
-  : m_node (node),
-    m_address (self),
-    m_name (""),
-    m_linkUp (false)
-{
-  Construct ();
-}
-
+WifiNetDevice::WifiNetDevice ()
+{}
 WifiNetDevice::~WifiNetDevice ()
 {}
-
-void
-WifiNetDevice::Construct (void)
-{
-  m_mtu = 2300;
-  // the physical layer.
-  m_phy = Create<WifiPhy> (this);
-
-  // the rate control algorithm
-  switch (WifiDefaultParameters::GetRateControlAlgorithm ()) {
-  case WifiDefaultParameters::ARF:
-    m_stations = new ArfMacStations (m_phy->GetMode (0), 
-                                     WifiDefaultParameters::GetArfRateControlTimerThreshold (),
-                                     WifiDefaultParameters::GetArfRateControlSuccessThreshold ());
-    break;
-  case WifiDefaultParameters::AARF:
-    m_stations = new AarfMacStations (m_phy->GetMode (0),
-                                      WifiDefaultParameters::GetAarfRateControlMinTimerThreshold (),
-                                      WifiDefaultParameters::GetAarfRateControlMinSuccessThreshold (),
-                                      WifiDefaultParameters::GetAarfRateControlSuccessK (),
-                                      WifiDefaultParameters::GetAarfRateControlMaxSuccessThreshold (),
-                                      WifiDefaultParameters::GetAarfRateControlTimerK ());
-    break;
-  case WifiDefaultParameters::CONSTANT_RATE: {
-    WifiMode dataRate = GetWifiModeForPhyMode (m_phy, WifiDefaultParameters::GetConstantDataRate ());
-    WifiMode ctlRate = GetWifiModeForPhyMode (m_phy, WifiDefaultParameters::GetConstantCtlRate ());
-    m_stations = new CrMacStations (dataRate, ctlRate);
-  } break;
-  case WifiDefaultParameters::IDEAL: {
-    double ber = WifiDefaultParameters::GetIdealRateControlBer ();
-    IdealMacStations *ideal = new IdealMacStations (m_phy->GetMode (0));
-    uint32_t nModes = m_phy->GetNModes ();
-    for (uint32_t i = 0; i < nModes; i++) 
-      {
-        WifiMode mode = m_phy->GetMode (i);
-        ideal->AddModeSnrThreshold (mode, m_phy->CalculateSnr (mode, ber));
-      }
-    m_stations = ideal;
-  } break;
-  case WifiDefaultParameters::ONOE: {
-    m_stations = new OnoeMacStations (m_phy->GetMode (0));
-  } break;
-  case WifiDefaultParameters::AMRR: {
-    m_stations = new AmrrMacStations (m_phy->GetMode (0));
-  } break;
-  case WifiDefaultParameters::RRAA: {
-    m_stations = new RraaMacStations (m_phy->GetMode (0));
-  } break;
-  default:
-    // NOTREACHED
-    NS_ASSERT (false);
-    break;
-  }
-
-  // WifiMacParameters
-  WifiMacParameters *parameters = new WifiMacParameters ();
-  m_parameters = parameters;
-  m_stations->SetParameters (m_parameters);
-
-  // the MacLow
-  Ptr<MacLow> low = CreateObject<MacLow> ();
-  low->SetDevice (this);
-  low->SetPhy (m_phy);
-  low->SetStations (m_stations);
-  low->SetParameters (m_parameters);
-  m_phy->SetReceiveOkCallback (MakeCallback (&MacLow::ReceiveOk, low));
-  m_phy->SetReceiveErrorCallback (MakeCallback (&MacLow::ReceiveError, low));
-  m_low = low;
-
-  // the 'middle' rx
-  MacRxMiddle *rxMiddle = new MacRxMiddle ();
-  low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, rxMiddle));
-  m_rxMiddle = rxMiddle;
-
-  // the 'middle' tx
-  MacTxMiddle *txMiddle = new MacTxMiddle ();
-  m_txMiddle = txMiddle;
-
-  m_manager = new DcfManager ();
-  Time ackTxDuration = m_phy->CalculateTxDuration (8 * (2+2+6+4), m_phy->GetMode (0), WIFI_PREAMBLE_LONG);
-  m_manager->SetAckTxDuration (ackTxDuration);
-  m_manager->SetSlotTime (m_parameters->GetSlotTime ());
-  m_manager->SetSifs (m_parameters->GetSifs ());
-  m_phyListener = new WifiNetDevice::PhyListener (m_manager);
-  m_phy->RegisterListener (m_phyListener);
-  m_navListener = new WifiNetDevice::NavListener (m_manager);
-  m_low->RegisterNavListener (m_navListener);
-}
-
-Ptr<DcaTxop>
-WifiNetDevice::CreateDca (uint32_t minCw, uint32_t maxCw, uint32_t aifsn) const
+  
+void 
+WifiNetDevice::Setup (Ptr<Node> node, Ptr<WifiMac> mac, Ptr<WifiPhy> phy,
+                      Ptr<WifiRemoteStationManager> manager,
+                      Ptr<WifiChannel> channel)
 {
-  Ptr<DcaTxop> dca = CreateObject<DcaTxop> (minCw, maxCw, aifsn, m_manager);
-  dca->SetParameters (m_parameters);
-  dca->SetTxMiddle (m_txMiddle);
-  dca->SetLow (m_low);
-  dca->SetStations (m_stations);
-  dca->SetMaxQueueSize (400);
-  dca->SetMaxQueueDelay (Seconds (10));
-  return dca;
-}
+  m_node = node;
+  m_mac = mac;
+  m_phy = phy;
+  m_stationManager = manager;
+
+  manager->SetupPhy (phy);
 
-Ptr<TraceResolver> 
-WifiNetDevice::GetTraceResolver (void) const
-{
-  Ptr<CompositeTraceResolver> resolver = 
-    Create<CompositeTraceResolver> ();
-  resolver->AddSource ("rx", 
-                       TraceDoc ("Receive a packet",
-                                 "Packet", "the packet received",
-                                 "Mac48Address", "the sender of the packet"),
-                       m_rxLogger,
-                       WifiNetDeviceTraceType (WifiNetDeviceTraceType::RX));
-  resolver->AddSource ("tx", 
-                       TraceDoc ("Send a packet",
-                                 "Packet", "the packet to send",
-                                 "Mac48Address", "the destination of the packet"),
-                       m_txLogger,
-                       WifiNetDeviceTraceType (WifiNetDeviceTraceType::TX));
-  resolver->AddComposite ("phy", m_phy);
-  resolver->AddComposite ("maclow", m_low);
-  resolver->SetParentResolver (NetDevice::GetTraceResolver ());
-  return resolver;
-}
-
-void 
-WifiNetDevice::Attach (Ptr<WifiChannel> channel)
-{
-  m_channel = channel;
-  m_phy->SetChannel (channel);
-  NotifyAttached ();
-}
-void 
-WifiNetDevice::DoForwardUp (Ptr<Packet> packet, const Mac48Address &from)
-{
-  m_rxLogger (packet, from);
+  m_mac->SetWifiRemoteStationManager (manager);
+  m_mac->SetWifiPhy (m_phy);
+  m_mac->SetForwardUpCallback (MakeCallback (&WifiNetDevice::ForwardUp, this));
+  m_mac->SetLinkUpCallback (MakeCallback (&WifiNetDevice::LinkUp, this));
+  m_mac->SetLinkDownCallback (MakeCallback (&WifiNetDevice::LinkDown, this));
+  channel->Add (this, m_phy);
 
-  LlcSnapHeader llc;
-  packet->RemoveHeader (llc);
-  m_rxCallback (this, packet, llc.GetType (), from);
+  m_phy->SetChannel (channel);
+  //XXX
+  //m_stationManager->
 }
-Mac48Address 
-WifiNetDevice::GetSelfAddress (void) const
-{
-  NS_ASSERT (Mac48Address::IsMatchingType (GetAddress ()));
-  Mac48Address self = Mac48Address::ConvertFrom (GetAddress ());
-  return self;
-}
-void 
-WifiNetDevice::DoDispose (void)
+Ptr<WifiMac> 
+WifiNetDevice::GetMac (void) const
 {
-  // cleanup local
-  m_node = 0;
-  m_channel = 0;
-  delete m_stations;
-  delete m_rxMiddle;
-  delete m_txMiddle;
-  delete m_parameters;
-  delete m_manager;
-  delete m_phyListener;
-  delete m_navListener;
-  m_phy = 0;
-  m_stations = 0;
-  m_low = 0;
-  m_rxMiddle = 0;
-  m_txMiddle = 0;
-  m_parameters = 0;
-  // chain up.
-  NetDevice::DoDispose ();
+  return m_mac;
 }
-
-void
-WifiNetDevice::NotifyLinkUp (void)
+Ptr<WifiPhy> 
+WifiNetDevice::GetPhy (void) const
 {
-  m_linkUp = true;
-  if (!m_linkChangeCallback.IsNull ())
-    {
-      m_linkChangeCallback ();
-    }
+  return m_phy;
 }
-void
-WifiNetDevice::NotifyLinkDown (void)
+Ptr<WifiRemoteStationManager> 
+WifiNetDevice::GetRemoteStationManager (void) const
 {
-  m_linkUp = false;
-  m_linkChangeCallback ();
+  return m_stationManager;
 }
 
 void 
@@ -381,43 +110,53 @@
 Ptr<Channel> 
 WifiNetDevice::GetChannel (void) const
 {
-  return m_channel;
+  return m_phy->GetChannel ();
 }
 Address 
 WifiNetDevice::GetAddress (void) const
 {
-  return m_address;
+  return m_mac->GetAddress ();
 }
 bool 
 WifiNetDevice::SetMtu (const uint16_t mtu)
 {
+  Uinteger maxMsduSize = m_mac->GetAttribute ("MaxMsduSize");
+  if (mtu > maxMsduSize && mtu > 0)
+    {
+      return false;
+    }
   m_mtu = mtu;
   return true;
 }
 uint16_t 
 WifiNetDevice::GetMtu (void) const
 {
+  if (m_mtu == 0)
+    {
+      Uinteger maxMsduSize = m_mac->GetAttribute ("MaxMsduSize");
+      m_mtu = maxMsduSize;
+    }
   return m_mtu;
 }
 bool 
 WifiNetDevice::IsLinkUp (void) const
 {
-  return m_linkUp;
+  return m_phy != 0 && m_linkUp;
 }
 void 
 WifiNetDevice::SetLinkChangeCallback (Callback<void> callback)
 {
-  m_linkChangeCallback = callback;
+  m_linkChange = callback;
 }
 bool 
 WifiNetDevice::IsBroadcast (void) const
 {
   return true;
 }
-Address
+Address 
 WifiNetDevice::GetBroadcast (void) const
 {
-  return Mac48Address ("ff:ff:ff:ff:ff:ff");
+  return Mac48Address::GetBroadcast ();
 }
 bool 
 WifiNetDevice::IsMulticast (void) const
@@ -432,7 +171,7 @@
 Address 
 WifiNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
 {
-  return Mac48Address ("01:00:5e:00:00:00");
+  return GetMulticast ();
 }
 bool 
 WifiNetDevice::IsPointToPoint (void) const
@@ -440,11 +179,11 @@
   return false;
 }
 bool 
-WifiNetDevice::Send(Ptr<Packet> packet, const Address& to, uint16_t protocolNumber)
+WifiNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
 {
-  NS_ASSERT (Mac48Address::IsMatchingType (to));
+  NS_ASSERT (Mac48Address::IsMatchingType (dest));
 
-  Mac48Address realTo = Mac48Address::ConvertFrom (to);
+  Mac48Address realTo = Mac48Address::ConvertFrom (dest);
 
   LlcSnapHeader llc;
   llc.SetType (protocolNumber);
@@ -452,7 +191,8 @@
 
   m_txLogger (packet, realTo);
 
-  return DoSendTo (packet, realTo);
+  m_mac->Enqueue (packet, realTo);
+  return true;
 }
 Ptr<Node> 
 WifiNetDevice::GetNode (void) const
@@ -467,276 +207,35 @@
 void 
 WifiNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
 {
-  m_rxCallback = cb;
-}
-
-
-/*****************************************************
- *            Adhoc code
- *****************************************************/
-
-AdhocWifiNetDevice::AdhocWifiNetDevice (Ptr<Node> node, Mac48Address self)
-  : WifiNetDevice (node, self)
-{
-  DoConstruct ();
-}
-void
-AdhocWifiNetDevice::DoConstruct (void)
-{
-  m_ssid = WifiDefaultParameters::GetSsid ();
-  m_dca = CreateDca (15, 1023, 2);
-
-  MacHighAdhoc *high = new MacHighAdhoc ();
-  high->SetDevice (this);
-  high->SetDcaTxop (m_dca);
-  high->SetForwardCallback (MakeCallback (&AdhocWifiNetDevice::DoForwardUp, 
-                                          static_cast<WifiNetDevice *> (this)));
-  high->SetPhy (m_phy);
-  high->SetStations (m_stations);
-  m_rxMiddle->SetForwardCallback (MakeCallback (&MacHighAdhoc::Receive, high));
-  m_high = high;
+  m_forwardUp = cb;
 }
 
-AdhocWifiNetDevice::~AdhocWifiNetDevice ()
-{}
-Mac48Address 
-AdhocWifiNetDevice::GetBssid (void) const
-{
-  return m_high->GetBssid ();
-}
-Ssid 
-AdhocWifiNetDevice::GetSsid (void) const
-{
-  return m_ssid;
-}
-void 
-AdhocWifiNetDevice::SetSsid (Ssid ssid)
-{
-  // XXX restart adhoc network join.
-  m_ssid = ssid;
-}
-bool
-AdhocWifiNetDevice::DoSendTo (Ptr<const Packet> packet, Mac48Address const &to)
+void
+WifiNetDevice::ForwardUp (Ptr<Packet> packet, const Mac48Address &from)
 {
-  m_high->Enqueue (packet, to);
-  return true;
-}
-void
-AdhocWifiNetDevice::NotifyAttached (void)
-{
-  NotifyLinkUp ();
-}
-void 
-AdhocWifiNetDevice::DoDispose (void)
-{
-  // chain up.
-  WifiNetDevice::DoDispose ();
-  // local cleanup
-  delete m_high;
-  m_dca = 0;
-  m_high = 0;
-}
-Ptr<TraceResolver> 
-AdhocWifiNetDevice::GetTraceResolver (void) const
-{
-  Ptr<CompositeTraceResolver> resolver = 
-    Create<CompositeTraceResolver> ();
-  resolver->AddComposite ("dca", m_dca);
-  resolver->SetParentResolver (WifiNetDevice::GetTraceResolver ());
-  return resolver;
+  LlcSnapHeader llc;
+  packet->RemoveHeader (llc);
+  m_forwardUp (this, packet, llc.GetType (), from);
+  m_rxLogger (packet, from);
 }
 
-
-/*****************************************************
- *            STA code
- *****************************************************/
-
-NqstaWifiNetDevice::NqstaWifiNetDevice (Ptr<Node> node, Mac48Address self)
-  : WifiNetDevice (node, self)
-{
-  DoConstruct ();
-}
 void
-NqstaWifiNetDevice::DoConstruct (void)
+WifiNetDevice::LinkUp (void)
 {
-  m_ssid = WifiDefaultParameters::GetSsid ();
-  m_dca = CreateDca (15, 1023, 2);
-  
-  MacHighNqsta *high = new MacHighNqsta ();
-  high->SetDevice (this);
-  high->SetDcaTxop (m_dca);
-  high->SetForwardCallback (MakeCallback (&NqstaWifiNetDevice::DoForwardUp, 
-                                          this));
-  high->SetAssociatedCallback (MakeCallback (&NqstaWifiNetDevice::Associated, 
-                                             this));
-  high->SetDisAssociatedCallback (MakeCallback (&NqstaWifiNetDevice::DisAssociated, 
-                                                this));
-  high->SetStations (m_stations);
-  high->SetPhy (m_phy);
-  m_rxMiddle->SetForwardCallback (MakeCallback (&MacHighNqsta::Receive, high));
-  m_high = high;
-}
-
-NqstaWifiNetDevice::~NqstaWifiNetDevice ()
-{}
-Mac48Address 
-NqstaWifiNetDevice::GetBssid (void) const
-{
-  return m_high->GetBssid ();
-}
-Ssid 
-NqstaWifiNetDevice::GetSsid (void) const
-{
-  return m_ssid;
-}
-void 
-NqstaWifiNetDevice::StartActiveAssociation (Ssid ssid)
-{
-  m_ssid = ssid;
-  m_high->StartActiveAssociation ();
-}
-bool
-NqstaWifiNetDevice::DoSendTo (Ptr<const Packet> packet, Mac48Address const &to)
-{
-  m_high->Queue (packet, to);
-  return true;
+  m_linkUp = true;
+  if (!m_linkChange.IsNull ())
+    {
+      m_linkChange ();
+    }
 }
 void
-NqstaWifiNetDevice::NotifyAttached (void)
-{
-  // do nothing because link status is kept track of in
-  // ::Associated and ::Disassociated
-}
-void 
-NqstaWifiNetDevice::Associated (void)
-{
-  WifiNetDevice::NotifyLinkUp ();
-}
-
-void 
-NqstaWifiNetDevice::DisAssociated (void)
-{
-  WifiNetDevice::NotifyLinkDown ();
-}
-void 
-NqstaWifiNetDevice::DoDispose (void)
-{
-  // chain up.
-  WifiNetDevice::DoDispose ();
-  // local cleanup
-  delete m_high;
-  m_dca = 0;
-  m_high = 0;
-}
-
-Ptr<TraceResolver> 
-NqstaWifiNetDevice::GetTraceResolver (void) const
+WifiNetDevice::LinkDown (void)
 {
-  Ptr<CompositeTraceResolver> resolver = 
-    Create<CompositeTraceResolver> ();
-  resolver->AddComposite ("dca", m_dca);
-  resolver->SetParentResolver (WifiNetDevice::GetTraceResolver ());
-  return resolver;
-}
-
-/*****************************************************
- *            AP code
- *****************************************************/
-
-
-NqapWifiNetDevice::NqapWifiNetDevice (Ptr<Node> node, Mac48Address self)
-  : WifiNetDevice (node, self)
-{
-  DoConstruct ();
-
-}
-void
-NqapWifiNetDevice::DoConstruct (void)
-{
-  m_ssid = WifiDefaultParameters::GetSsid ();
-
-  // The Beacon DCA is higher priority than
-  // the normal DCA so, we create it first.
-  m_beaconDca = CreateDca (0, 0, 1);
-  m_dca = CreateDca (15, 1023, 2);
-
-  // By default, we configure the Basic Rate Set to be the set
-  // of rates we support which are mandatory.
-  // This could be trivially made user-configurable
-  for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+  m_linkUp = false;
+  if (!m_linkChange.IsNull ())
     {
-      WifiMode mode = m_phy->GetMode (i);
-      if (mode.IsMandatory ())
-        {
-          m_stations->AddBasicMode (mode);
-        }
-    }  
-
-  MacHighNqap *high = new MacHighNqap ();
-  high->SetDevice (this);
-  high->SetDcaTxop (m_dca);
-  high->SetBeaconDcaTxop (m_beaconDca);
-  high->SetStations (m_stations);
-  high->SetPhy (m_phy);
-  high->SetForwardCallback (MakeCallback (&NqapWifiNetDevice::DoForwardUp, 
-                                          this));
-  m_rxMiddle->SetForwardCallback (MakeCallback (&MacHighNqap::Receive, high));
-  m_high = high;
-}
-NqapWifiNetDevice::~NqapWifiNetDevice ()
-{}
-Mac48Address 
-NqapWifiNetDevice::GetBssid (void) const
-{
-  return GetSelfAddress ();
-}
-Ssid 
-NqapWifiNetDevice::GetSsid (void) const
-{
-  return m_ssid;
-}
-void 
-NqapWifiNetDevice::SetSsid (Ssid ssid)
-{
-  m_ssid = ssid;
-}
-void
-NqapWifiNetDevice::StartBeaconing (void)
-{
-  m_high->StartBeaconing ();
-}
-bool
-NqapWifiNetDevice::DoSendTo (Ptr<const Packet> packet, Mac48Address const & to)
-{
-  m_high->Queue (packet, to);
-  return true;
-}
-void
-NqapWifiNetDevice::NotifyAttached (void)
-{
-  NotifyLinkUp ();
-}
-void 
-NqapWifiNetDevice::DoDispose (void)
-{
-  // chain up.
-  WifiNetDevice::DoDispose ();
-  // local cleanup
-  delete m_high;
-  m_dca = 0;
-  m_high = 0;
-  m_beaconDca = 0;
-}
-
-Ptr<TraceResolver> 
-NqapWifiNetDevice::GetTraceResolver (void) const
-{
-  Ptr<CompositeTraceResolver> resolver = 
-    Create<CompositeTraceResolver> ();
-  resolver->AddComposite ("dca", m_dca);
-  resolver->AddComposite ("beaconDca", m_beaconDca);
-  resolver->SetParentResolver (WifiNetDevice::GetTraceResolver ());
-  return resolver;
+      m_linkChange ();
+    }
 }
 
 } // namespace ns3
--- a/src/devices/wifi/wifi-net-device.h	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/wifi-net-device.h	Sat Mar 01 21:21:53 2008 +0100
@@ -23,80 +23,37 @@
 
 #include "ns3/net-device.h"
 #include "ns3/packet.h"
-#include "ns3/callback-trace-source.h"
+#include "ns3/traced-callback.h"
 #include "ns3/mac48-address.h"
-#include "ssid.h"
+#include "wifi-remote-station-manager.h"
 #include <string>
 
 namespace ns3 {
 
 class WifiChannel;
 class WifiPhy;
-class MacStations;
-class MacLow;
-class MacRxMiddle;
-class MacTxMiddle;
-class WifiMacParameters;
-class DcaTxop;
-class MacHighAdhoc;
-class MacHighNqsta;
-class MacHighNqap;
-class DcfManager;
-
-/**
- * \brief hold the type of trace event generated by 
- * a WifiNetDevice.
- */
-class WifiNetDeviceTraceType : public TraceContextElement
-{
-public:
-  enum Type {
-    RX,
-    TX
-  };
-  WifiNetDeviceTraceType ();
-  WifiNetDeviceTraceType (enum Type type);
-  /**
-   * \returns the type of event
-   */
-  enum Type Get (void) const;
-
-  static uint16_t GetUid (void);
-  void Print (std::ostream &os) const;
-  std::string GetTypeName (void) const;
-private:
-  enum Type m_type;
-};
+class WifiMac;
 
 /**
  * \brief the base class for 802.11 network interfaces
  *
  */
-class WifiNetDevice : public NetDevice {
+class WifiNetDevice : public NetDevice 
+{
 public:
+  static TypeId GetTypeId (void);
+
+  WifiNetDevice ();
   virtual ~WifiNetDevice ();
 
-  /**
-   * \param channel the channel to connect this 802.11 
-   *        interface to.
-   */
-  void Attach (Ptr<WifiChannel> channel);
+  
+  void Setup (Ptr<Node> node, Ptr<WifiMac> mac, Ptr<WifiPhy> phy,
+              Ptr<WifiRemoteStationManager> manager,
+              Ptr<WifiChannel> channel);
+  Ptr<WifiMac> GetMac (void) const;
+  Ptr<WifiPhy> GetPhy (void) const;
+  Ptr<WifiRemoteStationManager> GetRemoteStationManager (void) const;
 
-  /**
-   * \returns the Mac48Address of this 802.11 interface.
-   *
-   * This method is equivalent to NetDevice::GetAddress. The only
-   * difference is its return type.
-   */
-  Mac48Address GetSelfAddress (void) const;
-  /**
-   * \returns the bssid of this 802.11 interface.
-   */
-  virtual Mac48Address GetBssid (void) const = 0;
-  /**
-   * \returns the ssid of this 802.11 interface.
-   */
-  virtual Ssid GetSsid (void) const = 0;
 
   // inherited from NetDevice base class.
   virtual void SetName(const std::string name);
@@ -121,162 +78,21 @@
   virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
 
 private:
-  class PhyListener;
-  class NavListener;
-
-  // defined for children
-  virtual void NotifyAttached (void) = 0;
-  virtual bool DoSendTo (Ptr<const Packet> packet, const Mac48Address &to) = 0;
-  // private helper
-  void Construct (void);
-
-  CallbackTraceSource<Ptr<const Packet>, Mac48Address> m_rxLogger;
-  CallbackTraceSource<Ptr<const Packet>, Mac48Address> m_txLogger;
-protected:
-  WifiNetDevice (Ptr<Node> node, Mac48Address self);
-  void DoForwardUp (Ptr<Packet> packet, const Mac48Address &from);
-  Ptr<DcaTxop> CreateDca (uint32_t minCw, uint32_t maxCw, uint32_t aifsn) const;
-  void NotifyLinkUp (void);
-  void NotifyLinkDown (void);
-  // inherited from Object
-  virtual void DoDispose (void);
-  // inherited from Object
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
-
-  Ptr<WifiChannel> m_channel;
+  void ForwardUp (Ptr<Packet> packet, const Mac48Address &from);
+  void LinkUp (void);
+  void LinkDown (void);
+  Ptr<Node> m_node;
   Ptr<WifiPhy> m_phy;
-  MacStations *m_stations;
-  Ptr<MacLow> m_low;
-  MacRxMiddle *m_rxMiddle;
-  MacTxMiddle *m_txMiddle;
-  WifiMacParameters *m_parameters;
-  DcfManager *m_manager;
-  PhyListener *m_phyListener;
-  NavListener *m_navListener;
-
-  Ptr<Node> m_node;
-  Mac48Address m_address;
-  NetDevice::ReceiveCallback m_rxCallback;
+  Ptr<WifiMac> m_mac;
+  Ptr<WifiRemoteStationManager> m_stationManager;
+  Callback <bool,Ptr<NetDevice>,Ptr<Packet>,uint16_t,const Address &> m_forwardUp;
+  TracedCallback<Ptr<const Packet>, Mac48Address> m_rxLogger;
+  TracedCallback<Ptr<const Packet>, Mac48Address> m_txLogger;
   uint32_t m_ifIndex;
   std::string m_name;
   bool m_linkUp;
-  Callback<void> m_linkChangeCallback;
-  uint16_t m_mtu;
-};
-
-/**
- * \brief a 802.11 adhoc network interface
- *
- * This network interface is a very simple pass-through 
- * from the higher layers down to the MAC DCF layer.
- */
-class AdhocWifiNetDevice : public WifiNetDevice {
-public:
-  AdhocWifiNetDevice (Ptr<Node> node, Mac48Address self);
-  virtual ~AdhocWifiNetDevice ();
-
-  virtual Mac48Address GetBssid (void) const;
-  virtual Ssid GetSsid (void) const;
-  void SetSsid (Ssid ssid);
-
-protected:
-  // inherited from Object
-  virtual void DoDispose (void);
-private:
-  void DoConstruct (void);
-  void ForwardUp (void);
-  // inherited from WifiNetDefice
-  virtual bool DoSendTo (Ptr<const Packet> packet, Mac48Address const & to);
-  virtual void NotifyAttached (void);
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
-
-  Ssid m_ssid;
-  Ptr<DcaTxop> m_dca;
-  MacHighAdhoc *m_high;
-};
-
-/**
- * \brief a 802.11 STA network interface 
- *
- * This network interface implements the MAC-level STA 
- * active probing, association, and disassociation prototols.
- *
- * By default, it starts a new probing phase whenever a new 
- * data packet must be sent and the STA is not yet associated
- * to the AP.
- */
-class NqstaWifiNetDevice : public WifiNetDevice 
-{
-public:
-  /**
-   * The ssid is initialized from \valueref{WifiSsid}.
-   */
-  NqstaWifiNetDevice (Ptr<Node> node, Mac48Address self);
-  virtual ~NqstaWifiNetDevice ();
-
-  virtual Mac48Address GetBssid (void) const;
-  virtual Ssid GetSsid (void) const;
-
-  /**
-   * \param ssid the ssid we want to associate with
-   *
-   * Start a new active probing phase with the specified
-   * ssid.
-   */
-  void StartActiveAssociation (Ssid ssid);
-protected:
-  // inherited from Object
-  virtual void DoDispose (void);
-private:
-  void DoConstruct (void);
-  void Associated (void);
-  void DisAssociated (void);
-  // inherited from WifiNetDefice
-  virtual bool DoSendTo (Ptr<const Packet> packet, Mac48Address const & to);
-  virtual void NotifyAttached (void);
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
-
-  Ssid m_ssid;
-  Ptr<DcaTxop> m_dca;
-  MacHighNqsta *m_high;
-};
-
-/**
- * \brief a 802.11 AP network interface
- *
- * This network interface implements the MAC-level
- * AP-side of the beacon, probing, and, association
- * protocols. By default, every STA which tries
- * to associate is accepted.
- */
-class NqapWifiNetDevice : public WifiNetDevice 
-{
-public:
-  /**
-   * The ssid is initialized from \valueref{WifiSsid}.
-   */
-  NqapWifiNetDevice (Ptr<Node> node);
-  NqapWifiNetDevice (Ptr<Node> node, Mac48Address self);
-  virtual ~NqapWifiNetDevice ();
-
-  virtual Mac48Address GetBssid (void) const;
-  virtual Ssid GetSsid (void) const;
-  void SetSsid (Ssid ssid);
-  void StartBeaconing (void);
-protected:
-  // inherited from Object
-  virtual void DoDispose (void);
-private:
-  void DoConstruct (void);
-  // inherited from WifiNetDefice
-  virtual bool DoSendTo (Ptr<const Packet> packet, Mac48Address const & to);
-  virtual void NotifyAttached (void);
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
-
-  Ssid m_ssid;
-  Ptr<DcaTxop> m_dca;
-  Ptr<DcaTxop> m_beaconDca;
-  MacHighNqap *m_high;
+  Callback<void> m_linkChange;
+  mutable uint16_t m_mtu;
 };
 
 } // namespace ns3
--- a/src/devices/wifi/wifi-phy.cc	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/wifi-phy.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -21,16 +21,17 @@
 #include "wifi-phy.h"
 #include "wifi-mode.h"
 #include "wifi-channel.h"
-#include "wifi-net-device.h"
 #include "wifi-preamble.h"
-#include "wifi-default-parameters.h"
 #include "ns3/simulator.h"
 #include "ns3/packet.h"
 #include "ns3/random-variable.h"
 #include "ns3/assert.h"
 #include "ns3/log.h"
-#include "ns3/composite-trace-resolver.h"
 #include "ns3/object-base.h"
+#include "ns3/double.h"
+#include "ns3/uinteger.h"
+#include "ns3/enum.h"
+#include "ns3/trace-source-accessor.h"
 #include <math.h>
 
 NS_LOG_COMPONENT_DEFINE ("WifiPhy");
@@ -176,15 +177,71 @@
  *       The actual WifiPhy class
  ****************************************************************/
 
-WifiPhy::WifiPhy (Ptr<WifiNetDevice> device)
-  : m_edThresholdW (DbmToW (WifiDefaultParameters::GetPhyEnergyDetectionThresholdDbm ())),
-    m_txGainDb (WifiDefaultParameters::GetPhyTxGainDb ()),
-    m_rxGainDb (WifiDefaultParameters::GetPhyRxGainDb ()),
-    m_rxNoiseRatio (DbToRatio (WifiDefaultParameters::GetPhyRxNoiseDb ())),
-    m_txPowerBaseDbm (WifiDefaultParameters::GetPhyTxPowerBaseDbm ()),
-    m_txPowerEndDbm (WifiDefaultParameters::GetPhyTxPowerEndDbm ()),
-    m_nTxPower (WifiDefaultParameters::GetPhyTxPowerLevels ()),
-    m_syncing (false),
+NS_OBJECT_ENSURE_REGISTERED (WifiPhy);
+
+TypeId 
+WifiPhy::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("WifiPhy")
+    .SetParent<Object> ()
+    .AddConstructor<WifiPhy> ()
+    .AddAttribute ("EnergyDetectionThreshold",
+                   "The energy of a received signal should be higher than "
+                   "this threshold (dbm) to allow the PHY layer to detect the signal.",
+                   Double (-140.0),
+                   MakeDoubleAccessor (&WifiPhy::SetEdThreshold,
+                                       &WifiPhy::GetEdThreshold),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TxGain",
+                   "Transmission gain (dB).",
+                   Double (1.0),
+                   MakeDoubleAccessor (&WifiPhy::SetTxGain,
+                                       &WifiPhy::GetTxGain),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("RxGain",
+                   "Reception gain (dB).",
+                   Double (1.0),
+                   MakeDoubleAccessor (&WifiPhy::SetRxGain,
+                                       &WifiPhy::GetRxGain),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TxPowerLevels",
+                   "Number of transmission power levels available between "
+                   "TxPowerBase and TxPowerEnd included.",
+                   Uinteger (1),
+                   MakeUintegerAccessor (&WifiPhy::m_nTxPower),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("TxPowerEnd",
+                   "Maximum available transmission level (dbm).",
+                   Double (16.0206),
+                   MakeDoubleAccessor (&WifiPhy::SetTxPowerEnd, 
+                                       &WifiPhy::GetTxPowerEnd),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TxPowerStart",
+                   "Minimum available transmission level (dbm).",
+                   Double (16.0206),
+                   MakeDoubleAccessor (&WifiPhy::SetTxPowerStart, 
+                                       &WifiPhy::GetTxPowerStart),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("RxNoise",
+                   "Ratio of energy lost by receiver (dB).",
+                   Double (7),
+                   MakeDoubleAccessor (&WifiPhy::SetRxNoise,
+                                       &WifiPhy::GetRxNoise),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("Standard", "XXX",
+                   Enum (WIFI_PHY_STANDARD_80211a),
+                   MakeEnumAccessor (&WifiPhy::SetStandard),
+                   MakeEnumChecker (WIFI_PHY_STANDARD_80211a, "802.11a",
+                                    WIFI_PHY_STANDARD_holland, "holland"))
+    .AddTraceSource ("State",
+                     "The WifiPhy state",
+                     MakeTraceSourceAccessor (&WifiPhy::m_stateLogger))
+    ;
+  return tid;
+}
+
+WifiPhy::WifiPhy ()
+  : m_syncing (false),
     m_endTx (Seconds (0)),
     m_endSync (Seconds (0)),
     m_endCcaBusy (Seconds (0)),
@@ -192,12 +249,22 @@
     m_startSync (Seconds (0)),
     m_startCcaBusy (Seconds (0)),
     m_previousStateChangeTime (Seconds (0)),
-    m_device (device),
     m_endSyncEvent (),
-    m_random (0.0, 1.0),
-    m_standard (WifiDefaultParameters::GetPhyStandard ())
+    m_random (0.0, 1.0)
+{}
+
+WifiPhy::~WifiPhy ()
 {
-  switch (m_standard) {
+  m_channel = 0;
+  m_events.clear ();
+  m_modes.clear ();
+}
+
+void
+WifiPhy::SetStandard (enum WifiPhyStandard standard)
+{
+  m_standard = standard;
+  switch (standard) {
   case WIFI_PHY_STANDARD_80211a:
     Configure80211a ();
     break;
@@ -210,40 +277,84 @@
   }
 }
 
-WifiPhy::~WifiPhy ()
+
+void 
+WifiPhy::SetRxNoise (double db)
+{
+  m_rxNoiseRatio = DbToRatio (db);
+}
+void 
+WifiPhy::SetTxPowerStart (double start)
 {
-  m_channel = 0;
-  m_events.clear ();
-  m_modes.clear ();
+  m_txPowerBaseDbm = start;
+}
+void 
+WifiPhy::SetTxPowerEnd (double end)
+{
+  m_txPowerEndDbm = end;
+}
+void 
+WifiPhy::SetNTxPower (uint32_t n)
+{
+  m_nTxPower = n;
+}
+void 
+WifiPhy::SetTxGain (double gain)
+{
+  m_txGainDb = gain;
 }
-
-Ptr<WifiNetDevice> 
-WifiPhy::GetDevice (void) const
+void 
+WifiPhy::SetRxGain (double gain)
+{
+  m_rxGainDb = gain;
+}
+void 
+WifiPhy::SetEdThreshold (double threshold)
+{
+  m_edThresholdW = DbmToW (threshold);
+}
+double 
+WifiPhy::GetRxNoise (void) const
 {
-  return m_device;
+  return RatioToDb (m_rxNoiseRatio);
+}
+double 
+WifiPhy::GetTxPowerStart (void) const
+{
+  return m_txPowerBaseDbm;
+}
+double 
+WifiPhy::GetTxPowerEnd (void) const
+{
+  return m_txPowerEndDbm;
+}
+double 
+WifiPhy::GetTxGain (void) const
+{
+  return m_txGainDb;
+}
+double 
+WifiPhy::GetRxGain (void) const
+{
+  return m_rxGainDb;
 }
 
-Ptr<TraceResolver> 
-WifiPhy::GetTraceResolver (void) const
+double 
+WifiPhy::GetEdThreshold (void) const
 {
-  Ptr<CompositeTraceResolver> resolver =
-    Create<CompositeTraceResolver> ();
-  resolver->AddSource ("state",
-                       TraceDoc ("The WifiPhy state",
-                                 "Time", "start time",
-                                 "Time", "duration", 
-                                 "enum WifiPhy::State", "the state of the PHY layer."),
-                       m_stateLogger);
-  resolver->SetParentResolver (Object::GetTraceResolver ());
-  return resolver;
+  return WToDbm (m_edThresholdW);
 }
 
+Ptr<WifiChannel> 
+WifiPhy::GetChannel (void) const
+{
+  return m_channel;
+}
 
 void 
 WifiPhy::SetChannel (Ptr<WifiChannel> channel)
 {
   m_channel = channel;
-  m_channel->Add (m_device, MakeCallback (&WifiPhy::ReceivePacket, this));
 }
 
 void 
@@ -257,10 +368,10 @@
   m_syncErrorCallback = callback;
 }
 void 
-WifiPhy::ReceivePacket (Ptr<Packet> packet, 
-                        double rxPowerDbm,
-                        WifiMode txMode,
-                        enum WifiPreamble preamble)
+WifiPhy::StartReceivePacket (Ptr<Packet> packet, 
+                             double rxPowerDbm,
+                             WifiMode txMode,
+                             enum WifiPreamble preamble)
 {
   rxPowerDbm += m_rxGainDb;
   double rxPowerW = DbmToW (rxPowerDbm);
@@ -361,7 +472,7 @@
   Time txDuration = CalculateTxDuration (packet->GetSize (), txMode, preamble);
   NotifyTxStart (txDuration);
   SwitchToTx (txDuration);
-  m_channel->Send (m_device, packet, GetPowerDbm (txPower) + m_txGainDb, txMode, preamble);
+  m_channel->Send (this, packet, GetPowerDbm (txPower) + m_txGainDb, txMode, preamble);
 }
 
 uint32_t 
@@ -375,7 +486,7 @@
   return m_modes[mode];
 }
 uint32_t 
-WifiPhy::GetNTxpower (void) const
+WifiPhy::GetNTxPower (void) const
 {
   return m_nTxPower;
 }
@@ -611,6 +722,18 @@
 }
 
 double
+WifiPhy::WToDbm (double w) const
+{
+  return 10.0 * log10(w * 1000.0);
+}
+
+double
+WifiPhy::RatioToDb (double ratio) const
+{
+  return 10.0 * log10(ratio);
+}
+
+double
 WifiPhy::GetEdThresholdW (void) const
 {
   return m_edThresholdW;
@@ -1113,7 +1236,7 @@
   }
   Time plcpHeaderStart = (*j).GetTime () + MicroSeconds (plcpPreambleDelayUs);
   Time plcpPayloadStart = plcpHeaderStart + 
-    Seconds (m_plcpHeaderLength / headerMode.GetDataRate ());
+    Seconds ((m_plcpHeaderLength + 0.0) / headerMode.GetDataRate ());
   double noiseInterferenceW = (*j).GetDelta ();
   double powerW = event->GetRxPowerW ();
 
--- a/src/devices/wifi/wifi-phy.h	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/wifi-phy.h	Sat Mar 01 21:21:53 2008 +0100
@@ -28,7 +28,7 @@
 #include "ns3/event-id.h"
 #include "ns3/packet.h"
 #include "ns3/object.h"
-#include "ns3/callback-trace-source.h"
+#include "ns3/traced-callback.h"
 #include "ns3/nstime.h"
 #include "ns3/ptr.h"
 #include "ns3/random-variable.h"
@@ -120,17 +120,30 @@
    */
   typedef Callback<void,Ptr<Packet>, double> SyncErrorCallback;
 
+  static TypeId GetTypeId (void);
+
+  WifiPhy ();
+  virtual ~WifiPhy ();
+
+  void SetStandard (enum WifiPhyStandard standard);
+  void SetRxNoise (double ratio);
+  void SetTxPowerStart (double start);
+  void SetTxPowerEnd (double end);
+  void SetNTxPower (uint32_t n);
+  void SetTxGain (double gain);
+  void SetRxGain (double gain);
+  void SetEdThreshold (double threshold);
+  double GetRxNoise (void) const;
+  double GetTxPowerStart (void) const;
+  double GetTxPowerEnd (void) const;
   /**
-   * \param device the device which contains this PHY.
-   *
-   * Create a new PHY layer instance initialized with values
-   * coming from \valueref{WifiPhyEnergyDetectionThreshold},
-   * \valueref{WifiPhyRxNoise}, \valueref{WifiPhyTxPowerBase},
-   * \valueref{WifiPhyTxPowerEnd}, \valueref{WifiPhyTxPowerLevels},
-   * \valueref{WifiPhyTxGain}, and, \valueref{WifiPhyRxGain}
+   * \returns the number of tx power levels available for this PHY.
    */
-  WifiPhy (Ptr<WifiNetDevice> device);
-  virtual ~WifiPhy ();
+  uint32_t GetNTxPower (void) const;
+  double GetTxGain (void) const;
+  double GetRxGain (void) const;
+  double GetEdThreshold (void) const;
+
 
   Ptr<WifiNetDevice> GetDevice (void) const;
 
@@ -219,10 +232,6 @@
    * \returns the mode whose index is specified.
    */
   WifiMode GetMode (uint32_t mode) const;
-  /**
-   * \returns the number of tx power levels available for this PHY.
-   */
-  uint32_t GetNTxpower (void) const;
   /* return snr: W/W */
   /**
    * \param txMode the transmission mode
@@ -232,6 +241,14 @@
    */
   double CalculateSnr (WifiMode txMode, double ber) const;
 
+  /* rxPower unit is Watt */
+  void StartReceivePacket (Ptr<Packet> packet,
+                           double rxPowerDbm,
+                           WifiMode mode,
+                           WifiPreamble preamble);
+
+  Ptr<WifiChannel> GetChannel (void) const;
+
 private:
   class NiChange {
   public:
@@ -249,8 +266,6 @@
   typedef std::vector <NiChange> NiChanges;
 
 private:
-  // inherited from ns3::Object.
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
   void Configure80211aParameters (void);
   void PrintModes (void) const;
   void Configure80211a (void);
@@ -260,6 +275,8 @@
   double GetEdThresholdW (void) const;
   double DbmToW (double dbm) const;
   double DbToRatio (double db) const;
+  double WToDbm (double w) const;
+  double RatioToDb (double ratio) const;
   Time GetMaxPacketDuration (void) const;
   void CancelRx (void);
   double GetPowerDbm (uint8_t power) const;
@@ -297,11 +314,6 @@
                        uint32_t m, uint32_t dfree,
                        uint32_t adFree, uint32_t adFreePlusOne) const;
   double GetChunkSuccessRate (WifiMode mode, double snr, uint32_t nbits) const;
-  /* rxPower unit is Watt */
-  void ReceivePacket (Ptr<Packet> packet,
-                      double rxPowerDbm,
-                      WifiMode mode,
-                      WifiPreamble preamble);
 private:
   uint64_t m_txPrepareDelayUs;
   uint64_t m_plcpLongPreambleDelayUs;
@@ -330,7 +342,6 @@
   Time m_previousStateChangeTime;
 
   Ptr<WifiChannel> m_channel;
-  Ptr<WifiNetDevice> m_device;
   SyncOkCallback m_syncOkCallback;
   SyncErrorCallback m_syncErrorCallback;
   Modes m_modes;
@@ -338,7 +349,7 @@
   EventId m_endSyncEvent;
   Events m_events;
   UniformVariable m_random;
-  CallbackTraceSource<Time,Time,enum WifiPhy::State> m_stateLogger;
+  TracedCallback<Time,Time,enum WifiPhy::State> m_stateLogger;
   WifiPhyStandard m_standard;
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/wifi-remote-station-manager.cc	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,623 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006,2007 INRIA
+ *
+ * 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 "wifi-remote-station-manager.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/tag.h"
+#include "ns3/boolean.h"
+#include "ns3/uinteger.h"
+#include "ns3/wifi-phy.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);
+  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 void ReportFinalRtsFailed (void);
+  virtual void ReportFinalDataFailed (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::ReportRxOk (double rxSnr, WifiMode txMode)
+{
+  NS_ASSERT (false);
+}
+void 
+NonUnicastWifiRemoteStation::ReportRtsFailed (void)
+{
+  NS_ASSERT (false);
+}
+void 
+NonUnicastWifiRemoteStation::ReportDataFailed (void)
+{
+  NS_ASSERT (false);
+}
+void 
+NonUnicastWifiRemoteStation::ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+  NS_ASSERT (false);
+}
+void 
+NonUnicastWifiRemoteStation::ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+{
+  NS_ASSERT (false);
+}
+void 
+NonUnicastWifiRemoteStation::ReportFinalRtsFailed (void)
+{}
+void 
+NonUnicastWifiRemoteStation::ReportFinalDataFailed (void)
+{}
+
+WifiMode 
+NonUnicastWifiRemoteStation::DoGetDataMode (uint32_t size)
+{
+  WifiMode mode = m_stations->GetBasicMode (0);
+  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 ("WifiRemoteStationManager")
+    .SetParent<Object> ()
+    .AddAttribute ("IsLowLatency", "XXX",
+                   Boolean (true),
+                   MakeBooleanAccessor (&WifiRemoteStationManager::m_isLowLatency),
+                   MakeBooleanChecker ())
+    .AddAttribute ("MaxSsrc", "XXX",
+                   Uinteger (7),
+                   MakeUintegerAccessor (&WifiRemoteStationManager::m_maxSsrc),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MaxSlrc", "XXX",
+                   Uinteger (7),
+                   MakeUintegerAccessor (&WifiRemoteStationManager::m_maxSlrc),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("RtsCtsThreshold", "XXX",
+                   Uinteger (1500),
+                   MakeUintegerAccessor (&WifiRemoteStationManager::m_rtsCtsThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("FragmentationThreshold", "XXX",
+                   Uinteger (1500),
+                   MakeUintegerAccessor (&WifiRemoteStationManager::m_fragmentationThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+  return tid;
+}
+
+WifiRemoteStationManager::WifiRemoteStationManager ()
+  : m_nonUnicast (new NonUnicastWifiRemoteStation (this))
+{}
+
+WifiRemoteStationManager::~WifiRemoteStationManager ()
+{
+  for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) 
+    {
+      delete (*i).second;
+    }
+  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.IsBroadcast () ||
+      address.IsMulticast ())
+    {
+      return m_nonUnicast;
+    }
+  for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) 
+    {
+      if ((*i).first == address)
+        {
+          return (*i).second;
+        }
+    }
+  WifiRemoteStation *station = CreateStation ();
+  station->Reset ();
+  m_stations.push_back (std::make_pair (address, 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->second;
+    }
+  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;
+}
+
+} // namespace ns3
+
+/***************************************************************
+ *           Packet Mode Tagger
+ ***************************************************************/ 
+
+namespace ns3 {
+
+class TxModeTag : public Tag
+{
+public:
+  TxModeTag ();
+  TxModeTag (WifiMode rtsMode, WifiMode dataMode);
+  WifiMode GetRtsMode (void) const;
+  WifiMode GetDataMode (void) const;
+
+  static uint32_t GetUid (void);
+  void Print (std::ostream &os) const;
+  void Serialize (ns3::Buffer::Iterator start) const;
+  uint32_t Deserialize (ns3::Buffer::Iterator start);
+  uint32_t GetSerializedSize (void) const;
+private:
+  WifiMode m_rtsMode;
+  WifiMode m_dataMode;
+};
+
+TxModeTag::TxModeTag ()
+{}
+TxModeTag::TxModeTag (WifiMode rtsMode, WifiMode dataMode)
+  : m_rtsMode (rtsMode),
+    m_dataMode (dataMode)
+{}
+WifiMode 
+TxModeTag::GetRtsMode (void) const
+{
+  return m_rtsMode;
+}
+WifiMode 
+TxModeTag::GetDataMode (void) const
+{
+  return m_dataMode;
+}
+
+uint32_t 
+TxModeTag::GetUid (void)
+{
+  static uint32_t uid = Tag::AllocateUid<TxModeTag> ("ns3.wifi.TxModeTag");
+  return uid;
+}
+void 
+TxModeTag::Print (std::ostream &os) const
+{
+  os << "rts="<<m_rtsMode<<" data="<<m_dataMode;
+}
+void 
+TxModeTag::Serialize (ns3::Buffer::Iterator start) const
+{}
+uint32_t 
+TxModeTag::Deserialize (ns3::Buffer::Iterator start)
+{
+  return 0;
+}
+uint32_t 
+TxModeTag::GetSerializedSize (void) const
+{
+  return 0;
+}
+
+} // namespace ns3
+
+
+/***************************************************************
+ *           WifiRemoteStation below.
+ ***************************************************************/ 
+
+namespace ns3 {
+
+WifiRemoteStation::WifiRemoteStation ()
+  : m_state (BRAND_NEW)
+{}
+WifiRemoteStation::~WifiRemoteStation ()
+{}
+
+bool
+WifiRemoteStation::IsBrandNew (void) const
+{
+  return m_state == BRAND_NEW;
+}
+
+bool 
+WifiRemoteStation::IsAssociated (void) const
+{
+  return m_state == GOT_ASSOC_TX_OK;
+}
+bool 
+WifiRemoteStation::IsWaitAssocTxOk (void) const
+{
+  return m_state == WAIT_ASSOC_TX_OK;
+}
+void 
+WifiRemoteStation::RecordWaitAssocTxOk (void)
+{
+  m_state = WAIT_ASSOC_TX_OK;
+}
+void 
+WifiRemoteStation::RecordGotAssocTxOk (void)
+{
+  m_state = GOT_ASSOC_TX_OK;
+}
+void 
+WifiRemoteStation::RecordGotAssocTxFailed (void)
+{
+  m_state = DISASSOC;
+}
+void 
+WifiRemoteStation::RecordDisassociated (void)
+{
+  m_state = DISASSOC;
+}
+
+void 
+WifiRemoteStation::Reset (void)
+{
+  m_modes.clear ();
+  AddSupportedMode (GetManager ()->GetDefaultMode ());
+}
+void 
+WifiRemoteStation::AddSupportedMode (WifiMode mode)
+{
+  if (IsIn (mode))
+    {
+      return;
+    }
+  m_modes.push_back (mode);
+}
+
+bool
+WifiRemoteStation::IsIn (WifiMode mode) const
+{
+  for (SupportedModes::const_iterator i = m_modes.begin (); i != m_modes.end (); i++)
+    {
+      if ((*i) == mode)
+        {
+          return true;
+        }
+    }
+  return false;
+}
+
+WifiMode
+WifiRemoteStation::GetControlAnswerMode (WifiMode reqMode)
+{
+  /**
+   * see ieee 802.11e, section 9.6:
+   * 
+   * To allow the transmitting STA to calculate the contents of 
+   * the Duration/ID field, a STA responding to a received frame 
+   * shall transmit its Control Response frame (either CTS or ACK) 
+   * frames, other than the Block-Ack control frame, at the highest 
+   * rate in the BSSBasicRateSet parameter that is less than or equal 
+   * to the rate of the immediately previous frame in the frame 
+   * exchange sequence (as defined in 9.79.12) and that is of the
+   * same modulation type as the received frame. If no rate in the 
+   * basic rate set meets these conditions, then the control frame 
+   * sent in response to a received frame shall be transmitted at 
+   * the highest mandatory rate of the PHY that is less than or equal 
+   * to the rate of the received frame, and that is of the same 
+   * modulation type as the received frame. In addition, the Control 
+   * Response frame shall be sent using the same PHY options as the
+   * received frame, unless they conflict with the requirement to use 
+   * the BSSBasicRateSet parameter.
+   */
+  WifiMode mode = GetManager ()->GetDefaultMode ();
+  bool found = false;
+
+  // First, search the BSS Basic Rate set
+  for (WifiRemoteStationManager::BasicModesIterator i = GetManager ()->BeginBasicModes (); 
+       i != GetManager ()->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
+  // within the Basic rate set.
+  return mode;
+}
+
+WifiMode 
+WifiRemoteStation::GetCtsMode (WifiMode rtsMode)
+{
+  return GetControlAnswerMode (rtsMode);
+}
+WifiMode 
+WifiRemoteStation::GetAckMode (WifiMode dataMode)
+{
+  return GetControlAnswerMode (dataMode);
+}
+
+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)
+{
+  if (GetManager ()->IsLowLatency ())
+    {
+      return;
+    }
+  TxModeTag tag = TxModeTag (DoGetRtsMode (), DoGetDataMode (fullPacketSize));
+  packet->AddTag (tag);
+}
+WifiMode 
+WifiRemoteStation::GetDataMode (Ptr<const Packet> packet, uint32_t fullPacketSize)
+{
+  if (GetManager ()->IsLowLatency ())
+    {
+      return DoGetDataMode (fullPacketSize);
+    }
+  TxModeTag tag;
+  bool found;
+  found = packet->PeekTag (tag);
+  NS_ASSERT (found);
+  return tag.GetDataMode ();
+}
+WifiMode 
+WifiRemoteStation::GetRtsMode (Ptr<const Packet> packet)
+{
+  if (GetManager ()->IsLowLatency ())
+    {
+      return DoGetRtsMode ();
+    }
+  TxModeTag tag;
+  bool found;
+  found = packet->PeekTag (tag);
+  NS_ASSERT (found);
+  return tag.GetRtsMode ();
+}
+
+bool
+WifiRemoteStation::NeedRts (Ptr<const Packet> packet)
+{
+  if (packet->GetSize () > GetManager ()->GetRtsCtsThreshold ()) 
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+uint32_t 
+WifiRemoteStation::GetMaxSsrc (Ptr<const Packet> packet)
+{
+  return GetManager ()->GetMaxSsrc ();
+}
+
+uint32_t 
+WifiRemoteStation::GetMaxSlrc (Ptr<const Packet> packet)
+{
+  return GetManager ()->GetMaxSlrc ();
+}
+
+bool
+WifiRemoteStation::NeedFragmentation (Ptr<const Packet> packet)
+{
+  if (packet->GetSize () > GetManager ()->GetFragmentationThreshold ()) 
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+uint32_t
+WifiRemoteStation::GetNFragments (Ptr<const Packet> packet)
+{
+  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)
+    {
+      return 0;
+    }
+  if (fragmentNumber == nFragment - 1)
+    {
+      uint32_t lastFragmentSize = packet->GetSize () % GetManager ()->GetFragmentationThreshold ();
+      return lastFragmentSize;
+    }
+  else
+    {
+      return GetManager ()->GetFragmentationThreshold ();
+    }
+}
+
+bool
+WifiRemoteStation::IsLastFragment (Ptr<const Packet> packet, uint32_t fragmentNumber) 
+{
+  if (fragmentNumber == (GetNFragments (packet) - 1)) 
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+
+} // namespace ns3
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/wifi-remote-station-manager.h	Sat Mar 01 21:21:53 2008 +0100
@@ -0,0 +1,167 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006,2007 INRIA
+ *
+ * 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 WIFI_REMOTE_STATION_MANAGER_H
+#define WIFI_REMOTE_STATION_MANAGER_H
+
+#include <vector>
+#include <utility>
+#include "ns3/mac48-address.h"
+#include "ns3/packet.h"
+#include "ns3/object.h"
+#include "wifi-mode.h"
+
+namespace ns3 {
+
+class WifiRemoteStation;
+class NonUnicastWifiRemoteStation;
+class WifiPhy;
+
+class WifiRemoteStationManager : public Object
+{
+private:
+  typedef std::vector<WifiMode> BasicModes;
+public:
+  typedef BasicModes::const_iterator BasicModesIterator;
+
+  static TypeId GetTypeId (void);
+
+  WifiRemoteStationManager ();
+  virtual ~WifiRemoteStationManager ();
+
+  virtual void SetupPhy (Ptr<WifiPhy> phy);
+
+  uint32_t GetMaxSsrc (void) const;
+  uint32_t GetMaxSlrc (void) const;
+  uint32_t GetRtsCtsThreshold (void) const;
+  uint32_t GetFragmentationThreshold (void) const;
+  void SetMaxSsrc (uint32_t maxSsrc);
+  void SetMaxSlrc (uint32_t maxSlrc);
+  void SetRtsCtsThreshold (uint32_t threshold);
+  void SetFragmentationThreshold (uint32_t threshold);
+  
+  // 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;
+
+  bool IsLowLatency (void) const;
+
+  WifiRemoteStation *Lookup (Mac48Address address);
+  WifiRemoteStation *LookupNonUnicast (void);
+private:
+  typedef std::vector <std::pair<Mac48Address, 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;
+};
+
+} // namespace ns3
+
+namespace ns3 {
+
+class WifiRemoteStation {
+public:
+  WifiRemoteStation ();
+  virtual ~WifiRemoteStation ();
+
+  // 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 IsBrandNew (void) const;
+  bool IsAssociated (void) const;
+  bool IsWaitAssocTxOk (void) const;
+  void RecordWaitAssocTxOk (void);
+  void RecordGotAssocTxOk (void);
+  void RecordGotAssocTxFailed (void);
+  void RecordDisassociated (void);
+
+  void PrepareForQueue (Ptr<const Packet> packet, uint32_t fullPacketSize);
+  WifiMode GetDataMode (Ptr<const Packet> packet, uint32_t fullPacketSize);
+  WifiMode GetRtsMode (Ptr<const Packet> packet);
+
+  // reception-related method
+  virtual void ReportRxOk (double rxSnr, WifiMode txMode) = 0;
+
+  // transmission-related methods
+  virtual void ReportRtsFailed (void) = 0;
+  virtual void ReportDataFailed (void) = 0;
+  virtual void ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr) = 0;
+  virtual void ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr) = 0;
+  virtual void ReportFinalRtsFailed (void) = 0;
+  virtual void ReportFinalDataFailed (void) = 0;
+  virtual bool NeedRts (Ptr<const Packet> packet);
+  virtual uint32_t GetMaxSsrc (Ptr<const Packet> packet);
+  virtual uint32_t GetMaxSlrc (Ptr<const Packet> packet);
+  virtual bool NeedFragmentation (Ptr<const Packet> packet);
+  virtual uint32_t GetNFragments (Ptr<const Packet> packet);
+  virtual uint32_t GetFragmentSize (Ptr<const Packet> packet, uint32_t fragmentNumber);
+  virtual bool IsLastFragment (Ptr<const Packet> packet, uint32_t fragmentNumber);
+
+  WifiMode GetCtsMode (WifiMode rtsMode);
+  WifiMode GetAckMode (WifiMode dataMode);
+
+private:
+  typedef std::vector<WifiMode> SupportedModes;
+  virtual Ptr<WifiRemoteStationManager> GetManager (void) const = 0;
+  virtual WifiMode DoGetDataMode (uint32_t size) = 0;
+  virtual WifiMode DoGetRtsMode (void) = 0;
+protected:
+  uint32_t GetNSupportedModes (void) const;
+  WifiMode GetSupportedMode (uint32_t i) const;
+private:
+  bool IsIn (WifiMode mode) const;
+  WifiMode GetControlAnswerMode (WifiMode reqMode);
+  enum {
+    BRAND_NEW,
+    DISASSOC,
+    WAIT_ASSOC_TX_OK,
+    GOT_ASSOC_TX_OK
+  } m_state;
+  SupportedModes m_modes;
+};
+
+} // namespace ns3 
+
+#endif /* MAC_STATIONS_H */
--- a/src/devices/wifi/wscript	Sat Mar 01 20:41:08 2008 +0100
+++ b/src/devices/wifi/wscript	Sat Mar 01 21:21:53 2008 +0100
@@ -9,35 +9,31 @@
         'wifi-mode.cc',
         'ssid.cc',
         'wifi-phy.cc',
-        'mac-stations.cc',
-        'cr-mac-stations.cc',
-        'arf-mac-stations.cc',
-        'aarf-mac-stations.cc',
         'wifi-mac-header.cc',
         'wifi-mac-trailer.cc',
-        'wifi-mac-parameters.cc',
         'mac-low.cc',
         'wifi-mac-queue.cc',
         'mac-tx-middle.cc',
         'mac-rx-middle.cc',
         'dca-txop.cc',
-        'ideal-mac-stations.cc',
-        'mac-high-adhoc.cc',
         'supported-rates.cc',
         'capability-information.cc',
         'status-code.cc',
         'mgt-headers.cc',
-        'mac-high-nqap.cc',
-        'mac-high-nqsta.cc',
-        'wifi-net-device.cc',
-        'wifi-default-parameters.cc',
         'random-stream.cc',
         'dcf-manager.cc',
         'dcf-manager-test.cc',
-        'onoe-mac-stations.cc',
-        'amrr-mac-stations.cc',
-        'rraa-mac-stations.cc',
-	'wifi-trace.cc',
+        'wifi-mac.cc',
+        'wifi-remote-station-manager.cc',
+        'adhoc-wifi-mac.cc',
+        'nqap-wifi-mac.cc',
+        'nqsta-wifi-mac.cc',
+        'wifi-net-device.cc',
+        'arf-wifi-manager.cc',
+        'aarf-wifi-manager.cc',
+        'ideal-wifi-manager.cc',
+        'constant-rate-wifi-manager.cc',
+        'wifi-helper.cc',
         ]
     headers = bld.create_obj('ns3header')
     headers.source = [
@@ -50,4 +46,15 @@
 	'wifi-phy-standard.h',
         'wifi-phy.h',
 	'wifi-trace.h',
+        'wifi-remote-station-manager.h',
+        'arf-wifi-manager.h',
+        'aarf-wifi-manager.h',
+        'constant-rate-wifi-manager.h',
+        'ideal-wifi-manager.h',
+        'wifi-mac.h',
+        'adhoc-wifi-mac.h',
+        'nqsta-wifi-mac.h',
+        'nqap-wifi-mac.h',
+        'wifi-phy.h',
+        'wifi-helper.h',
         ]