Simplification to p2p-net-device and p2p-channel (work in progress)
This commit is contained in:
@@ -135,12 +135,14 @@ PointToPointChannel::TransmitEnd(Packet& p, Ptr<PointToPointNetDevice> src)
|
||||
// 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.
|
||||
//
|
||||
Packet packet = p;
|
||||
// Above is not correct (GFR). The event scheduler makes a copy
|
||||
// of the packet
|
||||
// Packet packet = p;
|
||||
NS_DEBUG ("PointToPointChannel::TransmitEnd (): Schedule event in " <<
|
||||
m_delay.GetSeconds () << "sec");
|
||||
Simulator::Schedule (m_delay,
|
||||
&PointToPointChannel::PropagationCompleteEvent,
|
||||
this, packet, src);
|
||||
this, p, src);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
* 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>
|
||||
* Author: Craig Dowell <craigdo@ee.washington.edu>
|
||||
* Revised: George Riley <riley@ece.gatech.edu>
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
@@ -32,11 +33,17 @@ NS_DEBUG_COMPONENT_DEFINE ("PointToPointNetDevice");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
PointToPointNetDevice::PointToPointNetDevice (Ptr<Node> node)
|
||||
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)
|
||||
:
|
||||
NetDevice(node, MacAddress ("00:00:00:00:00:00")),
|
||||
NetDevice(node, MacAddress (6)),
|
||||
m_txMachineState (READY),
|
||||
m_bps (DataRate (0xffffffff)),
|
||||
m_bps (rate),
|
||||
m_tInterframeGap (Seconds(0)),
|
||||
m_channel (0),
|
||||
m_queue (0),
|
||||
@@ -101,26 +108,25 @@ void PointToPointNetDevice::DoDispose()
|
||||
//
|
||||
// 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(DataRate bps)
|
||||
PointToPointNetDevice::SetDataRate(const DataRate& bps)
|
||||
{
|
||||
m_bps = bps;
|
||||
}
|
||||
|
||||
void
|
||||
PointToPointNetDevice::SetInterframeGap(Time t)
|
||||
PointToPointNetDevice::SetInterframeGap(const Time& t)
|
||||
{
|
||||
m_tInterframeGap = t;
|
||||
}
|
||||
@@ -133,68 +139,23 @@ PointToPointNetDevice::SendTo (Packet& p, const MacAddress& dest)
|
||||
|
||||
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.
|
||||
//
|
||||
// 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 there's a transmission in progress, we enque the packet for later
|
||||
// trnsmission; otherwise we send it now.
|
||||
if (m_txMachineState == READY)
|
||||
{
|
||||
return TransmitStart (p);
|
||||
}
|
||||
return true;
|
||||
else
|
||||
{
|
||||
return m_queue->Enqueue(p);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -206,25 +167,25 @@ PointToPointNetDevice::TransmitStart (Packet &p)
|
||||
//
|
||||
// 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 it's time to tell the
|
||||
// channel that we're done wiggling the wire.
|
||||
// schedule an event that will be executed when the transmission is complete.
|
||||
//
|
||||
NS_ASSERT_MSG(m_txMachineState == READY, "Must be READY to transmit");
|
||||
m_txMachineState = BUSY;
|
||||
Time tEvent = Seconds (m_bps.CalculateTxTime(p.GetSize()));
|
||||
Time txCompleteTime = Seconds (m_bps.CalculateTxTime(p.GetSize())) +
|
||||
m_tInterframeGap;
|
||||
|
||||
NS_DEBUG ("PointToPointNetDevice::TransmitStart (): " <<
|
||||
"Schedule TransmitCompleteEvent in " <<
|
||||
tEvent.GetSeconds () << "sec");
|
||||
|
||||
Simulator::Schedule (tEvent,
|
||||
&PointToPointNetDevice::TransmitCompleteEvent,
|
||||
txCompleteTime.GetSeconds () << "sec");
|
||||
// Schedule the tx complete event
|
||||
Simulator::Schedule (txCompleteTime,
|
||||
&PointToPointNetDevice::TransmitComplete,
|
||||
this);
|
||||
return m_channel->TransmitStart (p, this);
|
||||
return m_channel->TransmitStart(p, this);
|
||||
}
|
||||
|
||||
void
|
||||
PointToPointNetDevice::TransmitCompleteEvent (void)
|
||||
PointToPointNetDevice::TransmitComplete (void)
|
||||
{
|
||||
NS_DEBUG ("PointToPointNetDevice::TransmitCompleteEvent ()");
|
||||
//
|
||||
@@ -234,49 +195,10 @@ PointToPointNetDevice::TransmitCompleteEvent (void)
|
||||
// the transmitter after the interframe gap.
|
||||
//
|
||||
NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting");
|
||||
m_txMachineState = GAP;
|
||||
Packet 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);
|
||||
}
|
||||
Packet p;
|
||||
if (!m_queue->Dequeue(p)) return; // Nothing to do at this point
|
||||
TransmitStart(p);
|
||||
}
|
||||
|
||||
TraceResolver *
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#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 {
|
||||
@@ -80,7 +81,8 @@ public:
|
||||
* @see PointToPointTopology::AddPointToPointLink ()
|
||||
* @param node the Node to which this device is connected.
|
||||
*/
|
||||
PointToPointNetDevice (Ptr<Node> node);
|
||||
PointToPointNetDevice (Ptr<Node> node,
|
||||
const DataRate& = g_defaultRate.GetValue());
|
||||
/**
|
||||
* Copy Construct a PointToPointNetDevice
|
||||
*
|
||||
@@ -105,7 +107,7 @@ public:
|
||||
*
|
||||
* @param nd the object to be copied
|
||||
*/
|
||||
PointToPointNetDevice& operator= (PointToPointNetDevice nd);
|
||||
PointToPointNetDevice& operator= (const 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
|
||||
@@ -114,7 +116,7 @@ public:
|
||||
* @see Attach ()
|
||||
* @param bps the data rate at which this object operates
|
||||
*/
|
||||
void SetDataRate(DataRate bps);
|
||||
void SetDataRate(const DataRate& bps);
|
||||
/**
|
||||
* Set the inteframe gap used to separate packets. The interframe gap
|
||||
* defines the minimum space required between packets sent by this device.
|
||||
@@ -125,7 +127,7 @@ public:
|
||||
* @see Attach ()
|
||||
* @param t the interframe gap time
|
||||
*/
|
||||
void SetInterframeGap(Time t);
|
||||
void SetInterframeGap(const Time& t);
|
||||
/**
|
||||
* Attach the device to a channel.
|
||||
*
|
||||
@@ -190,6 +192,19 @@ protected:
|
||||
* @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.
|
||||
@@ -223,33 +238,11 @@ private:
|
||||
/**
|
||||
* Stop Sending a Packet Down the Wire and Begin the Interframe Gap.
|
||||
*
|
||||
* 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.
|
||||
* The TransmitComplete method is used internally to finish the process
|
||||
* of sending a packet out on the channel.
|
||||
*
|
||||
* @see PointToPointChannel::TransmitEnd ()
|
||||
* @see TransmitReadyEvent ()
|
||||
* @returns true if success, false on failure
|
||||
*/
|
||||
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);
|
||||
void TransmitComplete(void);
|
||||
/**
|
||||
* Create a Trace Resolver for events in the net device.
|
||||
*
|
||||
@@ -263,8 +256,7 @@ private:
|
||||
enum TxMachineState
|
||||
{
|
||||
READY, /**< The transmitter is ready to begin transmission of a packet */
|
||||
BUSY, /**< The transmitter is busy transmitting a packet */
|
||||
GAP /**< The transmitter is in the interframe gap time */
|
||||
BUSY /**< The transmitter is busy transmitting a packet */
|
||||
};
|
||||
/**
|
||||
* The state of the Net Device transmit state machine.
|
||||
@@ -305,6 +297,11 @@ private:
|
||||
* @see class TraceResolver
|
||||
*/
|
||||
CallbackTraceSource<Packet &> m_rxTrace;
|
||||
/**
|
||||
* Default data rate. Used for all newly created p2p net devices
|
||||
*/
|
||||
static DataRateDefaultValue g_defaultRate;
|
||||
|
||||
};
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
// Static variables
|
||||
uint8_t MacAddress::g_nextAddress[MacAddress::MAX_LEN];
|
||||
|
||||
static char
|
||||
AsciiToLowCase (char c)
|
||||
{
|
||||
@@ -54,6 +57,13 @@ MacAddress::MacAddress () : m_len(0)
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -148,6 +158,17 @@ MacAddress::Set (uint8_t const ad[MacAddress::MAX_LEN], uint8_t len)
|
||||
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);
|
||||
|
||||
@@ -46,6 +46,13 @@ public:
|
||||
* This MacAddress has length of zero, and is internally all zeros
|
||||
*/
|
||||
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
|
||||
*
|
||||
@@ -97,6 +104,14 @@ public:
|
||||
*/
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user