make NetDevice fully virtual.
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Mon, 25 Feb 2008 19:33:46 +0100
changeset 2470 254581fb9e9c
parent 2469 181c6a5b14c1
child 2476 febce6836ef3
make NetDevice fully virtual.
examples/csma-packet-socket.cc
samples/main-adhoc-wifi.cc
samples/main-ap-wifi.cc
src/devices/csma/csma-ipv4-topology.cc
src/devices/csma/csma-net-device.cc
src/devices/csma/csma-net-device.h
src/devices/point-to-point/point-to-point-net-device.cc
src/devices/point-to-point/point-to-point-net-device.h
src/devices/point-to-point/point-to-point-topology.cc
src/devices/wifi/wifi-net-device.cc
src/devices/wifi/wifi-net-device.h
src/internet-node/udp-socket.cc
src/node/net-device.cc
src/node/net-device.h
tutorial/point-to-point-ipv4-topology.cc
utils/print-introspected-doxygen.cc
--- a/examples/csma-packet-socket.cc	Sun Feb 24 20:18:02 2008 +0100
+++ b/examples/csma-packet-socket.cc	Mon Feb 25 19:33:46 2008 +0100
@@ -61,7 +61,9 @@
 static Ptr<CsmaNetDevice>
 CreateCsmaDevice (Ptr<Node> node, Ptr<CsmaChannel> channel)
 {
-  Ptr<CsmaNetDevice> device = CreateObject<CsmaNetDevice> (node);
+  Ptr<CsmaNetDevice> device = CreateObject<CsmaNetDevice> (node, Mac48Address::Allocate (),
+                                                           CsmaNetDevice::LLC);
+  node->AddDevice (device);
   device->Attach (channel);
   Ptr<Queue> queue = Queue::CreateDefault ();
   device->AddQueue (queue);
--- a/samples/main-adhoc-wifi.cc	Sun Feb 24 20:18:02 2008 +0100
+++ b/samples/main-adhoc-wifi.cc	Mon Feb 25 19:33:46 2008 +0100
@@ -47,6 +47,7 @@
 {
   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);
--- a/samples/main-ap-wifi.cc	Sun Feb 24 20:18:02 2008 +0100
+++ b/samples/main-ap-wifi.cc	Mon Feb 25 19:33:46 2008 +0100
@@ -73,6 +73,7 @@
 {
   Ptr<Node> node = CreateObject<Node> ();  
   Ptr<NqapWifiNetDevice> device = CreateObject<NqapWifiNetDevice> (node, Mac48Address (macAddress));
+  node->AddDevice (device);
   device->SetSsid (ssid);
   Simulator::Schedule (at, &NqapWifiNetDevice::StartBeaconing, device);
   device->Attach (channel);
@@ -90,6 +91,7 @@
 {
   Ptr<Node> node = CreateObject<Node> ();  
   Ptr<NqstaWifiNetDevice> device = CreateObject<NqstaWifiNetDevice> (node, Mac48Address (macAddress));
+  node->AddDevice (device);
   Simulator::ScheduleNow (&NqstaWifiNetDevice::StartActiveAssociation, device, 
                           ssid);
   device->Attach (channel);
--- a/src/devices/csma/csma-ipv4-topology.cc	Sun Feb 24 20:18:02 2008 +0100
+++ b/src/devices/csma/csma-ipv4-topology.cc	Mon Feb 25 19:33:46 2008 +0100
@@ -43,7 +43,8 @@
 
   // assume full-duplex
   Ptr<CsmaNetDevice> nd = CreateObject<CsmaNetDevice> (node, addr, 
-    ns3::CsmaNetDevice::IP_ARP, true, true);
+                                                       ns3::CsmaNetDevice::IP_ARP);
+  node->AddDevice (nd);
 
   nd->AddQueue(q);
   nd->Attach (channel);
@@ -59,14 +60,18 @@
   Ptr<Queue> q = Queue::CreateDefault ();
 
   Ptr<CsmaNetDevice> nd0 = CreateObject<CsmaNetDevice> (n1, addr,
-                                                  ns3::CsmaNetDevice::LLC,
-                                                  true, false);
+                                                        ns3::CsmaNetDevice::LLC);
+  n1->AddDevice (nd0);
+  nd0->SetSendEnable (true);
+  nd0->SetReceiveEnable (false);
   nd0->AddQueue(q);
   nd0->Attach (ch);
 
   Ptr<CsmaNetDevice> nd1 = CreateObject<CsmaNetDevice> (n1, addr,
-                                                  ns3::CsmaNetDevice::LLC,
-                                                  false, true);
+                                                        ns3::CsmaNetDevice::LLC);
+  n1->AddDevice (nd1);
+  nd1->SetSendEnable (false);
+  nd1->SetReceiveEnable (true);
   nd1->AddQueue(q);
   nd1->Attach (ch);
 }
@@ -79,14 +84,19 @@
   Ptr<Queue> q = Queue::CreateDefault ();
 
   Ptr<CsmaNetDevice> nd0 = CreateObject<CsmaNetDevice> (n1, addr,
-                                                  ns3::CsmaNetDevice::RAW,
-                                                  true, false);
+                                                        ns3::CsmaNetDevice::RAW);
+  n1->AddDevice (nd0);
+  nd0->SetSendEnable (true);
+  nd0->SetReceiveEnable (false);
   nd0->AddQueue(q);
   nd0->Attach (ch);
 
   Ptr<CsmaNetDevice> nd1 = CreateObject<CsmaNetDevice> (n1, addr,
-                                                  ns3::CsmaNetDevice::RAW,
-                                                  false, true);
+                                                        ns3::CsmaNetDevice::RAW);
+  n1->AddDevice (nd1);
+  nd1->SetSendEnable (false);
+  nd1->SetReceiveEnable (true);
+
   nd1->AddQueue(q);
   nd1->Attach (ch);
 }
--- a/src/devices/csma/csma-net-device.cc	Sun Feb 24 20:18:02 2008 +0100
+++ b/src/devices/csma/csma-net-device.cc	Mon Feb 25 19:33:46 2008 +0100
@@ -81,22 +81,15 @@
   return m_type;
 }
 
-CsmaNetDevice::CsmaNetDevice (Ptr<Node> node)
-  : NetDevice (node, Mac48Address::Allocate ()),
-    m_bps (DataRate (0xffffffff)),
-    m_receiveErrorModel (0)
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << node);
-  m_encapMode = IP_ARP;
-  Init(true, true);
-}
-
 CsmaNetDevice::CsmaNetDevice (Ptr<Node> node, Mac48Address addr, 
-                              CsmaEncapsulationMode encapMode) 
-  : NetDevice(node, addr), 
-    m_bps (DataRate (0xffffffff)),
-    m_receiveErrorModel (0)
+                              CsmaEncapsulationMode encapMode)
+  : m_bps (DataRate (0xffffffff)),
+    m_receiveErrorModel (0),
+    m_node (node),
+    m_address (addr),
+    m_name (""),
+    m_linkUp (false),
+    m_mtu (0xffff)
 {
   NS_LOG_FUNCTION;
   NS_LOG_PARAMS (this << node);
@@ -105,19 +98,6 @@
   Init(true, true);
 }
 
-CsmaNetDevice::CsmaNetDevice (Ptr<Node> node, Mac48Address addr, 
-                              CsmaEncapsulationMode encapMode,
-                              bool sendEnable, bool receiveEnable) 
-  : NetDevice(node, addr), 
-    m_bps (DataRate (0xffffffff))
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << node);
-  m_encapMode = encapMode;
-
-  Init(sendEnable, receiveEnable);
-}
-
 CsmaNetDevice::~CsmaNetDevice()
 {
   NS_LOG_FUNCTION;
@@ -129,27 +109,10 @@
 {
   NS_LOG_FUNCTION;
   m_channel = 0;
+  m_node = 0;
   NetDevice::DoDispose ();
 }
 
-//
-// Assignment operator for CsmaNetDevice.
-//
-// This uses the non-obvious trick of taking the source net device passed by
-// value instead of by reference.  This causes the copy constructor to be
-// invoked (where the real work is done -- see above).  All we have to do
-// here is to return the newly constructed net device.
-//
-/*
-CsmaNetDevice&
-CsmaNetDevice::operator= (const CsmaNetDevice nd)
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << &nd);
-  return *this;
-}
-*/
-
 void 
 CsmaNetDevice::Init(bool sendEnable, bool receiveEnable)
 {
@@ -159,9 +122,6 @@
   m_channel = 0; 
   m_queue = 0;
 
-  EnableBroadcast (Mac48Address ("ff:ff:ff:ff:ff:ff"));
-  EnableMulticast (Mac48Address ("01:00:5e:00:00:00"));
-
   SetSendEnable (sendEnable);
   SetReceiveEnable (receiveEnable);
 }
@@ -302,58 +262,6 @@
   return true;
 }
 
-bool
-CsmaNetDevice::DoNeedsArp (void) const
-{
-  NS_LOG_FUNCTION;
-  if ((m_encapMode == IP_ARP) || (m_encapMode == LLC))
-    {
-      return true;
-    } 
-  else 
-    {
-      return false;
-    }
-}
-
-bool
-CsmaNetDevice::SendTo (Ptr<Packet> packet, 
-                       const Address& dest, 
-                       uint16_t protocolNumber)
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_LOGIC ("p=" << packet);
-  NS_LOG_LOGIC ("UID is " << packet->GetUid () << ")");
-
-  NS_ASSERT (IsLinkUp ());
-
-  // Only transmit if send side of net device is enabled
-  if (!IsSendEnabled())
-    return false;
-
-  Mac48Address destination = Mac48Address::ConvertFrom (dest);
-  AddHeader(packet, destination, protocolNumber);
-
-  // Place the packet to be sent on the send queue
-  if (m_queue->Enqueue(packet) == false )
-    {
-      return false;
-    }
-  // If the device is idle, we need to start a transmission. Otherwise,
-  // the transmission will be started when the current packet finished
-  // transmission (see TransmitCompleteEvent)
-  if (m_txMachineState == READY) 
-    {
-      // Store the next packet to be transmitted
-      m_currentPkt = m_queue->Dequeue ();
-      if (m_currentPkt != 0)
-        {
-          TransmitStart();
-        }
-    }
-  return true;
-}
-
 void
 CsmaNetDevice::TransmitStart ()
 {
@@ -565,7 +473,7 @@
 
   if (m_encapMode == RAW)
     {
-      ForwardUp (packet, 0, GetBroadcast ());
+      m_rxCallback (this, packet, 0, GetBroadcast ());
       m_dropTrace (packet);
       return;
     }
@@ -636,12 +544,100 @@
           NS_ASSERT (false);
           break;
         }
-      ForwardUp (packet, protocol, header.GetSource ());
+      m_rxCallback (this, packet, protocol, header.GetSource ());
+    }
+}
+
+Ptr<Queue>
+CsmaNetDevice::GetQueue(void) const 
+{ 
+  NS_LOG_FUNCTION;
+  return m_queue;
+}
+
+void
+CsmaNetDevice::NotifyLinkUp (void)
+{
+  m_linkUp = true;
+  if (!m_linkChangeCallback.IsNull ())
+    {
+      m_linkChangeCallback ();
     }
 }
 
+void 
+CsmaNetDevice::SetName(const std::string name)
+{
+  m_name = name;
+}
+std::string 
+CsmaNetDevice::GetName(void) const
+{
+  return m_name;
+}
+void 
+CsmaNetDevice::SetIfIndex(const uint32_t index)
+{
+  m_ifIndex = index;
+}
+uint32_t 
+CsmaNetDevice::GetIfIndex(void) const
+{
+  return m_ifIndex;
+}
+Ptr<Channel> 
+CsmaNetDevice::GetChannel (void) const
+{
+  return m_channel;
+}
+Address 
+CsmaNetDevice::GetAddress (void) const
+{
+  return m_address;
+}
+bool 
+CsmaNetDevice::SetMtu (const uint16_t mtu)
+{
+  m_mtu = mtu;
+  return true;
+}
+uint16_t 
+CsmaNetDevice::GetMtu (void) const
+{
+  return m_mtu;
+}
+bool 
+CsmaNetDevice::IsLinkUp (void) const
+{
+  return m_linkUp;
+}
+void 
+CsmaNetDevice::SetLinkChangeCallback (Callback<void> callback)
+{
+  m_linkChangeCallback = callback;
+}
+bool 
+CsmaNetDevice::IsBroadcast (void) const
+{
+  return true;
+}
 Address
-CsmaNetDevice::MakeMulticastAddress(Ipv4Address multicastGroup) const
+CsmaNetDevice::GetBroadcast (void) const
+{
+  return Mac48Address ("ff:ff:ff:ff:ff:ff");
+}
+bool 
+CsmaNetDevice::IsMulticast (void) const
+{
+  return false;
+}
+Address 
+CsmaNetDevice::GetMulticast (void) const
+{
+  return Mac48Address ("01:00:5e:00:00:00");
+}
+Address 
+CsmaNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
 {
   NS_LOG_FUNCTION;
   NS_LOG_PARAMS (this << multicastGroup);
@@ -692,20 +688,67 @@
 
   return etherAddr;
 }
+bool 
+CsmaNetDevice::IsPointToPoint (void) const
+{
+  return false;
+}
+bool 
+CsmaNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_LOGIC ("p=" << packet);
+  NS_LOG_LOGIC ("UID is " << packet->GetUid () << ")");
 
-Ptr<Queue>
-CsmaNetDevice::GetQueue(void) const 
-{ 
-  NS_LOG_FUNCTION;
-  return m_queue;
+  NS_ASSERT (IsLinkUp ());
+
+  // Only transmit if send side of net device is enabled
+  if (!IsSendEnabled())
+    return false;
+
+  Mac48Address destination = Mac48Address::ConvertFrom (dest);
+  AddHeader(packet, destination, protocolNumber);
+
+  // Place the packet to be sent on the send queue
+  if (m_queue->Enqueue(packet) == false )
+    {
+      return false;
+    }
+  // If the device is idle, we need to start a transmission. Otherwise,
+  // the transmission will be started when the current packet finished
+  // transmission (see TransmitCompleteEvent)
+  if (m_txMachineState == READY) 
+    {
+      // Store the next packet to be transmitted
+      m_currentPkt = m_queue->Dequeue ();
+      if (m_currentPkt != 0)
+        {
+          TransmitStart();
+        }
+    }
+  return true;
+}
+Ptr<Node> 
+CsmaNetDevice::GetNode (void) const
+{
+  return m_node;
+}
+bool 
+CsmaNetDevice::NeedsArp (void) const
+{
+  if ((m_encapMode == IP_ARP) || (m_encapMode == LLC))
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+void 
+CsmaNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+  m_rxCallback = cb;
 }
 
-Ptr<Channel>
-CsmaNetDevice::DoGetChannel(void) const 
-{ 
-  NS_LOG_FUNCTION;
-  return m_channel;
-}
-
-
 } // namespace ns3
--- a/src/devices/csma/csma-net-device.h	Sun Feb 24 20:18:02 2008 +0100
+++ b/src/devices/csma/csma-net-device.h	Mon Feb 25 19:33:46 2008 +0100
@@ -98,7 +98,6 @@
   LLC,         /**< LLC packet encapsulation */  
 };
 
-  CsmaNetDevice (Ptr<Node> node);
   /**
    * Construct a CsmaNetDevice
    *
@@ -113,22 +112,6 @@
   CsmaNetDevice (Ptr<Node> node, Mac48Address addr, CsmaEncapsulationMode pktType);
 
   /**
-   * Construct a CsmaNetDevice
-   *
-   * This is the constructor for the CsmaNetDevice.  It takes as a
-   * parameter the Node to which this device is connected.  Ownership of the
-   * Node pointer is not implied and the node must not be deleted.
-   *
-   * \param node the Node to which this device is connected.
-   * \param addr The source MAC address of the net device.
-   * \param pktType the type of encapsulation
-   * \param sendEnable whether this device is able to send
-   * \param receiveEnable whether this device is able to receive
-   */
-  CsmaNetDevice (Ptr<Node> node, Mac48Address addr,
-                   CsmaEncapsulationMode pktType,
-                   bool sendEnable, bool receiveEnable);
-  /**
    * Destroy a CsmaNetDevice
    *
    * This is the destructor for the CsmaNetDevice.
@@ -216,6 +199,28 @@
    */
   void Receive (Ptr<Packet> p);
 
+  bool IsSendEnabled (void);
+  bool IsReceiveEnabled (void);
+
+  void SetSendEnable (bool);
+  void SetReceiveEnable (bool);
+
+
+  // inherited from NetDevice base class.
+  virtual void SetName(const std::string name);
+  virtual std::string GetName(void) const;
+  virtual void SetIfIndex(const uint32_t index);
+  virtual uint32_t GetIfIndex(void) const;
+  virtual Ptr<Channel> GetChannel (void) const;
+  virtual Address GetAddress (void) const;
+  virtual bool SetMtu (const uint16_t mtu);
+  virtual uint16_t GetMtu (void) const;
+  virtual bool IsLinkUp (void) const;
+  virtual void SetLinkChangeCallback (Callback<void> callback);
+  virtual bool IsBroadcast (void) const;
+  virtual Address GetBroadcast (void) const;
+  virtual bool IsMulticast (void) const;
+  virtual Address GetMulticast (void) const;
   /**
    * @brief Make and return a MAC multicast address using the provided
    *        multicast group
@@ -229,13 +234,6 @@
    * to an EUI-48-based CSMA device.  This MAC address is encapsulated in an
    *  abstract Address to avoid dependencies on the exact address format.
    *
-   * A default imlementation of MakeMulticastAddress is provided, but this
-   * method simply NS_ASSERTS.  In the case of net devices that do not support
-   * multicast, clients are expected to test NetDevice::IsMulticast and avoid
-   * attempting to map multicast packets.  Subclasses of NetDevice that do
-   * support multicasting are expected to override this method and provide an
-   * implementation appropriate to the particular device.
-   *
    * @param multicastGroup The IP address for the multicast group destination
    * of the packet.
    * @return The MAC multicast Address used to send packets to the provided
@@ -245,16 +243,14 @@
    * @see Mac48Address
    * @see Address
    */
-  Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
-
-  bool IsSendEnabled (void);
-  bool IsReceiveEnabled (void);
-
-  void SetSendEnable (bool);
-  void SetReceiveEnable (bool);
+  virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
+  virtual bool IsPointToPoint (void) const;
+  virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+  virtual Ptr<Node> GetNode (void) const;
+  virtual bool NeedsArp (void) const;
+  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
 
 protected:
-  virtual bool DoNeedsArp (void) const;
   virtual void DoDispose (void);
   /**
    * Create a Trace Resolver for events in the net device.
@@ -273,15 +269,6 @@
    */
   Ptr<Queue> GetQueue (void) const; 
   /**
-   * Get a copy of the attached Channel
-   *
-   * This method is provided for any derived class that may need to get
-   * direct access to the connected channel
-   *
-   * \return a pointer to the channel
-   */
-  virtual Ptr<Channel> DoGetChannel (void) const;
-  /**
    * Adds the necessary headers and trailers to a packet of data in order to
    * respect the packet type
    *
@@ -312,22 +299,6 @@
    * Initializes variablea when construction object.
    */
   void Init (bool sendEnable, bool receiveEnable);
-  /**
-   * Send a Packet on the Csma network
-   *
-   * This method does not use a destination address since all packets
-   * are broadcast to all NetDevices attached to the channel. Packet
-   * should contain all needed headers at this time.
-   *
-   * If the device is ready to transmit, the next packet is read off
-   * of the queue and stored locally until it has been transmitted.
-   *
-   * \param p a reference to the packet to send
-   * \param dest destination address
-   * \param protocolNumber -- this parameter is not used here
-   * \return true if success, false on failure
-   */
-  virtual bool SendTo (Ptr<Packet> p, const Address& dest, uint16_t protocolNumber);
 
   /**
    * Start Sending a Packet Down the Wire.
@@ -388,6 +359,7 @@
    *
    */
   void TransmitAbort (void);
+  void NotifyLinkUp (void);
 
   /** 
    * Device ID returned by the attached functions. It is used by the
@@ -481,6 +453,14 @@
   CallbackTraceSource<Ptr<const Packet> > m_rxTrace;
   CallbackTraceSource<Ptr<const Packet> > m_dropTrace;
 
+  Ptr<Node> m_node;
+  Mac48Address m_address;
+  NetDevice::ReceiveCallback m_rxCallback;
+  uint32_t m_ifIndex;
+  std::string m_name;
+  bool m_linkUp;
+  Callback<void> m_linkChangeCallback;
+  uint16_t m_mtu;
 };
 
 }; // namespace ns3
--- a/src/devices/point-to-point/point-to-point-net-device.cc	Sun Feb 24 20:18:02 2008 +0100
+++ b/src/devices/point-to-point/point-to-point-net-device.cc	Mon Feb 25 19:33:46 2008 +0100
@@ -86,9 +86,9 @@
 }
 
 PointToPointNetDevice::PointToPointNetDevice (Ptr<Node> node,
+                                              Mac48Address address,
                                               const DataRate& rate) 
 : 
-  NetDevice(node, Mac48Address::Allocate ()), 
   m_txMachineState (READY),
   m_bps (rate),
   m_tInterframeGap (Seconds(0)),
@@ -96,29 +96,19 @@
   m_queue (0),
   m_rxTrace (),
   m_dropTrace (),
-  m_receiveErrorModel (0)
+  m_receiveErrorModel (0),
+  m_node (node),
+  m_address (address),
+  m_name (""),
+  m_linkUp (false),
+  m_mtu (0xffff)
 {
   NS_LOG_FUNCTION;
   NS_LOG_PARAMS (this << node);
-//
-// XXX BUGBUG
-//
-// You _must_ support broadcast to get any sort of packet from the ARP layer.
-//
-  EnableBroadcast (Mac48Address ("ff:ff:ff:ff:ff:ff"));
-//
-// We want to allow multicast packets to flow across this link
-//
-  EnableMulticast (Mac48Address ("01:00:5e:00:00:00"));
-  EnablePointToPoint();
 }
 
-PointToPointNetDevice::~PointToPointNetDevice()
-{
-  NS_LOG_FUNCTION;
-  m_queue = 0;
-  m_receiveErrorModel = 0;
-}
+PointToPointNetDevice::~PointToPointNetDevice ()
+{}
 
 void 
 PointToPointNetDevice::AddHeader(Ptr<Packet> p, uint16_t protocolNumber)
@@ -144,7 +134,9 @@
 void PointToPointNetDevice::DoDispose()
 {
   NS_LOG_FUNCTION;
+  m_node = 0;
   m_channel = 0;
+  m_receiveErrorModel = 0;
   NetDevice::DoDispose ();
 }
 
@@ -163,40 +155,7 @@
   m_tInterframeGap = t;
 }
 
-bool PointToPointNetDevice::SendTo (Ptr<Packet> packet, const Address& dest, 
-                                    uint16_t protocolNumber)
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_LOGIC ("p=" << packet << ", dest=" << &dest);
-  NS_LOG_LOGIC ("UID is " << packet->GetUid ());
-
-  // GFR Comment. Why is this an assertion? Can't a link legitimately
-  // "go down" during the simulation?  Shouldn't we just wait for it
-  // to come back up?
-  NS_ASSERT (IsLinkUp ());
-  AddHeader(packet, protocolNumber);
-
-//
-// This class simulates a point to point device.  In the case of a serial
-// link, this means that we're simulating something like a UART.
-//
-//
-// If there's a transmission in progress, we enque the packet for later
-// transmission; otherwise we send it now.
-  if (m_txMachineState == READY) 
-    {
-// We still enqueue and dequeue it to hit the tracing hooks
-      m_queue->Enqueue (packet);
-      packet = m_queue->Dequeue ();
-      return TransmitStart (packet);
-    }
-  else
-    {
-      return m_queue->Enqueue(packet);
-    }
-}
-
-  bool
+bool
 PointToPointNetDevice::TransmitStart (Ptr<Packet> p)
 {
   NS_LOG_FUNCTION;
@@ -320,7 +279,7 @@
     {
       m_rxTrace (packet);
       ProcessHeader(packet, protocol);
-      ForwardUp (packet, protocol, GetBroadcast ());
+      m_rxCallback (this, packet, protocol, GetBroadcast ());
     }
 }
 
@@ -330,16 +289,144 @@
   return m_queue;
 }
 
-Ptr<Channel> PointToPointNetDevice::DoGetChannel(void) const 
-{ 
-  NS_LOG_FUNCTION;
-  return m_channel;
+void
+PointToPointNetDevice::NotifyLinkUp (void)
+{
+  m_linkUp = true;
+  if (!m_linkChangeCallback.IsNull ())
+    {
+      m_linkChangeCallback ();
+    }
 }
 
-bool PointToPointNetDevice::DoNeedsArp (void) const
+void 
+PointToPointNetDevice::SetName(const std::string name)
+{
+  m_name = name;
+}
+std::string 
+PointToPointNetDevice::GetName(void) const
+{
+  return m_name;
+}
+void 
+PointToPointNetDevice::SetIfIndex(const uint32_t index)
+{
+  m_ifIndex = index;
+}
+uint32_t 
+PointToPointNetDevice::GetIfIndex(void) const
+{
+  return m_ifIndex;
+}
+Ptr<Channel> 
+PointToPointNetDevice::GetChannel (void) const
+{
+  return m_channel;
+}
+Address 
+PointToPointNetDevice::GetAddress (void) const
 {
-  NS_LOG_FUNCTION;
+  return m_address;
+}
+bool 
+PointToPointNetDevice::SetMtu (const uint16_t mtu)
+{
+  m_mtu = mtu;
+  return true;
+}
+uint16_t 
+PointToPointNetDevice::GetMtu (void) const
+{
+  return m_mtu;
+}
+bool 
+PointToPointNetDevice::IsLinkUp (void) const
+{
+  return m_linkUp;
+}
+void 
+PointToPointNetDevice::SetLinkChangeCallback (Callback<void> callback)
+{
+  m_linkChangeCallback = callback;
+}
+bool 
+PointToPointNetDevice::IsBroadcast (void) const
+{
+  return true;
+}
+Address
+PointToPointNetDevice::GetBroadcast (void) const
+{
+  return Mac48Address ("ff:ff:ff:ff:ff:ff");
+}
+bool 
+PointToPointNetDevice::IsMulticast (void) const
+{
   return false;
 }
+Address 
+PointToPointNetDevice::GetMulticast (void) const
+{
+  return Mac48Address ("01:00:5e:00:00:00");
+}
+Address 
+PointToPointNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
+{
+  return Mac48Address ("01:00:5e:00:00:00");
+}
+bool 
+PointToPointNetDevice::IsPointToPoint (void) const
+{
+  return true;
+}
+bool 
+PointToPointNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
+{
+    NS_LOG_FUNCTION;
+  NS_LOG_LOGIC ("p=" << packet << ", dest=" << &dest);
+  NS_LOG_LOGIC ("UID is " << packet->GetUid ());
+
+  // GFR Comment. Why is this an assertion? Can't a link legitimately
+  // "go down" during the simulation?  Shouldn't we just wait for it
+  // to come back up?
+  NS_ASSERT (IsLinkUp ());
+  AddHeader(packet, protocolNumber);
+
+//
+// This class simulates a point to point device.  In the case of a serial
+// link, this means that we're simulating something like a UART.
+//
+//
+// If there's a transmission in progress, we enque the packet for later
+// transmission; otherwise we send it now.
+  if (m_txMachineState == READY) 
+    {
+// We still enqueue and dequeue it to hit the tracing hooks
+      m_queue->Enqueue (packet);
+      packet = m_queue->Dequeue ();
+      return TransmitStart (packet);
+    }
+  else
+    {
+      return m_queue->Enqueue(packet);
+    }
+}
+Ptr<Node> 
+PointToPointNetDevice::GetNode (void) const
+{
+  return m_node;
+}
+bool 
+PointToPointNetDevice::NeedsArp (void) const
+{
+  return false;
+}
+void 
+PointToPointNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+  m_rxCallback = cb;
+}
+
 
 } // namespace ns3
--- a/src/devices/point-to-point/point-to-point-net-device.h	Sun Feb 24 20:18:02 2008 +0100
+++ b/src/devices/point-to-point/point-to-point-net-device.h	Mon Feb 25 19:33:46 2008 +0100
@@ -32,6 +32,7 @@
 #include "ns3/data-rate.h"
 #include "ns3/default-value.h"
 #include "ns3/ptr.h"
+#include "ns3/mac48-address.h"
 
 namespace ns3 {
 
@@ -74,7 +75,8 @@
  * include a queue, data rate, and interframe transmission gap (the 
  * propagation delay is set in the PointToPointChannel).
  */
-class PointToPointNetDevice : public NetDevice {
+class PointToPointNetDevice : public NetDevice 
+{
 public:
   /**
    * Construct a PointToPointNetDevice
@@ -88,6 +90,7 @@
    * @param rate (optional) DataRate object
    */
   PointToPointNetDevice (Ptr<Node> node,
+                         Mac48Address address,
                          const DataRate& rate = g_defaultRate.GetValue());
   /**
    * Destroy a PointToPointNetDevice
@@ -168,6 +171,28 @@
    */
   void Receive (Ptr<Packet> p);
 
+  // inherited from NetDevice base class.
+  virtual void SetName(const std::string name);
+  virtual std::string GetName(void) const;
+  virtual void SetIfIndex(const uint32_t index);
+  virtual uint32_t GetIfIndex(void) const;
+  virtual Ptr<Channel> GetChannel (void) const;
+  virtual Address GetAddress (void) const;
+  virtual bool SetMtu (const uint16_t mtu);
+  virtual uint16_t GetMtu (void) const;
+  virtual bool IsLinkUp (void) const;
+  virtual void SetLinkChangeCallback (Callback<void> callback);
+  virtual bool IsBroadcast (void) const;
+  virtual Address GetBroadcast (void) const;
+  virtual bool IsMulticast (void) const;
+  virtual Address GetMulticast (void) const;
+  virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
+  virtual bool IsPointToPoint (void) const;
+  virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+  virtual Ptr<Node> GetNode (void) const;
+  virtual bool NeedsArp (void) const;
+  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
+
 private:
   /**
    * Create a Trace Resolver for events in the net device.
@@ -188,16 +213,6 @@
    */
   Ptr<Queue> GetQueue(void) const; 
 
-  /**
-   * Get a copy of the attached Channel
-   *
-   * This method is provided for any derived class that may need to get
-   * direct access to the connected channel
-   *
-   * @see PointToPointChannel
-   * @returns a pointer to the channel
-   */
-  virtual Ptr<Channel> DoGetChannel(void) const;
 
   /**
    * Set a new default data rate
@@ -224,21 +239,6 @@
    */
   bool ProcessHeader(Ptr<Packet> p, uint16_t& param);
   /**
-   * Send a Packet Down the Wire.
-   *
-   * The SendTo method is defined as the standard way that the level three
-   * protocol uses to tell a NetDevice to send a packet.  SendTo is declared
-   * as abstract in the NetDevice class and we declare it here.
-   *
-   * @see NetDevice
-   * @param p a reference to the packet to send
-   * @param dest a reference to the Address of the destination device
-   * @param protocolNumber Protocol Number used to find protocol touse
-   * @returns true if success, false on failure
-   */
-  virtual bool SendTo (Ptr<Packet> p, const Address& dest, 
-                       uint16_t protocolNumber);
-  /**
    * Start Sending a Packet Down the Wire.
    *
    * The TransmitStart method is the method that is used internally in the
@@ -262,7 +262,8 @@
    *
    */
   void TransmitComplete(void);
-  virtual bool DoNeedsArp (void) const;
+  void NotifyLinkUp (void);
+
   /**
    * Enumeration of the states of the transmit machine of the net device.
    */
@@ -327,6 +328,15 @@
    * Error model for receive packet events
    */
   Ptr<ErrorModel> m_receiveErrorModel;
+
+  Ptr<Node> m_node;
+  Mac48Address m_address;
+  NetDevice::ReceiveCallback m_rxCallback;
+  uint32_t m_ifIndex;
+  std::string m_name;
+  bool m_linkUp;
+  Callback<void> m_linkChangeCallback;
+  uint16_t m_mtu;
 };
 
 }; // namespace ns3
--- a/src/devices/point-to-point/point-to-point-topology.cc	Sun Feb 24 20:18:02 2008 +0100
+++ b/src/devices/point-to-point/point-to-point-topology.cc	Mon Feb 25 19:33:46 2008 +0100
@@ -47,13 +47,15 @@
 {
   Ptr<PointToPointChannel> channel = CreateObject<PointToPointChannel> (bps, delay);
 
-  Ptr<PointToPointNetDevice> net1 = CreateObject<PointToPointNetDevice> (n1);
+  Ptr<PointToPointNetDevice> net1 = CreateObject<PointToPointNetDevice> (n1, Mac48Address::Allocate ());
+  n1->AddDevice (net1);
 
   Ptr<Queue> q = Queue::CreateDefault ();
   net1->AddQueue(q);
   net1->Attach (channel);
   
-  Ptr<PointToPointNetDevice> net2 = CreateObject<PointToPointNetDevice> (n2);
+  Ptr<PointToPointNetDevice> net2 = CreateObject<PointToPointNetDevice> (n2, Mac48Address::Allocate ());
+  n2->AddDevice (net2);
 
   q = Queue::CreateDefault ();
   net2->AddQueue(q);
--- a/src/devices/wifi/wifi-net-device.cc	Sun Feb 24 20:18:02 2008 +0100
+++ b/src/devices/wifi/wifi-net-device.cc	Mon Feb 25 19:33:46 2008 +0100
@@ -158,14 +158,12 @@
  ***************************************************************/
 
 
-WifiNetDevice::WifiNetDevice (Ptr<Node> node)
-  : NetDevice (node, Mac48Address::Allocate ())
-{
-  Construct ();
-}
 
 WifiNetDevice::WifiNetDevice (Ptr<Node> node, Mac48Address self)
-  : NetDevice (node, self)
+  : m_node (node),
+    m_address (self),
+    m_name (""),
+    m_linkUp (false)
 {
   Construct ();
 }
@@ -176,9 +174,7 @@
 void
 WifiNetDevice::Construct (void)
 {
-  SetMtu (2300);
-  EnableBroadcast (Mac48Address ("ff:ff:ff:ff:ff:ff"));
-
+  m_mtu = 2300;
   // the physical layer.
   m_phy = Create<WifiPhy> (this);
 
@@ -307,21 +303,6 @@
   m_phy->SetChannel (channel);
   NotifyAttached ();
 }
-bool
-WifiNetDevice::SendTo (Ptr<Packet> packet, const Address &to, uint16_t protocolNumber)
-{
-  NS_ASSERT (Mac48Address::IsMatchingType (to));
-
-  Mac48Address realTo = Mac48Address::ConvertFrom (to);
-
-  LlcSnapHeader llc;
-  llc.SetType (protocolNumber);
-  packet->AddHeader (llc);
-
-  m_txLogger (packet, realTo);
-
-  return DoSendTo (packet, realTo);
-}
 void 
 WifiNetDevice::DoForwardUp (Ptr<Packet> packet, const Mac48Address &from)
 {
@@ -329,7 +310,7 @@
 
   LlcSnapHeader llc;
   packet->RemoveHeader (llc);
-  NetDevice::ForwardUp (packet, llc.GetType (), from);
+  m_rxCallback (this, packet, llc.GetType (), from);
 }
 Mac48Address 
 WifiNetDevice::GetSelfAddress (void) const
@@ -338,22 +319,11 @@
   Mac48Address self = Mac48Address::ConvertFrom (GetAddress ());
   return self;
 }
-bool 
-WifiNetDevice::DoNeedsArp (void) const
-{
-  return true;
-}
-Ptr<Channel> 
-WifiNetDevice::DoGetChannel (void) const
-{
-  return m_channel;
-}
 void 
 WifiNetDevice::DoDispose (void)
 {
-  // chain up.
-  NetDevice::DoDispose ();
   // cleanup local
+  m_node = 0;
   m_channel = 0;
   delete m_stations;
   delete m_low;
@@ -369,6 +339,136 @@
   m_rxMiddle = 0;
   m_txMiddle = 0;
   m_parameters = 0;
+  // chain up.
+  NetDevice::DoDispose ();
+}
+
+void
+WifiNetDevice::NotifyLinkUp (void)
+{
+  m_linkUp = true;
+  if (!m_linkChangeCallback.IsNull ())
+    {
+      m_linkChangeCallback ();
+    }
+}
+void
+WifiNetDevice::NotifyLinkDown (void)
+{
+  m_linkUp = false;
+  m_linkChangeCallback ();
+}
+
+void 
+WifiNetDevice::SetName(const std::string name)
+{
+  m_name = name;
+}
+std::string 
+WifiNetDevice::GetName(void) const
+{
+  return m_name;
+}
+void 
+WifiNetDevice::SetIfIndex(const uint32_t index)
+{
+  m_ifIndex = index;
+}
+uint32_t 
+WifiNetDevice::GetIfIndex(void) const
+{
+  return m_ifIndex;
+}
+Ptr<Channel> 
+WifiNetDevice::GetChannel (void) const
+{
+  return m_channel;
+}
+Address 
+WifiNetDevice::GetAddress (void) const
+{
+  return m_address;
+}
+bool 
+WifiNetDevice::SetMtu (const uint16_t mtu)
+{
+  m_mtu = mtu;
+  return true;
+}
+uint16_t 
+WifiNetDevice::GetMtu (void) const
+{
+  return m_mtu;
+}
+bool 
+WifiNetDevice::IsLinkUp (void) const
+{
+  return m_linkUp;
+}
+void 
+WifiNetDevice::SetLinkChangeCallback (Callback<void> callback)
+{
+  m_linkChangeCallback = callback;
+}
+bool 
+WifiNetDevice::IsBroadcast (void) const
+{
+  return true;
+}
+Address
+WifiNetDevice::GetBroadcast (void) const
+{
+  return Mac48Address ("ff:ff:ff:ff:ff:ff");
+}
+bool 
+WifiNetDevice::IsMulticast (void) const
+{
+  return false;
+}
+Address 
+WifiNetDevice::GetMulticast (void) const
+{
+  return Mac48Address ("01:00:5e:00:00:00");
+}
+Address 
+WifiNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
+{
+  return Mac48Address ("01:00:5e:00:00:00");
+}
+bool 
+WifiNetDevice::IsPointToPoint (void) const
+{
+  return false;
+}
+bool 
+WifiNetDevice::Send(Ptr<Packet> packet, const Address& to, uint16_t protocolNumber)
+{
+  NS_ASSERT (Mac48Address::IsMatchingType (to));
+
+  Mac48Address realTo = Mac48Address::ConvertFrom (to);
+
+  LlcSnapHeader llc;
+  llc.SetType (protocolNumber);
+  packet->AddHeader (llc);
+
+  m_txLogger (packet, realTo);
+
+  return DoSendTo (packet, realTo);
+}
+Ptr<Node> 
+WifiNetDevice::GetNode (void) const
+{
+  return m_node;
+}
+bool 
+WifiNetDevice::NeedsArp (void) const
+{
+  return true;
+}
+void 
+WifiNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+  m_rxCallback = cb;
 }
 
 
@@ -376,11 +476,6 @@
  *            Adhoc code
  *****************************************************/
 
-AdhocWifiNetDevice::AdhocWifiNetDevice (Ptr<Node> node)
-  : WifiNetDevice (node)
-{
-  DoConstruct ();
-}
 AdhocWifiNetDevice::AdhocWifiNetDevice (Ptr<Node> node, Mac48Address self)
   : WifiNetDevice (node, self)
 {
@@ -449,11 +544,6 @@
  *            STA code
  *****************************************************/
 
-NqstaWifiNetDevice::NqstaWifiNetDevice (Ptr<Node> node)
-  : WifiNetDevice (node)
-{
-  DoConstruct ();
-}
 NqstaWifiNetDevice::NqstaWifiNetDevice (Ptr<Node> node, Mac48Address self)
   : WifiNetDevice (node, self)
 {
@@ -513,13 +603,13 @@
 void 
 NqstaWifiNetDevice::Associated (void)
 {
-  NetDevice::NotifyLinkUp ();
+  WifiNetDevice::NotifyLinkUp ();
 }
 
 void 
 NqstaWifiNetDevice::DisAssociated (void)
 {
-  NetDevice::NotifyLinkDown ();
+  WifiNetDevice::NotifyLinkDown ();
 }
 void 
 NqstaWifiNetDevice::DoDispose (void)
@@ -539,11 +629,6 @@
  *****************************************************/
 
 
-NqapWifiNetDevice::NqapWifiNetDevice (Ptr<Node> node)
-  : WifiNetDevice (node)
-{
-  DoConstruct ();
-}
 NqapWifiNetDevice::NqapWifiNetDevice (Ptr<Node> node, Mac48Address self)
   : WifiNetDevice (node, self)
 {
--- a/src/devices/wifi/wifi-net-device.h	Sun Feb 24 20:18:02 2008 +0100
+++ b/src/devices/wifi/wifi-net-device.h	Mon Feb 25 19:33:46 2008 +0100
@@ -98,14 +98,32 @@
    */
   virtual Ssid GetSsid (void) const = 0;
 
+  // inherited from NetDevice base class.
+  virtual void SetName(const std::string name);
+  virtual std::string GetName(void) const;
+  virtual void SetIfIndex(const uint32_t index);
+  virtual uint32_t GetIfIndex(void) const;
+  virtual Ptr<Channel> GetChannel (void) const;
+  virtual Address GetAddress (void) const;
+  virtual bool SetMtu (const uint16_t mtu);
+  virtual uint16_t GetMtu (void) const;
+  virtual bool IsLinkUp (void) const;
+  virtual void SetLinkChangeCallback (Callback<void> callback);
+  virtual bool IsBroadcast (void) const;
+  virtual Address GetBroadcast (void) const;
+  virtual bool IsMulticast (void) const;
+  virtual Address GetMulticast (void) const;
+  virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
+  virtual bool IsPointToPoint (void) const;
+  virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+  virtual Ptr<Node> GetNode (void) const;
+  virtual bool NeedsArp (void) const;
+  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
+
 private:
   class PhyListener;
   class NavListener;
 
-  // inherited from NetDevice
-  virtual bool DoNeedsArp (void) const;
-  virtual Ptr<Channel> DoGetChannel (void) const;
-  virtual bool SendTo (Ptr<Packet> packet, const Address &to, uint16_t protocolNumber);
   // inherited from Object
   virtual Ptr<TraceResolver> GetTraceResolver (void) const;
   // defined for children
@@ -117,10 +135,11 @@
   CallbackTraceSource<Ptr<const Packet>, Mac48Address> m_rxLogger;
   CallbackTraceSource<Ptr<const Packet>, Mac48Address> m_txLogger;
 protected:
-  WifiNetDevice (Ptr<Node> node);
   WifiNetDevice (Ptr<Node> node, Mac48Address self);
   void DoForwardUp (Ptr<Packet> packet, const Mac48Address &from);
   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);
 
@@ -134,6 +153,15 @@
   DcfManager *m_manager;
   PhyListener *m_phyListener;
   NavListener *m_navListener;
+
+  Ptr<Node> m_node;
+  Mac48Address m_address;
+  NetDevice::ReceiveCallback m_rxCallback;
+  uint32_t m_ifIndex;
+  std::string m_name;
+  bool m_linkUp;
+  Callback<void> m_linkChangeCallback;
+  uint16_t m_mtu;
 };
 
 /**
@@ -144,7 +172,6 @@
  */
 class AdhocWifiNetDevice : public WifiNetDevice {
 public:
-  AdhocWifiNetDevice (Ptr<Node> node);
   AdhocWifiNetDevice (Ptr<Node> node, Mac48Address self);
   virtual ~AdhocWifiNetDevice ();
 
@@ -183,7 +210,6 @@
   /**
    * The ssid is initialized from \valueref{WifiSsid}.
    */
-  NqstaWifiNetDevice (Ptr<Node> node);
   NqstaWifiNetDevice (Ptr<Node> node, Mac48Address self);
   virtual ~NqstaWifiNetDevice ();
 
--- a/src/internet-node/udp-socket.cc	Sun Feb 24 20:18:02 2008 +0100
+++ b/src/internet-node/udp-socket.cc	Mon Feb 25 19:33:46 2008 +0100
@@ -388,7 +388,8 @@
   
   // Receiver Node
   Ptr<Node> rxNode = CreateObject<InternetNode> ();
-  Ptr<PointToPointNetDevice> rxDev = CreateObject<PointToPointNetDevice> (rxNode);
+  Ptr<PointToPointNetDevice> rxDev = CreateObject<PointToPointNetDevice> (rxNode, Mac48Address::Allocate ());
+  rxNode->AddDevice (rxDev);
   rxDev->AddQueue(CreateObject<DropTailQueue> ());
   Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
   uint32_t netdev_idx = ipv4->AddInterface (rxDev);
@@ -398,7 +399,8 @@
 
   // Sender Node
   Ptr<Node> txNode = CreateObject<InternetNode> ();
-  Ptr<PointToPointNetDevice> txDev = CreateObject<PointToPointNetDevice> (txNode);
+  Ptr<PointToPointNetDevice> txDev = CreateObject<PointToPointNetDevice> (txNode, Mac48Address::Allocate ());
+  txNode->AddDevice (txDev);
   txDev->AddQueue(CreateObject<DropTailQueue> ());
   ipv4 = txNode->GetObject<Ipv4> ();
   netdev_idx = ipv4->AddInterface (txDev);
--- a/src/node/net-device.cc	Sun Feb 24 20:18:02 2008 +0100
+++ b/src/node/net-device.cc	Mon Feb 25 19:33:46 2008 +0100
@@ -19,15 +19,9 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 
-#include <iostream>
-#include "ns3/assert.h"
 #include "ns3/object.h"
 #include "ns3/log.h"
-#include "ns3/trace-resolver.h"
-#include "ns3/packet.h"
-#include "channel.h"
 #include "net-device.h"
-#include "node.h"
 
 NS_LOG_COMPONENT_DEFINE ("NetDevice");
 
@@ -42,272 +36,7 @@
   return tid;
 }
 
-NetDevice::NetDevice(Ptr<Node> node, const Address& addr) : 
-  m_node (node), 
-  m_name(""), 
-  m_ifIndex (0), 
-  m_address (addr),
-  m_mtu (0xffff), 
-  m_isUp (false), 
-  m_isBroadcast (false), 
-  m_isMulticast (false), 
-  m_isPointToPoint (false)
-{
-  NS_LOG_FUNCTION;
-  m_node->AddDevice (this);
-}
-
 NetDevice::~NetDevice ()
-{
-  NS_LOG_FUNCTION;
-}
-
-Address 
-NetDevice::GetAddress (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_address;
-}
-
-bool
-NetDevice::SetMtu (const uint16_t mtu) 
-{
-  NS_LOG_FUNCTION;
-  m_mtu = mtu;
-  return true;
-}
-
-uint16_t 
-NetDevice::GetMtu (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_mtu;
-}
-
-void
-NetDevice::SetName(const std::string name) 
-{ 
-  NS_LOG_FUNCTION;
-  m_name = name; 
-}
-
-std::string 
-NetDevice::GetName(void) const 
-{ 
-  NS_LOG_FUNCTION;
-  return m_name; 
-}
-
-void
-NetDevice::SetIfIndex(uint32_t index) 
-{ 
-  NS_LOG_FUNCTION;
-  m_ifIndex = index; 
-}
-
-uint32_t
-NetDevice::GetIfIndex(void) const 
-{ 
-  NS_LOG_FUNCTION;
-  return m_ifIndex; 
-}
-
-bool 
-NetDevice::IsLinkUp (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_isUp;
-}
-
-void 
-NetDevice::SetLinkChangeCallback (Callback<void> callback)
-{
-  NS_LOG_FUNCTION;
-  m_linkChangeCallback = callback;
-}
-
-bool
-NetDevice::IsBroadcast (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_isBroadcast;
-}
-
-Address const &
-NetDevice::GetBroadcast (void) const
-{
-  NS_LOG_FUNCTION;
-  NS_ASSERT (m_isBroadcast);
-  return m_broadcast;
-}
-
-void
-NetDevice::EnableBroadcast (Address broadcast)
-{
-  NS_LOG_FUNCTION;
-  m_isBroadcast = true;
-  m_broadcast = broadcast;
-}
-
-void
-NetDevice::DisableBroadcast (void)
-{
-  NS_LOG_FUNCTION;
-  m_isBroadcast = false;
-}
-
-bool
-NetDevice::IsMulticast (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_isMulticast;
-}
-
-Address 
-NetDevice::GetMulticast (void) const
-{
-  NS_LOG_FUNCTION;
-  NS_ASSERT_MSG (m_isMulticast, "NetDevice::GetMulticast (): "
-    "Invalid operation when not IsMulticast ()");
-  return m_multicast;
-}
+{}
 
-Address
-NetDevice::MakeMulticastAddress(Ipv4Address multicastGroup) const
-{
-  NS_LOG_FUNCTION;
-  NS_ASSERT_MSG (m_isMulticast, "NetDevice::GetMulticast (): "
-    "Invalid operation when not IsMulticast ()");
-  return m_multicast;
-}
-
-void
-NetDevice::EnableMulticast (Address multicast)
-{
-  NS_LOG_FUNCTION;
-  m_isMulticast = true;
-  m_multicast = multicast;
-}
-
-void
-NetDevice::DisableMulticast (void)
-{
-  NS_LOG_FUNCTION;
-  m_isMulticast = false;
-}
-
-bool
-NetDevice::IsPointToPoint (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_isPointToPoint;
-}
-
-void
-NetDevice::EnablePointToPoint (void)
-{
-  NS_LOG_FUNCTION;
-  m_isPointToPoint = true;
-}
-
-void
-NetDevice::DisablePointToPoint (void)
-{
-  NS_LOG_FUNCTION;
-  m_isPointToPoint = false;
-}
-
-// Receive packet from above
-bool 
-NetDevice::Send(Ptr<Packet> p, const Address& dest, uint16_t protocolNumber)
-{
-  NS_LOG_FUNCTION;
-  if (m_isUp)
-    {
-      return SendTo(p, dest, protocolNumber);
-    }
-  else
-    {
-      return false;
-    }
-}
-
-Ptr<Channel>
-NetDevice::GetChannel (void) const
-{
-  NS_LOG_FUNCTION;
-  return DoGetChannel ();
-}
-
-// Receive packets from below
-bool
-NetDevice::ForwardUp(Ptr<Packet> p, uint16_t param, const Address &from)
-{
-  NS_LOG_FUNCTION;
-  bool retval = false;
-
-  NS_LOG_LOGIC ("UID is " << p->GetUid() << " device is: " << GetName());
-  
-  if (!m_receiveCallback.IsNull ())
-    {
-      retval = m_receiveCallback (this, p, param, from);
-    } 
-  else 
-    {
-      NS_LOG_WARN ("NetDevice::Receive call back is NULL");
-    }
-
-    return retval;
-}
-
-void 
-NetDevice::NotifyLinkUp (void)
-{
-  NS_LOG_FUNCTION;
-  m_isUp = true;
-  if (!m_linkChangeCallback.IsNull ())
-    {
-      m_linkChangeCallback ();
-    }
-}
-
-void 
-NetDevice::NotifyLinkDown (void)
-{
-  NS_LOG_FUNCTION;
-  m_isUp = false;
-  if (!m_linkChangeCallback.IsNull ())
-    {
-      m_linkChangeCallback ();
-    }
-}
-
-Ptr<Node>
-NetDevice::GetNode (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_node;
-}
-
-bool
-NetDevice::NeedsArp (void) const
-{
-  NS_LOG_FUNCTION;
-  return DoNeedsArp ();
-}
-
-void 
-NetDevice::SetReceiveCallback (ReceiveCallback cb)
-{
-  NS_LOG_FUNCTION;
-  m_receiveCallback = cb;
-}
-
-void
-NetDevice::DoDispose()
-{
-  NS_LOG_FUNCTION;
-  m_node = 0;
-}
-
-}; // namespace ns3
+} // namespace ns3
--- a/src/node/net-device.h	Sun Feb 24 20:18:02 2008 +0100
+++ b/src/node/net-device.h	Mon Feb 25 19:33:46 2008 +0100
@@ -63,52 +63,53 @@
   static TypeId GetTypeId (void);
   virtual ~NetDevice();
 
+  /**
+   * \param name name of the device (e.g. "eth0")
+   */
+  virtual void SetName(const std::string name) = 0;
+  /**
+   * \return name name of the device (e.g. "eth0")
+   */
+  virtual std::string GetName(void) const = 0;
+  /**
+   * \param index ifIndex of the device 
+   */
+  virtual void SetIfIndex(const uint32_t index) = 0;
+  /**
+   * \return index ifIndex of the device 
+   */
+  virtual uint32_t GetIfIndex(void) const = 0;
+
 
   /**
    * \return the channel this NetDevice is connected to. The value
    *         returned can be zero if the NetDevice is not yet connected
    *         to any channel.
    */
-  Ptr<Channel> GetChannel (void) const;
+  virtual Ptr<Channel> GetChannel (void) const = 0;
 
   /**
    * \return the current Address of this interface.
    */
-  Address GetAddress (void) const;
+  virtual Address GetAddress (void) const = 0;
   /**
    * \param mtu MTU value, in bytes, to set for the device
    * \return whether the MTU value was within legal bounds
    * 
    * Override for default MTU defined on a per-type basis.
    */
-  bool SetMtu (const uint16_t mtu);
+  virtual bool SetMtu (const uint16_t mtu) = 0;
   /**
    * \return the link-level MTU in bytes for this interface.
    * 
    * This value is typically used by the IP layer to perform
    * IP fragmentation when needed.
    */
-  uint16_t GetMtu (void) const;
-  /**
-   * \param name name of the device (e.g. "eth0")
-   */
-  void SetName(const std::string name); 
-  /**
-   * \return name name of the device (e.g. "eth0")
-   */
-  std::string GetName(void) const;
-  /**
-   * \param index ifIndex of the device 
-   */
-  void SetIfIndex(const uint32_t index);
-  /**
-   * \return index ifIndex of the device 
-   */
-  uint32_t GetIfIndex(void) const;
+  virtual uint16_t GetMtu (void) const = 0;
   /**
    * \return true if link is up; false otherwise
    */
-  bool IsLinkUp (void) const;
+  virtual bool IsLinkUp (void) const = 0;
   /**
    * \param callback the callback to invoke
    *
@@ -117,12 +118,12 @@
    * by the IP/ARP layer to flush the ARP cache 
    * whenever the link goes up.
    */
-  void SetLinkChangeCallback (Callback<void> callback);
+  virtual void SetLinkChangeCallback (Callback<void> callback) = 0;
   /**
    * \return true if this interface supports a broadcast address,
    *         false otherwise.
    */
-  bool IsBroadcast (void) const;
+  virtual bool IsBroadcast (void) const = 0;
   /**
    * \return the broadcast address supported by
    *         this netdevice.
@@ -130,12 +131,12 @@
    * Calling this method is invalid if IsBroadcast returns
    * not true.
    */
-  Address const &GetBroadcast (void) const;
+  virtual Address GetBroadcast (void) const = 0;
 
   /**
    * \return value of m_isMulticast flag
    */
-  bool IsMulticast (void) const;
+  virtual bool IsMulticast (void) const = 0;
 
   /**
    * \brief Return the MAC multicast base address used when mapping multicast
@@ -160,8 +161,8 @@
    * The method NS_ASSERTs if the device is not a multicast device.
    * \see NetDevice::MakeMulticastAddress
    */
-  Address GetMulticast (void) const;
-
+  virtual Address GetMulticast (void) const = 0;
+  
   /**
    * \brief Make and return a MAC multicast address using the provided
    *        multicast group
@@ -192,12 +193,12 @@
    * \see Address
    * \see NetDevice::IsMulticast
    */
-  virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
-
+  virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const = 0;
+  
   /**
    * \return value of m_isPointToPoint flag
    */
-  bool IsPointToPoint (void) const;
+  virtual bool IsPointToPoint (void) const = 0;
   /**
    * \param packet packet sent from above down to Network Device
    * \param dest mac address of the destination (already resolved)
@@ -210,7 +211,7 @@
    * 
    * \return whether the Send operation succeeded 
    */
-  bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+  virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber) = 0;
   /**
    * \returns the node base class which contains this network
    *          interface.
@@ -219,7 +220,7 @@
    * base class to print the nodeid for example, it can invoke
    * this method.
    */
-  Ptr<Node> GetNode (void) const;
+  virtual Ptr<Node> GetNode (void) const = 0;
 
   /**
    * \returns true if ARP is needed, false otherwise.
@@ -227,7 +228,7 @@
    * Called by higher-layers to check if this NetDevice requires
    * ARP to be used.
    */
-  bool NeedsArp (void) const;
+  virtual bool NeedsArp (void) const = 0;
 
   /**
    * \param device a pointer to the net device which is calling this callback
@@ -246,116 +247,10 @@
    *        be forwarded to the higher layers.
    *
    */
-  void SetReceiveCallback (ReceiveCallback cb);
-
- protected:
-  /**
-   * \param node base class node pointer of device's node 
-   * \param addr MAC address of this device.
-   */
-  NetDevice(Ptr<Node> node, const Address& addr);
-  /**
-   * Enable broadcast support. This method should be
-   * called by subclasses from their constructor
-   */
-  void EnableBroadcast (Address broadcast);
-  /**
-   * Set m_isBroadcast flag to false
-   */
-  void DisableBroadcast (void);
-  /**
-   * Enable multicast support. This method should be
-   * called by subclasses from their constructor
-   */
-  void EnableMulticast (Address multicast);
-  /**
-   * Set m_isMulticast flag to false
-   */
-  void DisableMulticast (void);
-  /**
-   * Set m_isPointToPoint flag to true
-   */
-  void EnablePointToPoint (void);
-  /**
-   * Set m_isPointToPoint flag to false
-   */
-  void DisablePointToPoint (void);
-  /**
-   * When a subclass notices that the link status has changed to up,
-   * it notifies its parent class by calling this method. This method
-   * is responsible for notifying any LinkUp callbacks. 
-   */
-  void NotifyLinkUp (void);
-  /**
-   * When a subclass notices that the link status has changed to 
-   * down, it notifies its parent class by calling this method.
-   */
-  void NotifyLinkDown (void);
+  virtual void SetReceiveCallback (ReceiveCallback cb) = 0;
 
-  /**
-   * \param p packet sent from below up to Network Device
-   * \param param Extra parameter extracted from header and needed by
-   * some protocols
-   * \param address the address of the sender of this packet.
-   * \returns true if the packet was forwarded successfully,
-   *          false otherwise.
-   *
-   * When a subclass gets a packet from the channel, it 
-   * forwards it to the higher layers by calling this method
-   * which is responsible for passing it up to the Rx callback.
-   */
-  bool ForwardUp (Ptr<Packet> p, uint16_t param, const Address &address);
-
-
-  /**
-   * The dispose method for this NetDevice class.
-   * Subclasses are expected to override this method _and_
-   * to chain up to it by calling NetDevice::DoDispose
-   * at the end of their own DoDispose method.
-   */
-  virtual void DoDispose (void);
-
- private:
-  /**
-   * \param p packet to send
-   * \param dest address of destination to which packet must be sent
-   * \param protocolNumber Number of the protocol (used with some protocols)
-   * \returns true if the packet could be sent successfully, false
-   *          otherwise.
-   *
-   * This is the private virtual target function of the public Send()
-   * method.  When the link is Up, this method is invoked to ask 
-   * subclasses to forward packets. Subclasses MUST override this method.
-   */
-  virtual bool SendTo (Ptr<Packet> p, const Address &dest, uint16_t protocolNumber) = 0;
-  /**
-   * \returns true if this NetDevice needs the higher-layers
-   *          to perform ARP over it, false otherwise.
-   *
-   * Subclasses must implement this method.
-   */
-  virtual bool DoNeedsArp (void) const = 0;
-  /**
-   * \returns the channel associated to this NetDevice.
-   *
-   * Subclasses must implement this method.
-   */
-  virtual Ptr<Channel> DoGetChannel (void) const = 0;
-
-  Ptr<Node>     m_node;
-  std::string   m_name;
-  uint16_t      m_ifIndex;
-  Address       m_address;
-  Address       m_broadcast;
-  Address       m_multicast;
-  uint16_t      m_mtu;
-  bool          m_isUp;
-  bool          m_isBroadcast;
-  bool          m_isMulticast;
-  bool          m_isPointToPoint;
-  Callback<void> m_linkChangeCallback;
-  ReceiveCallback m_receiveCallback;
 };
 
-}; // namespace ns3
-#endif
+} // namespace ns3
+
+#endif /* NET_DEVICE_H */
--- a/tutorial/point-to-point-ipv4-topology.cc	Sun Feb 24 20:18:02 2008 +0100
+++ b/tutorial/point-to-point-ipv4-topology.cc	Mon Feb 25 19:33:46 2008 +0100
@@ -43,8 +43,8 @@
 {
   NS_ASSERT (channel->GetNDevices () <= 1);
 
-  Ptr<PointToPointNetDevice> nd = CreateObject<PointToPointNetDevice> (node);
-
+  Ptr<PointToPointNetDevice> nd = CreateObject<PointToPointNetDevice> (node, Mac48Address::Allocate ());
+  node->AddDevice (nd);
   Ptr<Queue> q = Queue::CreateDefault ();
   nd->AddQueue(q);
   nd->Attach (channel);
--- a/utils/print-introspected-doxygen.cc	Sun Feb 24 20:18:02 2008 +0100
+++ b/utils/print-introspected-doxygen.cc	Mon Feb 25 19:33:46 2008 +0100
@@ -119,9 +119,12 @@
   Ptr<Node> node = CreateObject<InternetNode> ();
   node->AggregateObject (CreateObject<MobilityModelNotifier> ());
 
-  Ptr<PointToPointNetDevice> p2p = CreateObject<PointToPointNetDevice> (node);
+  Ptr<PointToPointNetDevice> p2p = CreateObject<PointToPointNetDevice> (node, Mac48Address::Allocate ());
+  node->AddDevice (p2p);
   p2p->AddQueue (Queue::CreateDefault ());
-  Ptr<CsmaNetDevice> csma = CreateObject<CsmaNetDevice> (node);
+  Ptr<CsmaNetDevice> csma = CreateObject<CsmaNetDevice> (node, Mac48Address::Allocate (),
+							 CsmaNetDevice::LLC);
+  node->AddDevice (csma);
   csma->AddQueue (Queue::CreateDefault ());
 
   TraceResolver::SourceCollection collection;