split WifiChannel in WifiChannel + YansWifiChannel
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Wed, 11 Jun 2008 16:19:28 -0700
changeset 3893 94f771c1373a
parent 3892 f985e116b696
child 3894 6b3415c550e1
split WifiChannel in WifiChannel + YansWifiChannel
examples/mixed-wireless.cc
examples/wifi-adhoc.cc
examples/wifi-ap.cc
src/devices/wifi/wifi-channel.cc
src/devices/wifi/wifi-channel.h
src/devices/wifi/wifi-net-device.cc
src/devices/wifi/wifi-phy-test.cc
src/devices/wifi/wifi-phy.h
src/devices/wifi/wifi-test.cc
src/devices/wifi/wscript
src/devices/wifi/yans-wifi-channel.cc
src/devices/wifi/yans-wifi-channel.h
src/devices/wifi/yans-wifi-phy.cc
src/devices/wifi/yans-wifi-phy.h
src/helper/wifi-helper.cc
src/helper/wifi-helper.h
--- a/examples/mixed-wireless.cc	Wed Jun 11 16:19:01 2008 -0700
+++ b/examples/mixed-wireless.cc	Wed Jun 11 16:19:28 2008 -0700
@@ -137,7 +137,6 @@
   //
   WifiHelper wifi;
   wifi.SetMac ("ns3::AdhocWifiMac");
-  wifi.SetPhy ("ns3::YansWifiPhy");
   NetDeviceContainer backboneDevices = wifi.Install (backbone);
   //
   // Add the IPv4 protocol stack to the nodes in our container
@@ -246,7 +245,6 @@
       //
       WifiHelper wifiInfra;
       wifiInfra.SetMac ("ns3::AdhocWifiMac");
-      wifiInfra.SetPhy ("ns3::YansWifiPhy");
       NetDeviceContainer infraDevices = wifiInfra.Install (infra);
 
       // Add the IPv4 protocol stack to the nodes in our container
--- a/examples/wifi-adhoc.cc	Wed Jun 11 16:19:01 2008 -0700
+++ b/examples/wifi-adhoc.cc	Wed Jun 11 16:19:28 2008 -0700
@@ -172,7 +172,6 @@
   GnuplotDataset dataset;
 
   wifi.SetMac ("ns3::AdhocWifiMac");
-  wifi.SetPhy ("ns3::YansWifiPhy");
 
   NS_LOG_DEBUG ("54");
   experiment = Experiment ("54mb");
--- a/examples/wifi-ap.cc	Wed Jun 11 16:19:01 2008 -0700
+++ b/examples/wifi-ap.cc	Wed Jun 11 16:19:28 2008 -0700
@@ -131,14 +131,13 @@
   packetSocket.Install (stas);
   packetSocket.Install (ap);
 
-  Ptr<WifiChannel> channel = CreateObject<WifiChannel> ();
+  Ptr<YansWifiChannel> channel = CreateObject<YansWifiChannel> ();
   channel->SetPropagationDelayModel (CreateObject<ConstantSpeedPropagationDelayModel> ());
   Ptr<LogDistancePropagationLossModel> log = CreateObject<LogDistancePropagationLossModel> ();
   log->SetReferenceModel (CreateObject<FriisPropagationLossModel> ());
   channel->SetPropagationLossModel (log);
 
   Ssid ssid = Ssid ("wifi-default");
-  wifi.SetPhy ("ns3::YansWifiPhy");
   wifi.SetRemoteStationManager ("ns3::ArfWifiManager");
   // setup stas.
   wifi.SetMac ("ns3::NqstaWifiMac", 
--- a/src/devices/wifi/wifi-channel.cc	Wed Jun 11 16:19:01 2008 -0700
+++ b/src/devices/wifi/wifi-channel.cc	Wed Jun 11 16:19:28 2008 -0700
@@ -24,8 +24,10 @@
 #include "ns3/node.h"
 #include "ns3/log.h"
 #include "ns3/pointer.h"
+#include "ns3/object-factory.h"
 #include "wifi-channel.h"
-#include "wifi-phy.h"
+#include "wifi-net-device.h"
+#include "yans-wifi-phy.h"
 #include "propagation-loss-model.h"
 #include "propagation-delay-model.h"
 
@@ -38,94 +40,8 @@
 {
   static TypeId tid = TypeId ("ns3::WifiChannel")
     .SetParent<Channel> ()
-    .AddConstructor<WifiChannel> ()
-    .AddAttribute ("PropagationLossModel", "A pointer to the propagation loss model attached to this channel.",
-                   PointerValue (),
-                   MakePointerAccessor (&WifiChannel::m_loss),
-                   MakePointerChecker<PropagationLossModel> ())
-    .AddAttribute ("PropagationDelayModel", "A pointer to the propagation delay model attached to this channel.",
-                   PointerValue (),
-                   MakePointerAccessor (&WifiChannel::m_delay),
-                   MakePointerChecker<PropagationDelayModel> ())
     ;
   return tid;
 }
 
-WifiChannel::WifiChannel ()
-{}
-WifiChannel::~WifiChannel ()
-{
-  m_deviceList.clear ();
-}
-
-void 
-WifiChannel::SetPropagationLossModel (Ptr<PropagationLossModel> loss)
-{
-  m_loss = loss;
-}
-void 
-WifiChannel::SetPropagationDelayModel (Ptr<PropagationDelayModel> delay)
-{
-  m_delay = delay;
-}
-
-void 
-WifiChannel::Add (Ptr<NetDevice> device, Ptr<WifiPhy> phy, Ptr<Object> mobility)
-{
-  struct Item item;
-  item.device = device;
-  item.phy = phy;
-  item.mobility = mobility;
-  m_deviceList.push_back (item);
-}
-void 
-WifiChannel::Send (Ptr<WifiPhy> sender, Ptr<const Packet> packet, double txPowerDbm,
-                   WifiMode wifiMode, WifiPreamble preamble) const
-{
-  Ptr<MobilityModel> senderMobility = 0;
-  for (DeviceList::const_iterator i = m_deviceList.begin (); i != m_deviceList.end (); i++)
-    {
-      if (sender == i->phy)
-        {
-          senderMobility = i->mobility->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->phy)
-        {
-          Ptr<MobilityModel> receiverMobility = i->mobility->GetObject<MobilityModel> ();
-          Time delay = m_delay->GetDelay (senderMobility, receiverMobility);
-          double rxPowerDbm = txPowerDbm + m_loss->GetLoss (senderMobility, receiverMobility);
-          NS_LOG_DEBUG ("propagation: txPower="<<txPowerDbm<<"dbm, rxPower="<<rxPowerDbm<<"dbm, "<<
-                        "distance="<<senderMobility->GetDistanceFrom (receiverMobility)<<"m, delay="<<delay);
-          Ptr<Packet> copy = packet->Copy ();
-          Simulator::Schedule (delay, &WifiChannel::Receive, this, 
-                               j, copy, rxPowerDbm, wifiMode, preamble);
-        }
-      j++;
-    }
-}
-
-void
-WifiChannel::Receive (uint32_t i, Ptr<Packet> packet, double rxPowerDbm,
-                      WifiMode txMode, WifiPreamble preamble) const
-{
-  m_deviceList[i].phy->StartReceivePacket (packet, rxPowerDbm, txMode, preamble);
-}
-
-uint32_t 
-WifiChannel::GetNDevices (void) const
-{
-  return m_deviceList.size ();
-}
-Ptr<NetDevice> 
-WifiChannel::GetDevice (uint32_t i) const
-{
-  return m_deviceList[i].device;
-}
-
 } // namespace ns3
--- a/src/devices/wifi/wifi-channel.h	Wed Jun 11 16:19:01 2008 -0700
+++ b/src/devices/wifi/wifi-channel.h	Wed Jun 11 16:19:28 2008 -0700
@@ -20,104 +20,33 @@
 #ifndef WIFI_CHANNEL_H
 #define WIFI_CHANNEL_H
 
-#include <vector>
-#include <stdint.h>
-#include "ns3/packet.h"
 #include "ns3/channel.h"
-#include "ns3/net-device.h"
-#include "wifi-mode.h"
-#include "wifi-preamble.h"
+#include "ns3/attribute-list.h"
 
 namespace ns3 {
 
-class NetDevice;
-class PropagationLossModel;
-class PropagationDelayModel;
+class WifiNetDevice;
 class WifiPhy;
 
 /**
  * \brief A 802.11 Channel
  *
- * This channel subclass can be used to connect together a set of 
- * ns3::WifiNetDevice network interfaces. A WifiChannel contains
- * a ns3::PropagationLossModel and a ns3::PropagationDelayModel which can
- * be overriden by the WifiChannel::SetPropagationLossModel
- * and the WifiChannel::SetPropagationDelayModel methods. By default,
- * no propagation models are set.
+ * This class works in tandem with the ns3::WifiPhy class. If you want to
+ * provide a new Wifi PHY layer, you have to subclass both ns3::WifiChannel 
+ * and ns3::WifiPhy.
+ *
+ * Typically, MyWifiChannel will define a Send method whose job is to distribute
+ * packets from a MyWifiPhy source to a set of MyWifiPhy destinations. MyWifiPhy
+ * also typically defines a Receive method which is invoked by MyWifiPhy.
  */
 class WifiChannel : public Channel
 {
 public:
   static TypeId GetTypeId (void);
 
-  WifiChannel ();
-  virtual ~WifiChannel ();
-
-  /**
-   * \returns the number of network interfaces connected to 
-   *          this channel.
-   *
-   * Overriden from the NetDevice base class.
-   */
-  virtual uint32_t GetNDevices (void) const;
-
-  /**
-   * \param i index of the requested network interface.
-   * \returns the requested network interfaces connected to 
-   *          this channel.
-   *
-   * Overriden from the NetDevice base class.
-   * Indexes start at 0 and end at n-1.
-   */
-  virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
-
-  /**
-   * \param loss the new propagation loss model.
-   */
-  void SetPropagationLossModel (Ptr<PropagationLossModel> loss);
-  /**
-   * \param delay the new propagation delay model.
-   */
-  void SetPropagationDelayModel (Ptr<PropagationDelayModel> delay);
-
-  /**
-   * \param device the device to add to the list of connected
-   *        devices.
-   * \param phy the physical layer which will receive packets
-   *        on behalf of the device.
-   * \param mobility the mobility model associated to the device.
-   *
-   * This method should not be invoked by normal users. It is 
-   * currently invoked only from WifiPhy::SetChannel.
-   */
-  void Add (Ptr<NetDevice> device,  Ptr<WifiPhy> phy, Ptr<Object> mobility);
-  /**
-   * \param sender the device from which the packet is originating.
-   * \param packet the packet to send
-   * \param txPowerDbm the tx power associated to the packet
-   * \param wifiMode the tx mode associated to the packet
-   * \param preamble the preamble associated to the packet
-   *
-   * This method should not be invoked by normal users. It is 
-   * currently invoked only from WifiPhy::Send.
-   */
-  void Send (Ptr<WifiPhy> sender, Ptr<const Packet> packet, double txPowerDbm,
-             WifiMode wifiMode, WifiPreamble preamble) const;
-
-private:
-  struct Item {
-    Ptr<NetDevice> device;
-    Ptr<WifiPhy> phy;
-    Ptr<Object> mobility;
-  };
-  typedef std::vector<struct Item> DeviceList;
-  void Receive (uint32_t i, Ptr<Packet> packet, double rxPowerDbm,
-                WifiMode txMode, WifiPreamble preamble) const;
-
-
-  DeviceList m_deviceList;
-  Ptr<PropagationLossModel> m_loss;
-  Ptr<PropagationDelayModel> m_delay;
+  virtual Ptr<WifiPhy> CreatePhy (Ptr<WifiNetDevice> device,
+                                  Ptr<Object> mobility,
+                                  UnsafeAttributeList list) = 0;
 };
 
 } // namespace ns3
--- a/src/devices/wifi/wifi-net-device.cc	Wed Jun 11 16:19:01 2008 -0700
+++ b/src/devices/wifi/wifi-net-device.cc	Wed Jun 11 16:19:28 2008 -0700
@@ -112,11 +112,6 @@
   m_phy = phy;
   if (m_phy != 0)
     {
-      if (m_channel != 0 && m_node != 0)
-        {
-          m_channel->Add (this, m_phy, m_node);
-          m_phy->SetChannel (m_channel);
-        }
       if (m_stationManager != 0)
         {
           m_stationManager->SetupPhy (m_phy);
@@ -147,11 +142,6 @@
 WifiNetDevice::SetChannel (Ptr<WifiChannel> channel)
 {
   m_channel = channel;
-  if (m_channel != 0 && m_phy != 0 && m_node != 0)
-    {
-      m_channel->Add (this, m_phy, m_node);
-      m_phy->SetChannel (m_channel);
-    }
 }
 Ptr<WifiMac> 
 WifiNetDevice::GetMac (void) const
@@ -292,11 +282,6 @@
 WifiNetDevice::SetNode (Ptr<Node> node)
 {
   m_node = node;
-  if (m_channel != 0 && m_phy != 0 && m_node != 0)
-    {
-      m_channel->Add (this, m_phy, m_node);
-      m_phy->SetChannel (m_channel);
-    }
 }
 bool 
 WifiNetDevice::NeedsArp (void) const
--- a/src/devices/wifi/wifi-phy-test.cc	Wed Jun 11 16:19:01 2008 -0700
+++ b/src/devices/wifi/wifi-phy-test.cc	Wed Jun 11 16:19:28 2008 -0700
@@ -1,5 +1,5 @@
-#include "wifi-phy.h"
-#include "wifi-channel.h"
+#include "wifi-net-device.h"
+#include "yans-wifi-channel.h"
 #include "yans-wifi-phy.h"
 #include "propagation-loss-model.h"
 #include "propagation-delay-model.h"
@@ -78,20 +78,15 @@
   Ptr<MobilityModel> posRx = CreateObject<StaticMobilityModel> ();
   posRx->SetPosition (Vector (m_input.distance, 0.0, 0.0));
 
-  Ptr<WifiPhy> tx = CreateObject<YansWifiPhy> ();
-  Ptr<WifiPhy> rx = CreateObject<YansWifiPhy> ();
-  rx->SetReceiveOkCallback (MakeCallback (&PsrExperiment::Receive, this));
-
-  Ptr<WifiChannel> channel = CreateObject<WifiChannel> ();
+  Ptr<YansWifiChannel> channel = CreateObject<YansWifiChannel> ();
   channel->SetPropagationDelayModel (CreateObject<ConstantSpeedPropagationDelayModel> ());
   Ptr<LogDistancePropagationLossModel> log = CreateObject<LogDistancePropagationLossModel> ();
   log->SetReferenceModel (CreateObject<FriisPropagationLossModel> ());
   channel->SetPropagationLossModel (log);
 
-  channel->Add (0, tx, posTx);
-  channel->Add (0, rx, posRx);
-  tx->SetChannel (channel);
-  rx->SetChannel (channel);
+  Ptr<WifiPhy> tx = channel->CreatePhy (0, posTx, UnsafeAttributeList ());
+  Ptr<WifiPhy> rx = channel->CreatePhy (0, posRx, UnsafeAttributeList ());
+  rx->SetReceiveOkCallback (MakeCallback (&PsrExperiment::Receive, this));
 
   for (uint32_t i = 0; i < m_input.nPackets; ++i)
     {
@@ -198,6 +193,12 @@
   m_flowIdA = FlowIdTag::AllocateFlowId ();
   m_flowIdB = FlowIdTag::AllocateFlowId ();
 
+  Ptr<YansWifiChannel> channel = CreateObject<YansWifiChannel> ();
+  channel->SetPropagationDelayModel (CreateObject<ConstantSpeedPropagationDelayModel> ());
+  Ptr<LogDistancePropagationLossModel> log = CreateObject<LogDistancePropagationLossModel> ();
+  log->SetReferenceModel (CreateObject<FriisPropagationLossModel> ());
+  channel->SetPropagationLossModel (log);
+
   Ptr<MobilityModel> posTxA = CreateObject<StaticMobilityModel> ();
   posTxA->SetPosition (Vector (input.xA, 0.0, 0.0));
   Ptr<MobilityModel> posTxB = CreateObject<StaticMobilityModel> ();
@@ -205,24 +206,11 @@
   Ptr<MobilityModel> posRx = CreateObject<StaticMobilityModel> ();
   posRx->SetPosition (Vector (0, 0.0, 0.0));
 
-  Ptr<WifiPhy> txA = CreateObject<YansWifiPhy> ();
-  Ptr<WifiPhy> txB = CreateObject<YansWifiPhy> ();
-  Ptr<WifiPhy> rx = CreateObject<YansWifiPhy> ();
+  Ptr<WifiPhy> txA = channel->CreatePhy (0, posTxA, UnsafeAttributeList ());
+  Ptr<WifiPhy> txB = channel->CreatePhy (0, posTxB, UnsafeAttributeList ());
+  Ptr<WifiPhy> rx = channel->CreatePhy (0, posRx, UnsafeAttributeList ());
   rx->SetReceiveOkCallback (MakeCallback (&CollisionExperiment::Receive, this));
 
-  Ptr<WifiChannel> channel = CreateObject<WifiChannel> ();
-  channel->SetPropagationDelayModel (CreateObject<ConstantSpeedPropagationDelayModel> ());
-  Ptr<LogDistancePropagationLossModel> log = CreateObject<LogDistancePropagationLossModel> ();
-  log->SetReferenceModel (CreateObject<FriisPropagationLossModel> ());
-  channel->SetPropagationLossModel (log);
-
-  channel->Add (0, txA, posTxA);
-  channel->Add (0, txB, posTxB);
-  channel->Add (0, rx, posRx);
-  txA->SetChannel (channel);
-  txB->SetChannel (channel);
-  rx->SetChannel (channel);
-
   for (uint32_t i = 0; i < m_input.nPackets; ++i)
     {
       Simulator::Schedule (Seconds (i), &CollisionExperiment::SendA, this);
--- a/src/devices/wifi/wifi-phy.h	Wed Jun 11 16:19:01 2008 -0700
+++ b/src/devices/wifi/wifi-phy.h	Wed Jun 11 16:19:28 2008 -0700
@@ -141,11 +141,6 @@
   virtual uint32_t GetNTxPower (void) const = 0;
 
   /**
-   * \param channel the channel to connect to.
-   */
-  virtual void SetChannel (Ptr<WifiChannel> channel) = 0;
-
-  /**
    * \param callback the callback to invoke
    *        upon successful packet reception.
    */
@@ -234,11 +229,6 @@
    */
   virtual double CalculateSnr (WifiMode txMode, double ber) const = 0;
 
-  /* rxPower unit is Watt */
-  virtual void StartReceivePacket (Ptr<Packet> packet,
-                                   double rxPowerDbm,
-                                   WifiMode mode,
-                                   WifiPreamble preamble) = 0;
 
   virtual Ptr<WifiChannel> GetChannel (void) const = 0;
 
--- a/src/devices/wifi/wifi-test.cc	Wed Jun 11 16:19:01 2008 -0700
+++ b/src/devices/wifi/wifi-test.cc	Wed Jun 11 16:19:28 2008 -0700
@@ -1,7 +1,7 @@
 #ifdef RUN_SELF_TESTS
 
 #include "wifi-net-device.h"
-#include "wifi-channel.h"
+#include "yans-wifi-channel.h"
 #include "adhoc-wifi-mac.h"
 #include "yans-wifi-phy.h"
 #include "arf-wifi-manager.h"
@@ -50,7 +50,7 @@
 
   Ptr<WifiMac> mac = m_mac.Create<WifiMac> ();
   Ptr<StaticMobilityModel> mobility = CreateObject<StaticMobilityModel> ();
-  Ptr<WifiPhy> phy = CreateObject<YansWifiPhy> ();
+  Ptr<WifiPhy> phy = channel->CreatePhy (dev, mobility, UnsafeAttributeList ());
   Ptr<WifiRemoteStationManager> manager = m_manager.Create<WifiRemoteStationManager> ();
 
   mobility->SetPosition (pos);
@@ -68,7 +68,7 @@
 void
 WifiTest::RunOne (void)
 {
-  Ptr<WifiChannel> channel = CreateObject<WifiChannel> ();
+  Ptr<YansWifiChannel> channel = CreateObject<YansWifiChannel> ();
   Ptr<PropagationDelayModel> propDelay = m_propDelay.Create<PropagationDelayModel> ();
   Ptr<PropagationLossModel> propLoss = CreateObject<RandomPropagationLossModel> ();
   channel->SetPropagationDelayModel (propDelay);
--- a/src/devices/wifi/wscript	Wed Jun 11 16:19:01 2008 -0700
+++ b/src/devices/wifi/wscript	Wed Jun 11 16:19:28 2008 -0700
@@ -12,6 +12,7 @@
         'ssid.cc',
         'wifi-phy.cc',
         'yans-wifi-phy.cc',
+        'yans-wifi-channel.cc',
         'wifi-mac-header.cc',
         'wifi-mac-trailer.cc',
         'mac-low.cc',
@@ -55,6 +56,7 @@
         'wifi-preamble.h',
 	'wifi-phy-standard.h',
         'yans-wifi-phy.h',
+        'yans-wifi-channel.h',
         'wifi-phy.h',
         'wifi-remote-station-manager.h',
         'arf-wifi-manager.h',
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/yans-wifi-channel.cc	Wed Jun 11 16:19:28 2008 -0700
@@ -0,0 +1,142 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 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 "ns3/packet.h"
+#include "ns3/simulator.h"
+#include "ns3/mobility-model.h"
+#include "ns3/net-device.h"
+#include "ns3/node.h"
+#include "ns3/log.h"
+#include "ns3/pointer.h"
+#include "ns3/object-factory.h"
+#include "yans-wifi-channel.h"
+#include "yans-wifi-phy.h"
+#include "wifi-net-device.h"
+#include "propagation-loss-model.h"
+#include "propagation-delay-model.h"
+
+NS_LOG_COMPONENT_DEFINE ("YansWifiChannel");
+
+namespace ns3 {
+
+TypeId 
+YansWifiChannel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::YansWifiChannel")
+    .SetParent<WifiChannel> ()
+    .AddConstructor<YansWifiChannel> ()
+    .AddAttribute ("PropagationLossModel", "A pointer to the propagation loss model attached to this channel.",
+                   PointerValue (),
+                   MakePointerAccessor (&YansWifiChannel::m_loss),
+                   MakePointerChecker<PropagationLossModel> ())
+    .AddAttribute ("PropagationDelayModel", "A pointer to the propagation delay model attached to this channel.",
+                   PointerValue (),
+                   MakePointerAccessor (&YansWifiChannel::m_delay),
+                   MakePointerChecker<PropagationDelayModel> ())
+    ;
+  return tid;
+}
+
+YansWifiChannel::YansWifiChannel ()
+{}
+YansWifiChannel::~YansWifiChannel ()
+{
+  m_deviceList.clear ();
+}
+
+void 
+YansWifiChannel::SetPropagationLossModel (Ptr<PropagationLossModel> loss)
+{
+  m_loss = loss;
+}
+void 
+YansWifiChannel::SetPropagationDelayModel (Ptr<PropagationDelayModel> delay)
+{
+  m_delay = delay;
+}
+
+void 
+YansWifiChannel::Send (Ptr<YansWifiPhy> sender, Ptr<const Packet> packet, double txPowerDbm,
+                       WifiMode wifiMode, WifiPreamble preamble) const
+{
+  Ptr<MobilityModel> senderMobility = 0;
+  for (DeviceList::const_iterator i = m_deviceList.begin (); i != m_deviceList.end (); i++)
+    {
+      if (sender == i->phy)
+        {
+          senderMobility = i->mobility->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->phy)
+        {
+          Ptr<MobilityModel> receiverMobility = i->mobility->GetObject<MobilityModel> ();
+          Time delay = m_delay->GetDelay (senderMobility, receiverMobility);
+          double rxPowerDbm = txPowerDbm + m_loss->GetLoss (senderMobility, receiverMobility);
+          NS_LOG_DEBUG ("propagation: txPower="<<txPowerDbm<<"dbm, rxPower="<<rxPowerDbm<<"dbm, "<<
+                        "distance="<<senderMobility->GetDistanceFrom (receiverMobility)<<"m, delay="<<delay);
+          Ptr<Packet> copy = packet->Copy ();
+          Simulator::Schedule (delay, &YansWifiChannel::Receive, this, 
+                               j, copy, rxPowerDbm, wifiMode, preamble);
+        }
+      j++;
+    }
+}
+
+void
+YansWifiChannel::Receive (uint32_t i, Ptr<Packet> packet, double rxPowerDbm,
+                      WifiMode txMode, WifiPreamble preamble) const
+{
+  m_deviceList[i].phy->StartReceivePacket (packet, rxPowerDbm, txMode, preamble);
+}
+
+uint32_t 
+YansWifiChannel::GetNDevices (void) const
+{
+  return m_deviceList.size ();
+}
+Ptr<NetDevice> 
+YansWifiChannel::GetDevice (uint32_t i) const
+{
+  return m_deviceList[i].device;
+}
+
+Ptr<WifiPhy> 
+YansWifiChannel::CreatePhy (Ptr<WifiNetDevice> device,
+                        Ptr<Object> mobility,
+                        UnsafeAttributeList list)
+{
+  ObjectFactory factory;
+  factory.SetTypeId ("ns3::YansWifiPhy");
+  factory.Set (list.GetSafe ("ns3::YansWifiPhy"));
+  Ptr<YansWifiPhy> phy = factory.Create<YansWifiPhy> ();
+  phy->SetChannel (this);
+  struct Item item;
+  item.device = device;
+  item.phy = phy;
+  item.mobility = mobility;
+  m_deviceList.push_back (item);
+  return phy;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/yans-wifi-channel.h	Wed Jun 11 16:19:28 2008 -0700
@@ -0,0 +1,120 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 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 YANS_WIFI_CHANNEL_H
+#define YANS_WIFI_CHANNEL_H
+
+#include <vector>
+#include <stdint.h>
+#include "ns3/packet.h"
+#include "wifi-channel.h"
+#include "wifi-mode.h"
+#include "wifi-preamble.h"
+
+namespace ns3 {
+
+class NetDevice;
+class WifiNetDevice;
+class PropagationLossModel;
+class PropagationDelayModel;
+class YansWifiPhy;
+
+/**
+ * \brief A Yans wifi channel
+ *
+ * This wifi channel implements the propagation model described in
+ * "Yet Another Network Simulator", (http://cutebugs.net/files/wns2-yans.pdf).
+ *
+ * This class is expected to be used in tandem with the ns3::YansWifiPhy 
+ * class and contains a ns3::PropagationLossModel and a ns3::PropagationDelayModel.
+ * By default, no propagation models are set so, it is the caller's responsability
+ * to set them before using the channel.
+ */
+class YansWifiChannel : public WifiChannel
+{
+public:
+  static TypeId GetTypeId (void);
+
+  YansWifiChannel ();
+  virtual ~YansWifiChannel ();
+
+  /**
+   * \returns the number of network interfaces connected to 
+   *          this channel.
+   *
+   * Overriden from the NetDevice base class.
+   */
+  virtual uint32_t GetNDevices (void) const;
+
+  /**
+   * \param i index of the requested network interface.
+   * \returns the requested network interfaces connected to 
+   *          this channel.
+   *
+   * Overriden from the NetDevice base class.
+   * Indexes start at 0 and end at n-1.
+   */
+  virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
+
+  virtual Ptr<WifiPhy> CreatePhy (Ptr<WifiNetDevice> device,
+                                  Ptr<Object> mobility,
+                                  UnsafeAttributeList list);
+
+  /**
+   * \param loss the new propagation loss model.
+   */
+  void SetPropagationLossModel (Ptr<PropagationLossModel> loss);
+  /**
+   * \param delay the new propagation delay model.
+   */
+  void SetPropagationDelayModel (Ptr<PropagationDelayModel> delay);
+
+  /**
+   * \param sender the device from which the packet is originating.
+   * \param packet the packet to send
+   * \param txPowerDbm the tx power associated to the packet
+   * \param wifiMode the tx mode associated to the packet
+   * \param preamble the preamble associated to the packet
+   *
+   * This method should not be invoked by normal users. It is 
+   * currently invoked only from WifiPhy::Send.
+   */
+  void Send (Ptr<YansWifiPhy> sender, Ptr<const Packet> packet, double txPowerDbm,
+             WifiMode wifiMode, WifiPreamble preamble) const;
+
+private:
+  struct Item {
+    Ptr<WifiNetDevice> device;
+    Ptr<YansWifiPhy> phy;
+    Ptr<Object> mobility;
+  };
+  typedef std::vector<struct Item> DeviceList;
+  void Receive (uint32_t i, Ptr<Packet> packet, double rxPowerDbm,
+                WifiMode txMode, WifiPreamble preamble) const;
+
+
+  DeviceList m_deviceList;
+  Ptr<PropagationLossModel> m_loss;
+  Ptr<PropagationDelayModel> m_delay;
+};
+
+} // namespace ns3
+
+
+#endif /* YANS_WIFI_CHANNEL_H */
--- a/src/devices/wifi/yans-wifi-phy.cc	Wed Jun 11 16:19:01 2008 -0700
+++ b/src/devices/wifi/yans-wifi-phy.cc	Wed Jun 11 16:19:28 2008 -0700
@@ -20,7 +20,7 @@
 
 #include "yans-wifi-phy.h"
 #include "wifi-mode.h"
-#include "wifi-channel.h"
+#include "yans-wifi-channel.h"
 #include "wifi-preamble.h"
 #include "ns3/simulator.h"
 #include "ns3/packet.h"
@@ -341,7 +341,7 @@
 }
 
 void 
-YansWifiPhy::SetChannel (Ptr<WifiChannel> channel)
+YansWifiPhy::SetChannel (Ptr<YansWifiChannel> channel)
 {
   m_channel = channel;
 }
--- a/src/devices/wifi/yans-wifi-phy.h	Wed Jun 11 16:19:01 2008 -0700
+++ b/src/devices/wifi/yans-wifi-phy.h	Wed Jun 11 16:19:28 2008 -0700
@@ -42,7 +42,7 @@
 
 class RandomUniform;
 class RxEvent;
-class WifiChannel;
+class YansWifiChannel;
 
 
 /**
@@ -57,7 +57,7 @@
  * This PHY model depends on a channel loss and delay
  * model as provided by the ns3::PropagationLossModel
  * and ns3::PropagationDelayModel classes, both of which are
- * members of the ns3::WifiChannel class.
+ * members of the ns3::YansWifiChannel class.
  */
 class YansWifiPhy : public WifiPhy
 {
@@ -68,6 +68,12 @@
   YansWifiPhy ();
   virtual ~YansWifiPhy ();
 
+  void SetChannel (Ptr<YansWifiChannel> channel);
+  void StartReceivePacket (Ptr<Packet> packet,
+                           double rxPowerDbm,
+                           WifiMode mode,
+                           WifiPreamble preamble);
+
   void SetStandard (enum WifiPhyStandard standard);
   void SetRxNoise (double ratio);
   void SetTxPowerStart (double start);
@@ -85,7 +91,6 @@
   virtual double GetTxPowerStart (void) const;
   virtual double GetTxPowerEnd (void) const;
   virtual uint32_t GetNTxPower (void) const;
-  virtual void SetChannel (Ptr<WifiChannel> channel);
   virtual void SetReceiveOkCallback (WifiPhy::SyncOkCallback callback);
   virtual void SetReceiveErrorCallback (WifiPhy::SyncErrorCallback callback);
   virtual void SendPacket (Ptr<const Packet> packet, WifiMode mode, enum WifiPreamble preamble, uint8_t txPowerLevel);
@@ -102,10 +107,6 @@
   virtual uint32_t GetNModes (void) const;
   virtual WifiMode GetMode (uint32_t mode) const;
   virtual double CalculateSnr (WifiMode txMode, double ber) const;
-  virtual void StartReceivePacket (Ptr<Packet> packet,
-                                   double rxPowerDbm,
-                                   WifiMode mode,
-                                   WifiPreamble preamble);
   virtual Ptr<WifiChannel> GetChannel (void) const;
 
 private:
@@ -201,7 +202,7 @@
   Time m_startCcaBusy;
   Time m_previousStateChangeTime;
 
-  Ptr<WifiChannel> m_channel;
+  Ptr<YansWifiChannel> m_channel;
   SyncOkCallback m_syncOkCallback;
   SyncErrorCallback m_syncErrorCallback;
   TracedCallback<Ptr<const Packet>, double, WifiMode, enum WifiPreamble> m_rxOkTrace;
--- a/src/helper/wifi-helper.cc	Wed Jun 11 16:19:01 2008 -0700
+++ b/src/helper/wifi-helper.cc	Wed Jun 11 16:19:28 2008 -0700
@@ -23,6 +23,7 @@
 #include "ns3/wifi-phy.h"
 #include "ns3/wifi-remote-station-manager.h"
 #include "ns3/wifi-channel.h"
+#include "ns3/yans-wifi-channel.h"
 #include "ns3/propagation-delay-model.h"
 #include "ns3/propagation-loss-model.h"
 #include "ns3/mobility-model.h"
@@ -72,7 +73,6 @@
 WifiHelper::WifiHelper ()
 {
   m_stationManager.SetTypeId ("ns3::ArfWifiManager");
-  m_phy.SetTypeId ("ns3::WifiPhy");
   m_mac.SetTypeId ("ns3::AdhocWifiMac");
 }
 
@@ -123,26 +123,9 @@
 }
 
 void 
-WifiHelper::SetPhy (std::string type,
-		    std::string n0, const AttributeValue &v0,
-		    std::string n1, const AttributeValue &v1,
-		    std::string n2, const AttributeValue &v2,
-		    std::string n3, const AttributeValue &v3,
-		    std::string n4, const AttributeValue &v4,
-		    std::string n5, const AttributeValue &v5,
-		    std::string n6, const AttributeValue &v6,
-		    std::string n7, const AttributeValue &v7)
+WifiHelper::SetPhyAttribute (std::string name, const AttributeValue &value)
 {
-  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);
+  m_phyAttributes.Set (name, value);
 }
 
 void 
@@ -234,7 +217,7 @@
 NetDeviceContainer
 WifiHelper::Install (NodeContainer c) const
 {
-  Ptr<WifiChannel> channel = CreateObject<WifiChannel> ();
+  Ptr<YansWifiChannel> channel = CreateObject<YansWifiChannel> ();
   channel->SetPropagationDelayModel (CreateObject<ConstantSpeedPropagationDelayModel> ());
   Ptr<LogDistancePropagationLossModel> log = CreateObject<LogDistancePropagationLossModel> ();
   log->SetReferenceModel (CreateObject<FriisPropagationLossModel> ());
@@ -251,7 +234,7 @@
       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> ();
+      Ptr<WifiPhy> phy = channel->CreatePhy (device, node, m_phyAttributes);
       mac->SetAddress (Mac48Address::Allocate ());
       device->SetMac (mac);
       device->SetPhy (phy);
--- a/src/helper/wifi-helper.h	Wed Jun 11 16:19:01 2008 -0700
+++ b/src/helper/wifi-helper.h	Wed Jun 11 16:19:28 2008 -0700
@@ -107,36 +107,11 @@
 	       std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
 
   /**
-   * \param phyType the type of ns3::WifiPhy to create.
-   * \param n0 the name of the attribute to set
-   * \param v0 the value of the attribute to set
-   * \param n1 the name of the attribute to set
-   * \param v1 the value of the attribute to set
-   * \param n2 the name of the attribute to set
-   * \param v2 the value of the attribute to set
-   * \param n3 the name of the attribute to set
-   * \param v3 the value of the attribute to set
-   * \param n4 the name of the attribute to set
-   * \param v4 the value of the attribute to set
-   * \param n5 the name of the attribute to set
-   * \param v5 the value of the attribute to set
-   * \param n6 the name of the attribute to set
-   * \param v6 the value of the attribute to set
-   * \param n7 the name of the attribute to set
-   * \param v7 the value of the attribute to set
+   * \param name the name of the attribute to set
+   * \param value the value of the attribute to set
    *
-   * All the attributes specified in this method should exist
-   * in the requested phy.
    */
-  void SetPhy (std::string phyType,
-	       std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
-	       std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
-	       std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
-	       std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
-	       std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
-	       std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
-	       std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
-	       std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+  void SetPhyAttribute (std::string n0, const AttributeValue &v0);
 
 
 
@@ -249,7 +224,7 @@
 private:
   ObjectFactory m_stationManager;
   ObjectFactory m_mac;
-  ObjectFactory m_phy;
+  UnsafeAttributeList m_phyAttributes;
 };
 
 } // namespace ns3