back out unfinished p2p changes
authorTom Henderson <tomh@tomh.org>
Fri, 15 Jun 2007 13:19:57 -0700
changeset 773 18ad0b94e2ae
parent 767 c36570ed4f5e
child 774 d8b27eb4efc5
back out unfinished p2p changes
src/devices/p2p/p2p-channel.cc
src/devices/p2p/p2p-net-device.cc
src/devices/p2p/p2p-net-device.h
src/node/mac-address.cc
src/node/mac-address.h
--- a/src/devices/p2p/p2p-channel.cc	Thu Jun 14 10:41:47 2007 +0200
+++ b/src/devices/p2p/p2p-channel.cc	Fri Jun 15 13:19:57 2007 -0700
@@ -135,14 +135,12 @@
 // The sender is going to free the packet as soon as it has been transmitted.
 // We need to copy it to get a reference so it won't e deleted.
 //
-// Above is not correct (GFR).  The event scheduler makes a copy
-// of the packet
-//  Packet packet = p;
+  Packet packet = p;
   NS_DEBUG ("PointToPointChannel::TransmitEnd (): Schedule event in " << 
             m_delay.GetSeconds () << "sec");
   Simulator::Schedule (m_delay,
                        &PointToPointChannel::PropagationCompleteEvent,
-                       this, p, src);
+                       this, packet, src);
   return true;
 }
 
--- a/src/devices/p2p/p2p-net-device.cc	Thu Jun 14 10:41:47 2007 +0200
+++ b/src/devices/p2p/p2p-net-device.cc	Fri Jun 15 13:19:57 2007 -0700
@@ -16,8 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Author:  Craig Dowell <craigdo@ee.washington.edu>
- * Revised: George Riley <riley@ece.gatech.edu>
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 
 #include <iostream>
@@ -33,17 +32,11 @@
 
 namespace ns3 {
 
-DataRateDefaultValue PointToPointNetDevice::g_defaultRate(
-           "PointToPointLinkDataRate", 
-           "The default data rate for point to point links",
-           DataRate ("10Mb/s"));
-
-  PointToPointNetDevice::PointToPointNetDevice (Ptr<Node> node,
-                                                const DataRate& rate) 
+PointToPointNetDevice::PointToPointNetDevice (Ptr<Node> node) 
 : 
-  NetDevice(node, MacAddress (6)), 
+  NetDevice(node, MacAddress ("00:00:00:00:00:00")), 
   m_txMachineState (READY),
-  m_bps (rate),
+  m_bps (DataRate (0xffffffff)),
   m_tInterframeGap (Seconds(0)),
   m_channel (0), 
   m_queue (0),
@@ -108,25 +101,26 @@
 //
 // Assignment operator for PointToPointNetDevice.
 //
+// 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.
 //
-PointToPointNetDevice&
-PointToPointNetDevice::operator= (const PointToPointNetDevice& nd)
+  PointToPointNetDevice&
+PointToPointNetDevice::operator= (const PointToPointNetDevice nd)
 {
   NS_DEBUG ("PointToPointNetDevice::operator= (" << &nd << ")");
-  // FIXME.  Not sure what to do here
-  // GFR Note.  I would suggest dis-allowing netdevice assignment,
-  // as well as pass-by-value (ie. copy constructor).
   return *this;
 }
 
   void 
-PointToPointNetDevice::SetDataRate(const DataRate& bps)
+PointToPointNetDevice::SetDataRate(DataRate bps)
 {
   m_bps = bps;
 }
 
   void 
-PointToPointNetDevice::SetInterframeGap(const Time& t)
+PointToPointNetDevice::SetInterframeGap(Time t)
 {
   m_tInterframeGap = t;
 }
@@ -139,23 +133,68 @@
 
   NS_ASSERT (IsLinkUp ());
 
+#ifdef NOTYET
+    struct NetDevicePacketDestAddress tag;
+    tag.address = address;
+    p.AddTag (tag);
+#endif
+
 //
 // 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.  This is
 // not a requirement for a point-to-point link, but it's a typical model for
 // the device.  
 //
+// Generally, a real device will have a list of pending packets to transmit.  
+// An on-device CPU frees the main CPU(s) of the details of what is happening
+// in the device and feeds the USART.  The main CPU basically just sees the 
+// list of packets -- it puts packets into the list, and the device frees the
+// packets when they are transmitted.
 //
-// If there's a transmission in progress, we enque the packet for later
-// trnsmission; otherwise we send it now.
+// In the case of our virtual device here, the queue pointed to by m_queue
+// corresponds to this list.  The main CPU adds packets to the list by 
+// calling this method and when the device completes a send, the packets are
+// freed in an "interrupt" service routine.
+//
+// We're going to do the same thing here.  So first of all, the incoming packet
+// goes onto our queue if possible.  If the queue can't handle it, there's
+// nothing to be done.
+//
+    if (m_queue->Enqueue(p) == false )
+      {
+        return false;
+      }
+//
+// If there's a transmission in progress, the "interrupt" will keep the
+// transmission process going.  If the device is idle, we need to start a
+// transmission.
+//
+// In the real world, the USART runs until it finishes sending bits, and then
+// pulls on the device's transmit complete interrupt wire.  At the same time,
+// the electrons from the last wiggle of the wire are busy propagating down
+// the wire.  In the case of a long speed-of-light delay in the wire, we could
+// conceivably start transmitting the next packet before the end of the 
+// previously sent data has even reached the end of the wire.  This situation
+// is usually avoided (like the plague) and an "interframe gap" is introduced.
+// This is usually the round-trip delay on the channel plus some hard-to-
+// quantify receiver turn-around time (the time required for the receiver
+// to process the last frame and prepare for reception of the next).
+//
+// So, if the transmit machine is ready, we need to schedule a transmit 
+// complete event (at which time we tell the channel we're no longer sending
+// bits).  A separate transmit ready event (at which time the transmitter 
+// becomes ready to start sending bits again is scheduled there).  Finally, 
+// we tell the channel (via TransmitStart ()) that we've started wiggling the 
+// wire and bits are coming out.
+//
+// If the transmit machine is not ready, we just leave and the transmit ready
+// event we know is coming will kick-start the transmit process.
+//
     if (m_txMachineState == READY) 
       {
         return TransmitStart (p);
       }
-    else
-      {
-        return m_queue->Enqueue(p);
-      }
+    return true;
 }
 
   bool
@@ -167,25 +206,25 @@
 //
 // This function is called to start the process of transmitting a packet.
 // We need to tell the channel that we've started wiggling the wire and
-// schedule an event that will be executed when the transmission is complete.
+// schedule an event that will be executed when it's time to tell the 
+// channel that we're done wiggling the wire.
 //
   NS_ASSERT_MSG(m_txMachineState == READY, "Must be READY to transmit");
   m_txMachineState = BUSY;
-  Time txCompleteTime = Seconds (m_bps.CalculateTxTime(p.GetSize())) + 
-    m_tInterframeGap;
+  Time tEvent = Seconds (m_bps.CalculateTxTime(p.GetSize()));
 
   NS_DEBUG ("PointToPointNetDevice::TransmitStart (): " <<
     "Schedule TransmitCompleteEvent in " << 
-    txCompleteTime.GetSeconds () << "sec");
-  // Schedule the tx complete event
-  Simulator::Schedule (txCompleteTime, 
-                       &PointToPointNetDevice::TransmitComplete, 
+    tEvent.GetSeconds () << "sec");
+
+  Simulator::Schedule (tEvent, 
+                       &PointToPointNetDevice::TransmitCompleteEvent, 
                        this);
-  return m_channel->TransmitStart(p, this); 
+  return m_channel->TransmitStart (p, this); 
 }
 
   void
-PointToPointNetDevice::TransmitComplete (void)
+PointToPointNetDevice::TransmitCompleteEvent (void)
 {
   NS_DEBUG ("PointToPointNetDevice::TransmitCompleteEvent ()");
 //
@@ -195,10 +234,49 @@
 // the transmitter after the interframe gap.
 //
   NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting");
-  m_txMachineState = READY;
+  m_txMachineState = GAP;
   Packet p;
-  if (!m_queue->Dequeue(p)) return; // Nothing to do at this point
-  TransmitStart(p);
+  bool found;
+  found = m_queue->Dequeue (p);
+  NS_ASSERT_MSG(found, "Packet must be on queue if transmitted");
+  NS_DEBUG ("PointToPointNetDevice::TransmitCompleteEvent (): Pkt UID is " << 
+            p.GetUid () << ")");
+  m_channel->TransmitEnd (p, this); 
+
+  NS_DEBUG (
+    "PointToPointNetDevice::TransmitCompleteEvent (): " <<
+    "Schedule TransmitReadyEvent in "
+    << m_tInterframeGap.GetSeconds () << "sec");
+
+  Simulator::Schedule (m_tInterframeGap, 
+                       &PointToPointNetDevice::TransmitReadyEvent, 
+                       this);
+}
+
+  void
+PointToPointNetDevice::TransmitReadyEvent (void)
+{
+  NS_DEBUG ("PointToPointNetDevice::TransmitReadyEvent ()");
+//
+// This function is called to enable the transmitter after the interframe
+// gap has passed.  If there are pending transmissions, we use this opportunity
+// to start the next transmit.
+//
+  NS_ASSERT_MSG(m_txMachineState == GAP, "Must be in interframe gap");
+  m_txMachineState = READY;
+
+  if (m_queue->IsEmpty())
+    {
+      return;
+    }
+  else
+    {
+      Packet p;
+      bool found;
+      found = m_queue->Peek (p);
+      NS_ASSERT_MSG(found, "IsEmpty false but no Packet on queue?");
+      TransmitStart (p);
+    }
 }
 
 TraceResolver *
--- a/src/devices/p2p/p2p-net-device.h	Thu Jun 14 10:41:47 2007 +0200
+++ b/src/devices/p2p/p2p-net-device.h	Fri Jun 15 13:19:57 2007 -0700
@@ -30,7 +30,6 @@
 #include "ns3/callback-trace-source.h"
 #include "ns3/nstime.h"
 #include "ns3/data-rate.h"
-#include "ns3/default-value.h"
 #include "ns3/ptr.h"
 
 namespace ns3 {
@@ -81,8 +80,7 @@
    * @see PointToPointTopology::AddPointToPointLink ()
    * @param node the Node to which this device is connected.
    */
-  PointToPointNetDevice (Ptr<Node> node,
-                         const DataRate& = g_defaultRate.GetValue());
+  PointToPointNetDevice (Ptr<Node> node);
   /**
    * Copy Construct a PointToPointNetDevice
    *
@@ -107,7 +105,7 @@
    *
    * @param nd the object to be copied
    */
-  PointToPointNetDevice& operator= (const PointToPointNetDevice& nd);
+  PointToPointNetDevice& operator= (PointToPointNetDevice nd);
   /**
    * Set the Data Rate used for transmission of packets.  The data rate is
    * set in the Attach () method from the corresponding field in the channel
@@ -116,7 +114,7 @@
    * @see Attach ()
    * @param bps the data rate at which this object operates
    */
-  void SetDataRate(const DataRate& bps);
+  void SetDataRate(DataRate bps);
   /**
    * Set the inteframe gap used to separate packets.  The interframe gap
    * defines the minimum space required between packets sent by this device.
@@ -127,7 +125,7 @@
    * @see Attach ()
    * @param t the interframe gap time
    */
-  void SetInterframeGap(const Time& t);
+  void SetInterframeGap(Time t);
   /**
    * Attach the device to a channel.
    *
@@ -192,19 +190,6 @@
    * @returns a pointer to the channel
    */
   virtual Ptr<Channel> DoGetChannel(void) const;
-  /**
-   * Set a new default data rate
-   * @param Data rate to set for new default
-   */
-  static void SetDefaultRate(const DataRate&);
-
-  /** 
-   * Get the current default rate.
-   * @returns a const reference to current default
-   */
-
-  static const DataRate& GetDefaultRate();
-
 private:
   /**
    * Send a Packet Down the Wire.
@@ -238,11 +223,33 @@
   /**
    * Stop Sending a Packet Down the Wire and Begin the Interframe Gap.
    *
-   * The TransmitComplete method is used internally to finish the process
-   * of sending a packet out on the channel.
+   * The TransmitCompleteEvent method is used internally to finish the process
+   * of sending a packet out on the channel.  During execution of this method
+   * the TransmitEnd method is called on the channel to let it know that the
+   * physical device this class represents has virually finished sending 
+   * signals.  The channel uses this event to begin its speed of light delay
+   * timer after which it notifies the Net Device at the other end of the 
+   * link that the bits have arrived.  During this method, the net device 
+   * also schedules the TransmitReadyEvent at which time the transmitter 
+   * becomes ready to send the next packet.
    *
+   * @see PointToPointChannel::TransmitEnd ()
+   * @see TransmitReadyEvent ()
+   * @returns true if success, false on failure
    */
-  void TransmitComplete(void);
+  void TransmitCompleteEvent (void);
+  /**
+   * Cause the Transmitter to Become Ready to Send Another Packet.
+   *
+   * The TransmitReadyEvent method is used internally to re-enable the 
+   * transmit machine of the net device.  It is scheduled after a suitable
+   * interframe gap after the completion of the previous transmission.
+   * The queue is checked at this time, and if there is a packet waiting on
+   * the queue, the transmission process is begun.
+   *
+   * @see TransmitStart ()
+   */
+  void TransmitReadyEvent (void);
   /**
    * Create a Trace Resolver for events in the net device.
    *
@@ -256,7 +263,8 @@
   enum TxMachineState
     {
       READY, /**< The transmitter is ready to begin transmission of a packet */
-      BUSY   /**< The transmitter is busy transmitting a packet */
+      BUSY,  /**< The transmitter is busy transmitting a packet */
+      GAP    /**< The transmitter is in the interframe gap time */
     };
   /**
    * The state of the Net Device transmit state machine.
@@ -297,11 +305,6 @@
    * @see class TraceResolver
    */
   CallbackTraceSource<Packet &> m_rxTrace;
-  /** 
-   * Default data rate.  Used for all newly created p2p net devices
-   */
-   static DataRateDefaultValue g_defaultRate;
-
 };
 
 }; // namespace ns3
--- a/src/node/mac-address.cc	Thu Jun 14 10:41:47 2007 +0200
+++ b/src/node/mac-address.cc	Fri Jun 15 13:19:57 2007 -0700
@@ -33,9 +33,6 @@
 
 namespace ns3 {
 
-// Static variables
-uint8_t MacAddress::g_nextAddress[MacAddress::MAX_LEN];
-
 static char
 AsciiToLowCase (char c)
 {
@@ -57,13 +54,6 @@
     }
 }
 
-MacAddress::MacAddress(uint8_t len) : m_len(len)
-{
-  NS_ASSERT (len <= MacAddress::MAX_LEN);
-  AdvanceAddress();
-  memcpy(m_address, g_nextAddress, len);
-}
-
 MacAddress::MacAddress (uint8_t const *address, uint8_t len)
 {
   NS_ASSERT (len <= MacAddress::MAX_LEN);
@@ -158,17 +148,6 @@
         m_len = len;
 }
 
-// Static methods
-void MacAddress::AdvanceAddress()
-  {
-    // Advance to next address, little end first
-    for(size_t i = 0; i < MAX_LEN; ++i)
-      {
-        if (++g_nextAddress[i] != 0) break;
-      }
-  }
-
-// Non-member operators
 bool operator == (MacAddress const&a, MacAddress const&b)
 {
 	return a.IsEqual (b);
--- a/src/node/mac-address.h	Thu Jun 14 10:41:47 2007 +0200
+++ b/src/node/mac-address.h	Fri Jun 15 13:19:57 2007 -0700
@@ -47,13 +47,6 @@
    */
   MacAddress (void);
   /**
-   * \brief Construct a MacAddress using the next available
-   * address.
-   * \see MacAddres::Next
-   * \param len length, in bytes, of the desired address
-   */
-  MacAddress(uint8_t len);
-  /**
    * \brief Construct a MacAddress from a byte-array
    *
    * low byte should be first.
@@ -104,14 +97,6 @@
    */
   void Set (uint8_t const ad[MAX_LEN], uint8_t len);
 
-  // Static methods/members
-  /**
-   *
-   * Advance the global to the next available mac address.
-   */
-  static void AdvanceAddress();
-  static uint8_t g_nextAddress[MAX_LEN];
-
 private:
   uint8_t m_address[MAX_LEN];
   uint8_t m_len;