Testing
This commit is contained in:
@@ -12,39 +12,55 @@ Gustavo Carneiro (gjcarneiro@gmail.com) is the maintainer.
|
||||
=== Building with Waf ===
|
||||
|
||||
To build ns-3 with waf type the commands:
|
||||
1. ./waf configure [options]
|
||||
2. ./waf
|
||||
1. waf configure [options]
|
||||
2. waf
|
||||
|
||||
[ Note: if ./waf does not exist, see the section "Note for developers" below ]
|
||||
[ Note: if waf does not exist in your path, see the section
|
||||
"Note for developers" below ]
|
||||
|
||||
To see valid configure options, type ./waf --help. The most important
|
||||
To see valid configure options, type waf --help. The most important
|
||||
option is -d <debug level>. Valid debug levels (which are listed in
|
||||
./waf --help) are: ultradebug, debug, release, and optimized.
|
||||
waf --help) are: ultradebug, debug, release, and optimized. It is
|
||||
also possible to change the flags used for compilation with (e.g.):
|
||||
CXXFLAGS="-O3" waf configure.
|
||||
|
||||
[ Note: Unlike some other build tools, to change the build target,
|
||||
the option must be supplied during the configure stage rather than
|
||||
the build stage (i.e., "waf -d optimized" will not work; instead, do
|
||||
"waf -d optimized configure; waf" ]
|
||||
|
||||
The resulting binaries are placed in build/<debuglevel>/srcpath.
|
||||
|
||||
Other waf usages include:
|
||||
|
||||
1. ./waf check
|
||||
1. waf check
|
||||
Runs the unit tests
|
||||
|
||||
2. ./waf --doxygen
|
||||
2. waf --doxygen
|
||||
Run doxygen to generate documentation
|
||||
|
||||
3. ./waf --lcov-report
|
||||
3. waf --lcov-report
|
||||
Run code coverage analysis (assuming the project was configured
|
||||
with --enable-gcov)
|
||||
|
||||
4. ./waf --run "program [args]"
|
||||
4. waf --run "program [args]"
|
||||
Run a ns3 program, given its target name, with the given
|
||||
arguments. This takes care of automatically modifying the the
|
||||
path for finding the ns3 dynamic libraries in the environment
|
||||
before running the program. Note: the "program [args]" string is
|
||||
parsed using POSIX shell rules.
|
||||
|
||||
5. ./waf --shell
|
||||
5. waf --shell
|
||||
Starts a nested system shell with modified environment to run ns3 programs.
|
||||
|
||||
6. waf distclean
|
||||
Cleans out the entire build/ directory
|
||||
|
||||
7. waf dist
|
||||
The command 'waf dist' can be used to create a distribution tarball.
|
||||
It includes all files in the source directory, except some particular
|
||||
extensions that are blacklisted, such as back files (ending in ~).
|
||||
|
||||
|
||||
=== Extending ns-3 ===
|
||||
|
||||
@@ -90,13 +106,9 @@ developers should check it out from a subversion repository:
|
||||
tested to work correctly with ns3, although 'trunk' will likely work
|
||||
as well ]
|
||||
|
||||
Then it can be installed system-wide with 'sudo ./waf-light install'.
|
||||
Then it can be installed system-wide with 'sudo waf-light install'.
|
||||
When preparing a distribution, the resulting 'waf' script, which is
|
||||
self contained (no external files needed), can be easily included in
|
||||
the tarball so that users downloading ns-3 can easily build it without
|
||||
having Waf installed (although Python >= 2.3 is still needed).
|
||||
|
||||
The command 'waf dist' can be used to create a distribution tarball.
|
||||
It includes all files in the source directory, except some particular
|
||||
extensions that are blacklisted, such as back files (ending in ~).
|
||||
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
|
||||
def configure(conf):
|
||||
conf.env.append_value('NS3_MODULES', 'ns3-applications')
|
||||
|
||||
|
||||
def build(bld):
|
||||
obj = bld.create_obj('cpp', 'shlib')
|
||||
obj.name = 'ns3-applications'
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def configure(conf):
|
||||
conf.env.append_value('NS3_MODULES', 'ns3-common')
|
||||
|
||||
def build(bld):
|
||||
common = bld.create_obj('cpp', 'shlib')
|
||||
common.name = 'ns3-common'
|
||||
|
||||
@@ -130,8 +130,8 @@ private:
|
||||
if (!(assertion)) \
|
||||
{ \
|
||||
Failure () << __FILE__ << ":" <<__LINE__ \
|
||||
<< ": assertion `" << (assertion) \
|
||||
<< "'failed." << std::endl; \
|
||||
<< ": assertion `" << #assertion \
|
||||
<< "' failed." << std::endl; \
|
||||
result = false; \
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@ import sys
|
||||
|
||||
|
||||
def configure(conf):
|
||||
conf.env.append_value('NS3_MODULES', 'ns3-core')
|
||||
|
||||
e = conf.create_header_configurator()
|
||||
e.mandatory = False
|
||||
e.name = 'stdlib.h'
|
||||
|
||||
@@ -76,8 +76,7 @@ PointToPointChannel::Attach(Ptr<PointToPointNetDevice> device)
|
||||
NS_ASSERT(m_nDevices < N_DEVICES && "Only two devices permitted");
|
||||
NS_ASSERT(device != 0);
|
||||
|
||||
m_link[m_nDevices].m_src = device;
|
||||
++m_nDevices;
|
||||
m_link[m_nDevices++].m_src = device;
|
||||
//
|
||||
// If we have both devices connected to the channel, then finish introducing
|
||||
// the two halves and set the links to IDLE.
|
||||
@@ -91,8 +90,9 @@ PointToPointChannel::Attach(Ptr<PointToPointNetDevice> device)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PointToPointChannel::TransmitStart(Packet& p, Ptr<PointToPointNetDevice> src)
|
||||
bool PointToPointChannel::TransmitStart(Packet& p,
|
||||
Ptr<PointToPointNetDevice> src,
|
||||
const Time& txTime)
|
||||
{
|
||||
NS_DEBUG ("PointToPointChannel::TransmitStart (" << &p << ", " << src <<
|
||||
")");
|
||||
@@ -104,65 +104,15 @@ PointToPointChannel::TransmitStart(Packet& p, Ptr<PointToPointNetDevice> src)
|
||||
|
||||
uint32_t wire = src == m_link[0].m_src ? 0 : 1;
|
||||
|
||||
if (m_link[wire].m_state == TRANSMITTING)
|
||||
{
|
||||
NS_DEBUG("PointToPointChannel::TransmitStart (): **** ERROR ****");
|
||||
NS_DEBUG("PointToPointChannel::TransmitStart (): state TRANSMITTING");
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_DEBUG("PointToPointChannel::TransmitStart (): switch to TRANSMITTING");
|
||||
m_link[wire].m_state = TRANSMITTING;
|
||||
// Here we schedule the packet receive event at the receiver,
|
||||
// which simplifies this model quite a bit. The channel just
|
||||
// adds the propagation delay time
|
||||
Simulator::Schedule (txTime + m_delay,
|
||||
&PointToPointNetDevice::Receive,
|
||||
m_link[wire].m_dst, p);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PointToPointChannel::TransmitEnd(Packet& p, Ptr<PointToPointNetDevice> src)
|
||||
{
|
||||
NS_DEBUG("PointToPointChannel::TransmitEnd (" << &p << ", " << src << ")");
|
||||
NS_DEBUG ("PointToPointChannel::TransmitEnd (): UID is " <<
|
||||
p.GetUid () << ")");
|
||||
|
||||
NS_ASSERT(m_link[0].m_state != INITIALIZING);
|
||||
NS_ASSERT(m_link[1].m_state != INITIALIZING);
|
||||
|
||||
uint32_t wire = src == m_link[0].m_src ? 0 : 1;
|
||||
|
||||
NS_ASSERT(m_link[wire].m_state == TRANSMITTING);
|
||||
|
||||
m_link[wire].m_state = PROPAGATING;
|
||||
//
|
||||
// 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;
|
||||
NS_DEBUG ("PointToPointChannel::TransmitEnd (): Schedule event in " <<
|
||||
m_delay.GetSeconds () << "sec");
|
||||
Simulator::Schedule (m_delay,
|
||||
&PointToPointChannel::PropagationCompleteEvent,
|
||||
this, packet, src);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PointToPointChannel::PropagationCompleteEvent(
|
||||
Packet p,
|
||||
Ptr<PointToPointNetDevice> src)
|
||||
{
|
||||
NS_DEBUG("PointToPointChannel::PropagationCompleteEvent (" << &p << ", " <<
|
||||
src << ")");
|
||||
NS_DEBUG ("PointToPointChannel::PropagationCompleteEvent (): UID is " <<
|
||||
p.GetUid () << ")");
|
||||
|
||||
uint32_t wire = src == m_link[0].m_src ? 0 : 1;
|
||||
NS_ASSERT(m_link[wire].m_state == PROPAGATING);
|
||||
m_link[wire].m_state = IDLE;
|
||||
|
||||
NS_DEBUG ("PointToPointChannel::PropagationCompleteEvent (): Receive");
|
||||
m_link[wire].m_dst->Receive (p);
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
PointToPointChannel::GetNDevices (void) const
|
||||
{
|
||||
@@ -176,13 +126,13 @@ PointToPointChannel::GetDevice (uint32_t i) const
|
||||
return m_link[i].m_src;
|
||||
}
|
||||
|
||||
DataRate
|
||||
const DataRate&
|
||||
PointToPointChannel::GetDataRate (void)
|
||||
{
|
||||
return m_bps;
|
||||
}
|
||||
|
||||
Time
|
||||
const Time&
|
||||
PointToPointChannel::GetDelay (void)
|
||||
{
|
||||
return m_delay;
|
||||
|
||||
@@ -51,11 +51,7 @@ class PointToPointNetDevice;
|
||||
*/
|
||||
class PointToPointChannel : public Channel {
|
||||
public:
|
||||
//
|
||||
// This is really kidding myself, since just setting N_DEVICES to 3 isn't
|
||||
// going to come close to magically creating a multi-drop link, but I can't
|
||||
// bring myself to just type 2 in the code (even though I type 0 and 1 :-).
|
||||
//
|
||||
// Each point to point link has exactly two net devices
|
||||
static const int N_DEVICES = 2;
|
||||
/**
|
||||
* \brief Create a PointToPointChannel
|
||||
@@ -68,7 +64,7 @@ public:
|
||||
/**
|
||||
* \brief Create a PointToPointChannel
|
||||
*
|
||||
* \param bps The bitrate of the channel
|
||||
* \param bps The maximum bitrate of the channel
|
||||
* \param delay Transmission delay through the channel
|
||||
*/
|
||||
PointToPointChannel (const DataRate& bps, const Time& delay);
|
||||
@@ -77,7 +73,7 @@ public:
|
||||
* \brief Create a PointToPointChannel
|
||||
*
|
||||
* \param name the name of the channel for identification purposes
|
||||
* \param bps The bitrate of the channel
|
||||
* \param bps The maximum bitrate of the channel
|
||||
* \param delay Transmission delay through the channel
|
||||
*/
|
||||
PointToPointChannel (const std::string& name,
|
||||
@@ -88,21 +84,22 @@ public:
|
||||
* \param device pointer to the netdevice to attach to the channel
|
||||
*/
|
||||
void Attach (Ptr<PointToPointNetDevice> device);
|
||||
bool TransmitStart (Packet& p, Ptr<PointToPointNetDevice> src);
|
||||
bool TransmitEnd (Packet &p, Ptr<PointToPointNetDevice> src);
|
||||
void PropagationCompleteEvent(Packet p, Ptr<PointToPointNetDevice> src);
|
||||
bool TransmitStart (Packet& p, Ptr<PointToPointNetDevice> src,
|
||||
const Time& txTime);
|
||||
// Below two not needed
|
||||
//bool TransmitEnd (Packet &p, Ptr<PointToPointNetDevice> src);
|
||||
//void PropagationCompleteEvent(Packet p, Ptr<PointToPointNetDevice> src);
|
||||
|
||||
|
||||
virtual uint32_t GetNDevices (void) const;
|
||||
virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
|
||||
|
||||
virtual DataRate GetDataRate (void);
|
||||
virtual Time GetDelay (void);
|
||||
virtual const DataRate& GetDataRate (void);
|
||||
virtual const Time& GetDelay (void);
|
||||
|
||||
private:
|
||||
DataRate m_bps;
|
||||
Time m_delay;
|
||||
|
||||
int32_t m_nDevices;
|
||||
|
||||
enum WireState
|
||||
|
||||
@@ -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),
|
||||
@@ -73,6 +80,9 @@ PointToPointNetDevice::~PointToPointNetDevice()
|
||||
// We're assuming that the tracing will be set up after the topology creation
|
||||
// phase and this won't actually matter.
|
||||
//
|
||||
// GFR Comments. Don't see where the "copy the pointer and add reference"
|
||||
// stated above is done. Can original author please comment and/or fix.
|
||||
// Shouldn't the queue pointer also bump the refcount?
|
||||
PointToPointNetDevice::PointToPointNetDevice (const PointToPointNetDevice& nd)
|
||||
:
|
||||
NetDevice(nd),
|
||||
@@ -92,6 +102,8 @@ PointToPointNetDevice::PointToPointNetDevice (const PointToPointNetDevice& nd)
|
||||
|
||||
}
|
||||
|
||||
// GFR COmments...shouldn't this decrement the refcount instead
|
||||
// of just nil-ing out the pointer? Don't understand this.
|
||||
void PointToPointNetDevice::DoDispose()
|
||||
{
|
||||
m_channel = 0;
|
||||
@@ -101,100 +113,54 @@ 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).
|
||||
// This resolves some of the questions above about copy constructors.
|
||||
// Why should we ever copy or assign a net device?
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
PointToPointNetDevice::SetDataRate(DataRate bps)
|
||||
void PointToPointNetDevice::SetDataRate(const DataRate& bps)
|
||||
{
|
||||
m_bps = bps;
|
||||
}
|
||||
|
||||
void
|
||||
PointToPointNetDevice::SetInterframeGap(Time t)
|
||||
void PointToPointNetDevice::SetInterframeGap(const Time& t)
|
||||
{
|
||||
m_tInterframeGap = t;
|
||||
}
|
||||
|
||||
bool
|
||||
PointToPointNetDevice::SendTo (Packet& p, const MacAddress& dest)
|
||||
bool PointToPointNetDevice::SendTo (Packet& p, const MacAddress& dest)
|
||||
{
|
||||
NS_DEBUG ("PointToPointNetDevice::SendTo (" << &p << ", " << &dest << ")");
|
||||
NS_DEBUG ("PointToPointNetDevice::SendTo (): UID is " << p.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 ());
|
||||
|
||||
#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.
|
||||
// link, this means that we're simulating something like a UART.
|
||||
//
|
||||
// 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,81 +172,41 @@ 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 txTime = Seconds (m_bps.CalculateTxTime(p.GetSize()));
|
||||
Time txCompleteTime = txTime + 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, txTime);
|
||||
}
|
||||
|
||||
void
|
||||
PointToPointNetDevice::TransmitCompleteEvent (void)
|
||||
void PointToPointNetDevice::TransmitComplete (void)
|
||||
{
|
||||
NS_DEBUG ("PointToPointNetDevice::TransmitCompleteEvent ()");
|
||||
//
|
||||
// This function is called to finish the process of transmitting a packet.
|
||||
// We need to tell the channel that we've stopped wiggling the wire and
|
||||
// schedule an event that will be executed when it's time to re-enable
|
||||
// the transmitter after the interframe gap.
|
||||
// get the next packet from the queue. If the queue is empty, we are
|
||||
// done, otherwise transmit the next packet.
|
||||
//
|
||||
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 *
|
||||
PointToPointNetDevice::DoCreateTraceResolver (TraceContext const &context)
|
||||
TraceResolver* PointToPointNetDevice::DoCreateTraceResolver (
|
||||
TraceContext const &context)
|
||||
{
|
||||
CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
|
||||
resolver->Add ("queue",
|
||||
@@ -292,8 +218,7 @@ PointToPointNetDevice::DoCreateTraceResolver (TraceContext const &context)
|
||||
return resolver;
|
||||
}
|
||||
|
||||
bool
|
||||
PointToPointNetDevice::Attach (Ptr<PointToPointChannel> ch)
|
||||
bool PointToPointNetDevice::Attach (Ptr<PointToPointChannel> ch)
|
||||
{
|
||||
NS_DEBUG ("PointToPointNetDevice::Attach (" << &ch << ")");
|
||||
|
||||
@@ -301,7 +226,9 @@ PointToPointNetDevice::Attach (Ptr<PointToPointChannel> ch)
|
||||
|
||||
m_channel->Attach(this);
|
||||
m_bps = m_channel->GetDataRate ();
|
||||
m_tInterframeGap = m_channel->GetDelay ();
|
||||
// GFR Comment. Below is definitely wrong. Interframe gap
|
||||
// is unrelated to channel delay.
|
||||
//m_tInterframeGap = m_channel->GetDelay ();
|
||||
|
||||
/*
|
||||
* For now, this device is up whenever a channel is attached to it.
|
||||
@@ -315,38 +242,32 @@ PointToPointNetDevice::Attach (Ptr<PointToPointChannel> ch)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PointToPointNetDevice::AddQueue (Ptr<Queue> q)
|
||||
void PointToPointNetDevice::AddQueue (Ptr<Queue> q)
|
||||
{
|
||||
NS_DEBUG ("PointToPointNetDevice::AddQueue (" << q << ")");
|
||||
|
||||
m_queue = q;
|
||||
}
|
||||
|
||||
void
|
||||
PointToPointNetDevice::Receive (Packet& p)
|
||||
void PointToPointNetDevice::Receive (Packet& p)
|
||||
{
|
||||
// ignore return value for now.
|
||||
NS_DEBUG ("PointToPointNetDevice::Receive (" << &p << ")");
|
||||
|
||||
m_rxTrace (p);
|
||||
ForwardUp (p);
|
||||
}
|
||||
|
||||
Ptr<Queue>
|
||||
PointToPointNetDevice::GetQueue(void) const
|
||||
Ptr<Queue> PointToPointNetDevice::GetQueue(void) const
|
||||
{
|
||||
return m_queue;
|
||||
}
|
||||
|
||||
Ptr<Channel>
|
||||
PointToPointNetDevice::DoGetChannel(void) const
|
||||
Ptr<Channel> PointToPointNetDevice::DoGetChannel(void) const
|
||||
{
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
bool
|
||||
PointToPointNetDevice::DoNeedsArp (void) const
|
||||
bool PointToPointNetDevice::DoNeedsArp (void) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -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,39 +238,17 @@ 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.
|
||||
*
|
||||
* @see class TraceResolver
|
||||
*/
|
||||
virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
|
||||
virtual TraceResolver* DoCreateTraceResolver (TraceContext const &context);
|
||||
virtual bool DoNeedsArp (void) const;
|
||||
/**
|
||||
* Enumeration of the states of the transmit machine of 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
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
|
||||
def configure(conf):
|
||||
conf.env.append_value('NS3_MODULES', 'ns3-p2p')
|
||||
|
||||
|
||||
def build(bld):
|
||||
p2p = bld.create_obj('cpp', 'shlib')
|
||||
p2p.name = 'ns3-p2p'
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
|
||||
def configure(conf):
|
||||
conf.env.append_value('NS3_MODULES', 'ns3-internet-node')
|
||||
|
||||
|
||||
def build(bld):
|
||||
obj = bld.create_obj('cpp', 'shlib')
|
||||
obj.name = 'ns3-internet-node'
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def configure(conf):
|
||||
conf.env.append_value('NS3_MODULES', 'ns3-node')
|
||||
|
||||
|
||||
def build(bld):
|
||||
node = bld.create_obj('cpp', 'shlib')
|
||||
node.name = 'ns3-node'
|
||||
|
||||
@@ -45,12 +45,12 @@ EventId::Cancel (void)
|
||||
}
|
||||
}
|
||||
bool
|
||||
EventId::IsExpired (void)
|
||||
EventId::IsExpired (void) const
|
||||
{
|
||||
return Simulator::IsExpired (*this);
|
||||
}
|
||||
bool
|
||||
EventId::IsRunning (void)
|
||||
EventId::IsRunning (void) const
|
||||
{
|
||||
return !IsExpired ();
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ public:
|
||||
* method.
|
||||
* \returns true if the event has expired, false otherwise.
|
||||
*/
|
||||
bool IsExpired (void);
|
||||
bool IsRunning (void);
|
||||
bool IsExpired (void) const;
|
||||
bool IsRunning (void) const;
|
||||
public:
|
||||
/* The following methods are semi-private
|
||||
* they are supposed to be invoked only by
|
||||
|
||||
@@ -266,7 +266,7 @@ SimulatorPrivate::Cancel (EventId &id)
|
||||
}
|
||||
|
||||
bool
|
||||
SimulatorPrivate::IsExpired (EventId ev)
|
||||
SimulatorPrivate::IsExpired (const EventId ev)
|
||||
{
|
||||
if (ev.GetEventImpl () == 0 ||
|
||||
ev.GetTs () < m_currentTs ||
|
||||
|
||||
@@ -173,6 +173,10 @@ public:
|
||||
*/
|
||||
template <typename T, typename OBJ, typename T1>
|
||||
static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1), OBJ obj, T1 a1);
|
||||
template <typename T, typename OBJ, typename T1>
|
||||
static EventId Schedule (Time const &time, void (T::*mem_ptr) (const T1&), OBJ obj, T1 a1); // GFR
|
||||
template <typename T, typename OBJ, typename T1>
|
||||
static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1&), OBJ obj, T1 a1); // GFR
|
||||
/**
|
||||
* @param time the relative expiration time of the event.
|
||||
* @param mem_ptr member method pointer to invoke
|
||||
@@ -234,6 +238,10 @@ public:
|
||||
*/
|
||||
template <typename T1>
|
||||
static EventId Schedule (Time const &time, void (*f) (T1), T1 a1);
|
||||
template <typename T1>
|
||||
static EventId Schedule (Time const &time, void (*f) (const T1&), T1 a1); // GFR
|
||||
template <typename T1>
|
||||
static EventId Schedule (Time const &time, void (*f) (T1&), T1 a1); // GFR
|
||||
/**
|
||||
* @param time the relative expiration time of the event.
|
||||
* @param f the function to invoke
|
||||
@@ -521,7 +529,7 @@ public:
|
||||
* @param id the event to test for expiration
|
||||
* @returns true if the event has expired, false otherwise.
|
||||
*/
|
||||
static bool IsExpired (EventId id);
|
||||
static bool IsExpired (const EventId id);
|
||||
/**
|
||||
* Return the "current simulation time".
|
||||
*/
|
||||
@@ -533,6 +541,10 @@ private:
|
||||
static EventImpl *MakeEvent (void (T::*mem_ptr) (void), OBJ obj);
|
||||
template <typename T, typename OBJ, typename T1>
|
||||
static EventImpl *MakeEvent (void (T::*mem_ptr) (T1), OBJ obj, T1 a1);
|
||||
template <typename T, typename OBJ, typename T1>
|
||||
static EventImpl *MakeEvent (void (T::*mem_ptr) (const T1&), OBJ obj, T1 a1); // GFR
|
||||
template <typename T, typename OBJ, typename T1>
|
||||
static EventImpl *MakeEvent (void (T::*mem_ptr) (T1&), OBJ obj, T1 a1); // GFR
|
||||
template <typename T, typename OBJ, typename T1, typename T2>
|
||||
static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2);
|
||||
template <typename T, typename OBJ, typename T1, typename T2, typename T3>
|
||||
@@ -642,6 +654,56 @@ EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1), OBJ obj, T1 a1)
|
||||
return ev;
|
||||
}
|
||||
|
||||
template <typename T, typename OBJ, typename T1>
|
||||
EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (const T1&), OBJ obj, T1 a1)
|
||||
{
|
||||
// one argument version, with const reference
|
||||
class EventMemberImpl1 : public EventImpl {
|
||||
public:
|
||||
typedef void (T::*F)(const T1&);
|
||||
EventMemberImpl1 (OBJ obj, F function, T1 a1)
|
||||
: m_obj (obj),
|
||||
m_function (function),
|
||||
m_a1 (a1)
|
||||
{}
|
||||
protected:
|
||||
virtual ~EventMemberImpl1 () {}
|
||||
private:
|
||||
virtual void Notify (void) {
|
||||
(EventMemberImplTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1);
|
||||
}
|
||||
OBJ m_obj;
|
||||
F m_function;
|
||||
T1 m_a1;
|
||||
} *ev = new EventMemberImpl1 (obj, mem_ptr, a1);
|
||||
return ev;
|
||||
}
|
||||
|
||||
template <typename T, typename OBJ, typename T1>
|
||||
EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1&), OBJ obj, T1 a1)
|
||||
{
|
||||
// one argument version with non-const reference
|
||||
class EventMemberImpl1 : public EventImpl {
|
||||
public:
|
||||
typedef void (T::*F)(T1&);
|
||||
EventMemberImpl1 (OBJ obj, F function, T1 a1)
|
||||
: m_obj (obj),
|
||||
m_function (function),
|
||||
m_a1 (a1)
|
||||
{}
|
||||
protected:
|
||||
virtual ~EventMemberImpl1 () {}
|
||||
private:
|
||||
virtual void Notify (void) {
|
||||
(EventMemberImplTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1);
|
||||
}
|
||||
OBJ m_obj;
|
||||
F m_function;
|
||||
T1 m_a1;
|
||||
} *ev = new EventMemberImpl1 (obj, mem_ptr, a1);
|
||||
return ev;
|
||||
}
|
||||
|
||||
template <typename T, typename OBJ, typename T1, typename T2>
|
||||
EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2)
|
||||
{
|
||||
@@ -920,6 +982,18 @@ EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1), OBJ obj,
|
||||
return Schedule (time, MakeEvent (mem_ptr, obj, a1));
|
||||
}
|
||||
|
||||
template <typename T, typename OBJ, typename T1>
|
||||
EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (const T1&), OBJ obj, T1 a1)
|
||||
{
|
||||
return Schedule (time, MakeEvent (mem_ptr, obj, a1));
|
||||
}
|
||||
|
||||
template <typename T, typename OBJ, typename T1>
|
||||
EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1&), OBJ obj, T1 a1)
|
||||
{
|
||||
return Schedule (time, MakeEvent (mem_ptr, obj, a1));
|
||||
}
|
||||
|
||||
template <typename T, typename OBJ, typename T1, typename T2>
|
||||
EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2)
|
||||
{
|
||||
|
||||
@@ -15,8 +15,6 @@ def set_options(opt):
|
||||
|
||||
|
||||
def configure(conf):
|
||||
conf.env.append_value('NS3_MODULES', 'ns3-simulator')
|
||||
|
||||
if Params.g_options.high_precision_as_double:
|
||||
conf.add_define('USE_HIGH_PRECISION_DOUBLE', 1)
|
||||
conf.env['USE_HIGH_PRECISION_DOUBLE'] = 1
|
||||
|
||||
@@ -29,9 +29,11 @@ def configure(conf):
|
||||
|
||||
blddir = os.path.abspath(os.path.join(conf.m_blddir, conf.env.variant()))
|
||||
for module in all_modules:
|
||||
conf.sub_config(module)
|
||||
conf.env.append_value('NS3_MODULE_PATH', os.path.join(blddir, 'src', module))
|
||||
|
||||
## Used to link the 'run-tests' program with all of ns-3 code
|
||||
conf.env['NS3_MODULES'] = ['ns3-' + module.split('/')[-1] for module in all_modules]
|
||||
|
||||
|
||||
def build(bld):
|
||||
Object.register('ns3header', Ns3Header)
|
||||
|
||||
55
wscript
55
wscript
@@ -8,6 +8,7 @@ import Params
|
||||
import Object
|
||||
import pproc as subprocess
|
||||
import optparse
|
||||
import os.path
|
||||
|
||||
Params.g_autoconfig = 1
|
||||
|
||||
@@ -20,8 +21,8 @@ srcdir = '.'
|
||||
blddir = 'build'
|
||||
|
||||
def dist_hook(srcdir, blddir):
|
||||
shutil.rmtree("doc/html")
|
||||
shutil.rmtree("doc/latex")
|
||||
shutil.rmtree("doc/html", True)
|
||||
shutil.rmtree("doc/latex", True)
|
||||
|
||||
def set_options(opt):
|
||||
|
||||
@@ -105,13 +106,23 @@ def configure(conf):
|
||||
|
||||
variant_env.append_value('CXXDEFINES', 'RUN_SELF_TESTS')
|
||||
|
||||
if os.path.basename(conf.env['CXX']).startswith("g++"):
|
||||
if (os.path.basename(conf.env['CXX']).startswith("g++")
|
||||
and 'CXXFLAGS' not in os.environ):
|
||||
variant_env.append_value('CXXFLAGS', ['-Wall', '-Werror'])
|
||||
|
||||
if 'debug' in Params.g_options.debug_level.lower():
|
||||
variant_env.append_value('CXXDEFINES', 'NS3_DEBUG_ENABLE')
|
||||
variant_env.append_value('CXXDEFINES', 'NS3_ASSERT_ENABLE')
|
||||
|
||||
## In optimized builds we still want debugging symbols, e.g. for
|
||||
## profiling, and at least partially usable stack traces.
|
||||
if ('optimized' in Params.g_options.debug_level.lower()
|
||||
and 'CXXFLAGS' not in os.environ):
|
||||
for flag in variant_env['CXXFLAGS_DEBUG']:
|
||||
## this probably doesn't work for MSVC
|
||||
if flag.startswith('-g'):
|
||||
variant_env.append_value('CXXFLAGS', flag)
|
||||
|
||||
if sys.platform == 'win32':
|
||||
if os.path.basename(conf.env['CXX']).startswith("g++"):
|
||||
variant_env.append_value("LINKFLAGS", "-Wl,--enable-runtime-pseudo-reloc")
|
||||
@@ -124,10 +135,7 @@ def build(bld):
|
||||
variant_env = bld.env_of_name(variant_name)
|
||||
bld.m_allenvs['default'] = variant_env # switch to the active variant
|
||||
|
||||
if Params.g_options.run:
|
||||
run_program(Params.g_options.run)
|
||||
return
|
||||
elif Params.g_options.shell:
|
||||
if Params.g_options.shell:
|
||||
run_shell()
|
||||
return
|
||||
|
||||
@@ -154,11 +162,26 @@ def shutdown():
|
||||
if Params.g_options.doxygen:
|
||||
doxygen()
|
||||
|
||||
def _find_program(program_name):
|
||||
if Params.g_options.run:
|
||||
run_program(Params.g_options.run)
|
||||
|
||||
def _find_program(program_name, env):
|
||||
launch_dir = os.path.abspath(Params.g_cwd_launch)
|
||||
found_programs = []
|
||||
for obj in Object.g_allobjs:
|
||||
if obj.m_type != 'program' or not obj.target:
|
||||
continue
|
||||
|
||||
## filter out programs not in the subtree starting at the launch dir
|
||||
if not (obj.path.abspath().startswith(launch_dir)
|
||||
or obj.path.abspath(env).startswith(launch_dir)):
|
||||
continue
|
||||
|
||||
found_programs.append(obj.target)
|
||||
if obj.target == program_name:
|
||||
return obj
|
||||
raise ValueError("progam '%s' not found" % (program_name,))
|
||||
raise ValueError("program '%s' not found; available programs are: %r"
|
||||
% (program_name, found_programs))
|
||||
|
||||
def _run_argv(argv):
|
||||
env = Params.g_build.env_of_name('default')
|
||||
@@ -198,9 +221,9 @@ def run_program(program_string):
|
||||
program_name = argv[0]
|
||||
|
||||
try:
|
||||
program_obj = _find_program(program_name)
|
||||
except ValueError:
|
||||
Params.fatal("progam '%s' not found" % (program_name,))
|
||||
program_obj = _find_program(program_name, env)
|
||||
except ValueError, ex:
|
||||
Params.fatal(str(ex))
|
||||
|
||||
try:
|
||||
program_node, = program_obj.m_linktask.m_outputs
|
||||
@@ -208,7 +231,13 @@ def run_program(program_string):
|
||||
Params.fatal("%s does not appear to be a program" % (program_name,))
|
||||
|
||||
execvec = [program_node.abspath(env)] + argv[1:]
|
||||
return _run_argv(execvec)
|
||||
|
||||
former_cwd = os.getcwd()
|
||||
os.chdir(Params.g_cwd_launch)
|
||||
try:
|
||||
return _run_argv(execvec)
|
||||
finally:
|
||||
os.chdir(former_cwd)
|
||||
|
||||
|
||||
def run_shell():
|
||||
|
||||
Reference in New Issue
Block a user