Merge with ns-3-dev.
This commit is contained in:
@@ -158,7 +158,16 @@ MeshTest::CreateNodes ()
|
||||
* mesh point device
|
||||
*/
|
||||
mesh = MeshHelper::Default ();
|
||||
mesh.SetStackInstaller (m_stack, "Root", Mac48AddressValue (Mac48Address (m_root.c_str ())));
|
||||
if (!Mac48Address (m_root.c_str ()).IsBroadcast ())
|
||||
{
|
||||
mesh.SetStackInstaller (m_stack, "Root", Mac48AddressValue (Mac48Address (m_root.c_str ())));
|
||||
}
|
||||
else
|
||||
{
|
||||
//If root is not set, we do not use "Root" attribute, because it
|
||||
//is specified only for 11s
|
||||
mesh.SetStackInstaller (m_stack);
|
||||
}
|
||||
if (m_chan)
|
||||
{
|
||||
mesh.SetSpreadInterfaceChannels (MeshHelper::SPREAD_CHANNELS);
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Craig Dowell (craigdo@ee.washington.edu)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
@@ -948,6 +950,62 @@ ReadFileTestCase::DoRun (void)
|
||||
return false;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test case to make sure that the Pcap::Diff method works as expected
|
||||
// ===========================================================================
|
||||
class DiffTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
DiffTestCase ();
|
||||
|
||||
private:
|
||||
virtual bool DoRun (void);
|
||||
};
|
||||
|
||||
DiffTestCase::DiffTestCase ()
|
||||
: TestCase ("Check that PcapFile::Diff works as expected")
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
DiffTestCase::DoRun (void)
|
||||
{
|
||||
//
|
||||
// Check that PcapDiff(file, file) is false
|
||||
//
|
||||
std::string filename = NS_TEST_SOURCEDIR + "known.pcap";
|
||||
uint32_t sec(0), usec(0);
|
||||
bool diff = PcapFile::Diff (filename, filename, sec, usec);
|
||||
NS_TEST_EXPECT_MSG_EQ (diff, false, "PcapDiff(file, file) must always be false");
|
||||
|
||||
//
|
||||
// Create different PCAP file (with the same timestamps, but different packets) and check that it is indeed different
|
||||
//
|
||||
std::string filename2 = "different.pcap";
|
||||
PcapFile f;
|
||||
|
||||
bool err = f.Open (filename2, "w");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << filename2 << ", \"w\") returns error");
|
||||
err = f.Init (1, N_PACKET_BYTES);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Init (1, " << N_PACKET_BYTES << ") returns error");
|
||||
|
||||
for (uint32_t i = 0; i < N_KNOWN_PACKETS; ++i)
|
||||
{
|
||||
PacketEntry const & p = knownPackets[i];
|
||||
|
||||
err = f.Write (p.tsSec, p.tsUsec, (uint8_t const *)p.data, p.origLen);
|
||||
NS_TEST_EXPECT_MSG_EQ (err, false, "Write must not fail");
|
||||
}
|
||||
f.Close ();
|
||||
|
||||
diff = PcapFile::Diff (filename, filename2, sec, usec);
|
||||
NS_TEST_EXPECT_MSG_EQ (diff, true, "PcapDiff(file, file2) must be true");
|
||||
NS_TEST_EXPECT_MSG_EQ (sec, 2, "Files are different from 2.3696 seconds");
|
||||
NS_TEST_EXPECT_MSG_EQ (usec, 3696, "Files are different from 2.3696 seconds");
|
||||
|
||||
return GetErrorStatus();
|
||||
}
|
||||
|
||||
class PcapFileTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
@@ -963,6 +1021,7 @@ PcapFileTestSuite::PcapFileTestSuite ()
|
||||
AddTestCase (new FileHeaderTestCase);
|
||||
AddTestCase (new RecordHeaderTestCase);
|
||||
AddTestCase (new ReadFileTestCase);
|
||||
AddTestCase (new DiffTestCase);
|
||||
}
|
||||
|
||||
PcapFileTestSuite pcapFileTestSuite;
|
||||
|
||||
@@ -14,14 +14,16 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Craig Dowell (craigdo@ee.washington.edu)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstring>
|
||||
|
||||
#include "pcap-file.h"
|
||||
|
||||
//
|
||||
// This file is used as part of the ns-3 test framework, so please refrain from
|
||||
// adding any ns-3 specific constructs such as Packet to this file.
|
||||
@@ -516,4 +518,65 @@ PcapFile::Read (
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
PcapFile::Diff (std::string const & f1, std::string const & f2,
|
||||
uint32_t & sec, uint32_t & usec,
|
||||
uint32_t snapLen)
|
||||
{
|
||||
PcapFile pcap[2];
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
std::string const & file = (i == 0) ? f1 : f2;
|
||||
bool err = pcap[i].Open (file, "r");
|
||||
if (err)
|
||||
{
|
||||
// Can't open file
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t data[2][snapLen];
|
||||
uint32_t tsSec[2], tsUsec[2], inclLen[2], origLen[2], readLen[2];
|
||||
bool err[2];
|
||||
bool diff(false);
|
||||
|
||||
while (1)
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
err[i] = pcap[i].Read (data[i], snapLen, tsSec[i], tsUsec[i], inclLen[i], origLen[i], readLen[i]);
|
||||
|
||||
sec = tsSec[0];
|
||||
usec = tsUsec[0];
|
||||
|
||||
if (err[0] != err[1])
|
||||
{
|
||||
diff = true; // Read status doesn't match
|
||||
break;
|
||||
}
|
||||
|
||||
if (err[0]) break; // nothing left
|
||||
|
||||
if (tsSec[0] != tsSec[1] || tsUsec[0] != tsUsec[1])
|
||||
{
|
||||
diff = true; // Next packet timestamps do not match
|
||||
break;
|
||||
}
|
||||
|
||||
if (readLen[0] != readLen[1])
|
||||
{
|
||||
diff = true; // Packet lengths do not match
|
||||
break;
|
||||
}
|
||||
|
||||
if (std::memcmp(data[0], data[1], readLen[0]) != 0)
|
||||
{
|
||||
diff = true; // Packet data do not match
|
||||
break;
|
||||
}
|
||||
}
|
||||
pcap[0].Close ();
|
||||
pcap[1].Close ();
|
||||
return diff;
|
||||
}
|
||||
|
||||
} //namespace ns3
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Craig Dowell (craigdo@ee.washington.edu)
|
||||
*/
|
||||
|
||||
#ifndef PCAP_FILE_H
|
||||
@@ -125,7 +127,7 @@ public:
|
||||
* time zone from UTC/GMT. For example, Pacific Standard Time in the US is
|
||||
* GMT-8, so one would enter -8 for that correction. Defaults to 0 (UTC).
|
||||
*
|
||||
* \returns false if the open succeeds, true otherwise.
|
||||
* \return false if the open succeeds, true otherwise.
|
||||
*
|
||||
* \warning Calling this method on an existing file will result in the loss
|
||||
* any existing data.
|
||||
@@ -135,8 +137,31 @@ public:
|
||||
int32_t timeZoneCorrection = ZONE_DEFAULT,
|
||||
bool swapMode = false);
|
||||
|
||||
/**
|
||||
* \brief Write next packet to file
|
||||
*
|
||||
* \param tsSec Packet timestamp, seconds
|
||||
* \param tsUsec Packet timestamp, microseconds
|
||||
* \param data Data buffer
|
||||
* \param totalLen Total packet length
|
||||
*
|
||||
* \return true on error, false otherwise
|
||||
*/
|
||||
bool Write (uint32_t tsSec, uint32_t tsUsec, uint8_t const * const data, uint32_t totalLen);
|
||||
|
||||
/**
|
||||
* \brief Read next packet from file
|
||||
*
|
||||
* \param data [out] Data buffer
|
||||
* \param maxBytes Allocated data buffer size
|
||||
* \param tsSec [out] Packet timestamp, seconds
|
||||
* \param tsUsec [out] Packet timestamp, microseconds
|
||||
* \param inclLen [out] Included length
|
||||
* \param origLen [out] Original length
|
||||
* \param readLen [out] Number of bytes read
|
||||
*
|
||||
* \return true if read failed, false otherwise
|
||||
*/
|
||||
bool Read (uint8_t * const data,
|
||||
uint32_t maxBytes,
|
||||
uint32_t &tsSec,
|
||||
@@ -154,6 +179,21 @@ public:
|
||||
uint32_t GetSigFigs (void);
|
||||
uint32_t GetSnapLen (void);
|
||||
uint32_t GetDataLinkType (void);
|
||||
|
||||
/**
|
||||
* \brief Compare two PCAP files packet-by-packet
|
||||
*
|
||||
* \return true if files are different, false otherwise
|
||||
*
|
||||
* \param f1 First PCAP file name
|
||||
* \param f2 Second PCAP file name
|
||||
* \param sec [out] Time stamp of first different packet, seconds. Undefined if files doesn't differ.
|
||||
* \param uses [out] Time stamp of first different packet, microseconds. Undefined if files doesn't differ.
|
||||
* \param snapLen Snap length (if used)
|
||||
*/
|
||||
static bool Diff (std::string const & f1, std::string const & f2,
|
||||
uint32_t & sec, uint32_t & usec,
|
||||
uint32_t snapLen = SNAPLEN_DEFAULT);
|
||||
|
||||
private:
|
||||
typedef struct {
|
||||
|
||||
@@ -21,10 +21,13 @@
|
||||
#ifndef SYSTEM_WALL_CLOCK_MS_H
|
||||
#define SYSTEM_WALL_CLOCK_MS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief measure wall-clock time in milliseconds
|
||||
* \brief measure elapsed time in milliseconds
|
||||
*
|
||||
*/
|
||||
class SystemWallClockMs {
|
||||
public:
|
||||
@@ -36,13 +39,39 @@ public:
|
||||
*/
|
||||
void Start (void);
|
||||
/**
|
||||
* \returns the measured elapsed wall clock time since
|
||||
* ns3::SystemWallClockMs::start was invoked.
|
||||
* \brief Stop measuring the time since Start() was called.
|
||||
* \returns the measured elapsed wall clock time (in milliseconds) since
|
||||
* ns3::SystemWallClockMs::Start was invoked.
|
||||
*
|
||||
* It is possible to start a new measurement with ns3::SystemWallClockMs::start
|
||||
* It is possible to start a new measurement with ns3::SystemWallClockMs::Start
|
||||
* after this method returns.
|
||||
*
|
||||
* Returns int64_t to avoid dependency on clock_t in ns-3 code.
|
||||
*/
|
||||
unsigned long long End (void);
|
||||
int64_t End (void);
|
||||
|
||||
/**
|
||||
* \returns the measured elapsed wall clock time (in milliseconds) since
|
||||
* ns3::SystemWallClockMs::Start was invoked.
|
||||
*
|
||||
* Returns int64_t to avoid dependency on clock_t in ns-3 code.
|
||||
*/
|
||||
int64_t GetElapsedReal (void) const;
|
||||
/**
|
||||
* \returns the measured elapsed 'user' wall clock time (in milliseconds) since
|
||||
* ns3::SystemWallClockMs::Start was invoked.
|
||||
*
|
||||
* Returns int64_t to avoid dependency on clock_t in ns-3 code.
|
||||
*/
|
||||
int64_t GetElapsedUser (void) const;
|
||||
/**
|
||||
* \returns the measured elapsed 'system' wall clock time (in milliseconds) since
|
||||
* ns3::SystemWallClockMs::Start was invoked.
|
||||
*
|
||||
* Returns int64_t to avoid dependency on clock_t in ns-3 code.
|
||||
*/
|
||||
int64_t GetElapsedSystem (void) const;
|
||||
|
||||
private:
|
||||
class SystemWallClockMsPrivate *m_priv;
|
||||
};
|
||||
|
||||
@@ -262,7 +262,7 @@ TestCase::ContinueOnFailure (void)
|
||||
void
|
||||
TestCase::DoReportStart (void)
|
||||
{
|
||||
m_startTime = times (&m_startTimes);
|
||||
m_msClock.Start ();
|
||||
|
||||
if (m_ofs == 0)
|
||||
{
|
||||
@@ -319,26 +319,21 @@ TestCase::DoReportTestFailure (
|
||||
void
|
||||
TestCase::DoReportEnd (void)
|
||||
{
|
||||
static long ticksPerSecond = sysconf (_SC_CLK_TCK);
|
||||
m_msClock.End ();
|
||||
|
||||
if (m_ofs == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
struct tms endTimes;
|
||||
clock_t endTime = times (&endTimes);
|
||||
|
||||
clock_t elapsed = endTime - m_startTime;
|
||||
clock_t elapsedUsr = endTimes.tms_utime - m_startTimes.tms_utime;
|
||||
clock_t elapsedSys = endTimes.tms_stime - m_startTimes.tms_stime;
|
||||
|
||||
(*m_ofs).precision (2);
|
||||
(*m_ofs).precision (3);
|
||||
*m_ofs << std::fixed;
|
||||
|
||||
*m_ofs << " <CaseTime>" << "real " << static_cast<double> (elapsed) / ticksPerSecond
|
||||
<< " user " << static_cast<double> (elapsedUsr) / ticksPerSecond
|
||||
<< " system " << static_cast<double> (elapsedSys) / ticksPerSecond
|
||||
const double MS_PER_SEC = 1000.;
|
||||
|
||||
*m_ofs << " <CaseTime>" << "real " << m_msClock.GetElapsedReal () / MS_PER_SEC
|
||||
<< " user " << m_msClock.GetElapsedUser () / MS_PER_SEC
|
||||
<< " system " << m_msClock.GetElapsedSystem () / MS_PER_SEC
|
||||
<< "</CaseTime>" << std::endl;
|
||||
|
||||
*m_ofs << " </TestCase>" << std::endl;
|
||||
@@ -523,8 +518,8 @@ TestSuite::ContinueOnFailure (void)
|
||||
void
|
||||
TestSuite::DoReportStart (void)
|
||||
{
|
||||
m_startTime = times (&m_startTimes);
|
||||
|
||||
m_msClock.Start ();
|
||||
|
||||
if (m_ofs == 0)
|
||||
{
|
||||
return;
|
||||
@@ -556,25 +551,21 @@ TestSuite::DoReportSuccess (void)
|
||||
void
|
||||
TestSuite::DoReportEnd (void)
|
||||
{
|
||||
static long ticksPerSecond = sysconf (_SC_CLK_TCK);
|
||||
|
||||
m_msClock.End ();
|
||||
|
||||
if (m_ofs == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
struct tms endTimes;
|
||||
clock_t endTime = times (&endTimes);
|
||||
|
||||
clock_t elapsed = endTime - m_startTime;
|
||||
clock_t elapsedUsr = endTimes.tms_utime - m_startTimes.tms_utime;
|
||||
clock_t elapsedSys = endTimes.tms_stime - m_startTimes.tms_stime;
|
||||
|
||||
(*m_ofs).precision (2);
|
||||
(*m_ofs).precision (3);
|
||||
*m_ofs << std::fixed;
|
||||
|
||||
*m_ofs << " <SuiteTime>" << "real " << static_cast<double> (elapsed) / ticksPerSecond
|
||||
<< " user " << static_cast<double> (elapsedUsr) / ticksPerSecond
|
||||
<< " system " << static_cast<double> (elapsedSys) / ticksPerSecond
|
||||
const double MS_PER_SEC = 1000.;
|
||||
|
||||
*m_ofs << " <SuiteTime>" << "real " << m_msClock.GetElapsedReal () / MS_PER_SEC
|
||||
<< " user " << m_msClock.GetElapsedUser () / MS_PER_SEC
|
||||
<< " system " << m_msClock.GetElapsedSystem () / MS_PER_SEC
|
||||
<< "</SuiteTime>" << std::endl;
|
||||
|
||||
*m_ofs << "</TestSuite>" << std::endl;
|
||||
|
||||
@@ -27,7 +27,10 @@
|
||||
#include <list>
|
||||
#include <limits>
|
||||
#include <stdint.h>
|
||||
#include <sys/times.h>
|
||||
|
||||
#include "ns3/system-wall-clock-ms.h"
|
||||
|
||||
|
||||
//
|
||||
// Note on below macros:
|
||||
//
|
||||
@@ -821,6 +824,7 @@ private:
|
||||
TestCase (TestCase& tc);
|
||||
TestCase& operator= (TestCase& tc);
|
||||
|
||||
SystemWallClockMs m_msClock;
|
||||
std::string m_name;
|
||||
bool m_verbose;
|
||||
bool m_continueOnFailure;
|
||||
@@ -828,8 +832,6 @@ private:
|
||||
std::string m_basedir;
|
||||
std::ofstream *m_ofs;
|
||||
bool m_error;
|
||||
clock_t m_startTime;
|
||||
struct tms m_startTimes;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1057,6 +1059,7 @@ private:
|
||||
TestSuite (TestSuite& ts);
|
||||
TestSuite& operator= (TestSuite& ts);
|
||||
|
||||
SystemWallClockMs m_msClock;
|
||||
std::string m_name;
|
||||
bool m_verbose;
|
||||
bool m_continueOnFailure;
|
||||
@@ -1064,10 +1067,7 @@ private:
|
||||
std::ofstream *m_ofs;
|
||||
bool m_error;
|
||||
TestType m_type;
|
||||
|
||||
clock_t m_startTime;
|
||||
struct tms m_startTimes;
|
||||
|
||||
|
||||
typedef std::vector<TestCase *> TestCaseVector_t;
|
||||
TestCaseVector_t m_tests;
|
||||
};
|
||||
|
||||
@@ -19,36 +19,105 @@
|
||||
*/
|
||||
|
||||
#include "system-wall-clock-ms.h"
|
||||
#include <sys/time.h>
|
||||
#include "abort.h"
|
||||
#include <sys/times.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class SystemWallClockMsPrivate {
|
||||
public:
|
||||
void Start (void);
|
||||
unsigned long long End (void);
|
||||
int64_t End (void);
|
||||
int64_t GetElapsedReal (void) const;
|
||||
int64_t GetElapsedUser (void) const;
|
||||
int64_t GetElapsedSystem (void) const;
|
||||
|
||||
private:
|
||||
struct timeval m_startTv;
|
||||
struct timeval m_endTv;
|
||||
struct tms m_startTimes;
|
||||
clock_t m_startTime;
|
||||
int64_t m_elapsedReal;
|
||||
int64_t m_elapsedUser;
|
||||
int64_t m_elapsedSystem;
|
||||
};
|
||||
|
||||
void
|
||||
SystemWallClockMsPrivate::Start (void)
|
||||
{
|
||||
struct timezone tz;
|
||||
gettimeofday (&m_startTv, &tz);
|
||||
m_startTime = times (&m_startTimes);
|
||||
}
|
||||
|
||||
unsigned long long
|
||||
int64_t
|
||||
SystemWallClockMsPrivate::End (void)
|
||||
{
|
||||
struct timezone tz;
|
||||
gettimeofday (&m_endTv, &tz);
|
||||
unsigned long long end = m_endTv.tv_sec *1000 + m_endTv.tv_usec / 1000;
|
||||
unsigned long long start = m_startTv.tv_sec *1000 + m_startTv.tv_usec / 1000;
|
||||
return end - start;
|
||||
//
|
||||
// We need to return the number of milliseconds that have elapsed in some
|
||||
// reasonably portable way. The underlying function that we will use returns
|
||||
// a number of elapsed ticks. We can look up the number of ticks per second
|
||||
// from the system configuration.
|
||||
//
|
||||
// Conceptually, we need to find the number of elapsed clock ticks and then
|
||||
// multiply the result by the milliseconds per clock tick (or divide by clock
|
||||
// ticks per millisecond). Integer dividing by clock ticks per millisecond
|
||||
// is bad since this number is fractional on most machines and would result
|
||||
// in divide by zero errors due to integer rounding.
|
||||
//
|
||||
// Multiplying by milliseconds per clock tick works up to a clock resolution
|
||||
// of 1000 ticks per second. If we go past this point, we begin to get zero
|
||||
// elapsed times when millisecondsPerTick becomes fractional and another
|
||||
// rounding error appears.
|
||||
//
|
||||
// So rounding errors using integers can bite you from both direction. Since
|
||||
// all of our targets have math coprocessors, why not just use doubles
|
||||
// internally? Works fine, lasts a long time.
|
||||
//
|
||||
// If millisecondsPerTick becomes fractional, and an elapsed time greater than
|
||||
// a milliscond is measured, the function will work as expected. If an elapsed
|
||||
// time is measured that turns out to be less than a millisecond, we'll just
|
||||
// return zero which would, I think, also will be expected.
|
||||
//
|
||||
static int64_t ticksPerSecond = sysconf (_SC_CLK_TCK);
|
||||
static double millisecondsPerTick = 1000. / ticksPerSecond;
|
||||
|
||||
//
|
||||
// If sysconf () fails, we have no idea how to do the required conversion to ms.
|
||||
//
|
||||
NS_ABORT_MSG_IF (ticksPerSecond == -1, "SystemWallClockMsPrivate(): Cannot sysconf (_SC_CLK_TCK)");
|
||||
|
||||
struct tms endTimes;
|
||||
clock_t endTime = times (&endTimes);
|
||||
|
||||
double tmp;
|
||||
|
||||
tmp = static_cast<double> (endTime - m_startTime) * millisecondsPerTick;
|
||||
m_elapsedReal = static_cast<int64_t> (tmp);
|
||||
|
||||
tmp = static_cast<double> (endTimes.tms_utime - m_startTimes.tms_utime) * millisecondsPerTick;
|
||||
m_elapsedUser = static_cast<int64_t> (tmp);
|
||||
|
||||
tmp = static_cast<double> (endTimes.tms_stime - m_startTimes.tms_stime) * millisecondsPerTick;
|
||||
m_elapsedSystem = static_cast<int64_t> (tmp);
|
||||
|
||||
return m_elapsedReal;
|
||||
}
|
||||
|
||||
int64_t
|
||||
SystemWallClockMsPrivate::GetElapsedReal (void) const
|
||||
{
|
||||
return m_elapsedReal;
|
||||
}
|
||||
|
||||
int64_t
|
||||
SystemWallClockMsPrivate::GetElapsedUser (void) const
|
||||
{
|
||||
return m_elapsedUser;
|
||||
}
|
||||
|
||||
int64_t
|
||||
SystemWallClockMsPrivate::GetElapsedSystem (void) const
|
||||
{
|
||||
return m_elapsedSystem;
|
||||
}
|
||||
|
||||
SystemWallClockMs::SystemWallClockMs ()
|
||||
: m_priv (new SystemWallClockMsPrivate ())
|
||||
{}
|
||||
@@ -64,10 +133,29 @@ SystemWallClockMs::Start (void)
|
||||
{
|
||||
m_priv->Start ();
|
||||
}
|
||||
unsigned long long
|
||||
|
||||
int64_t
|
||||
SystemWallClockMs::End (void)
|
||||
{
|
||||
return m_priv->End ();
|
||||
}
|
||||
|
||||
int64_t
|
||||
SystemWallClockMs::GetElapsedReal (void) const
|
||||
{
|
||||
return m_priv->GetElapsedReal ();
|
||||
}
|
||||
|
||||
int64_t
|
||||
SystemWallClockMs::GetElapsedUser (void) const
|
||||
{
|
||||
return m_priv->GetElapsedUser ();
|
||||
}
|
||||
|
||||
int64_t
|
||||
SystemWallClockMs::GetElapsedSystem (void) const
|
||||
{
|
||||
return m_priv->GetElapsedSystem ();
|
||||
}
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
@@ -20,26 +20,97 @@
|
||||
|
||||
#include "system-wall-clock-ms.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class SystemWallClockMsPrivate {
|
||||
public:
|
||||
void Start (void);
|
||||
unsigned long long End (void);
|
||||
int64_t End (void);
|
||||
int64_t GetElapsedReal (void) const;
|
||||
int64_t GetElapsedUser (void) const;
|
||||
int64_t GetElapsedSystem (void) const;
|
||||
|
||||
private:
|
||||
clock_t m_startTime;
|
||||
int64_t m_elapsedReal;
|
||||
int64_t m_elapsedUser;
|
||||
int64_t m_elapsedSystem;
|
||||
};
|
||||
|
||||
void
|
||||
SystemWallClockMsPrivate::Start (void)
|
||||
{
|
||||
m_startTime = clock ();
|
||||
}
|
||||
|
||||
unsigned long long
|
||||
int64_t
|
||||
SystemWallClockMsPrivate::End (void)
|
||||
{
|
||||
return 0;
|
||||
//
|
||||
// We need to return the number of milliseconds that have elapsed in some
|
||||
// reasonably portable way. The underlying function that we will use returns
|
||||
// a number of elapsed ticks. We can look up the number of ticks per second
|
||||
// from the system configuration.
|
||||
//
|
||||
// Conceptually, we need to find the number of elapsed clock ticks and then
|
||||
// multiply the result by the milliseconds per clock tick (or just as easily
|
||||
// divide by clock ticks per millisecond). Integer dividing by clock ticks
|
||||
// per millisecond is bad since this number is fractional on most machines
|
||||
// and would result in divide by zero errors due to integer rounding.
|
||||
//
|
||||
// Multiplying by milliseconds per clock tick works up to a clock resolution
|
||||
// of 1000 ticks per second. If we go past this point, we begin to get zero
|
||||
// elapsed times when millisecondsPerTick becomes fractional and another
|
||||
// rounding error appears.
|
||||
//
|
||||
// So rounding errors using integers can bite you from two direction. Since
|
||||
// all of our targets have math coprocessors, why not just use doubles
|
||||
// internally? Works fine, lasts a long time.
|
||||
//
|
||||
// If millisecondsPerTick becomes fractional, and an elapsed time greater than
|
||||
// a milliscond is measured, the function will work as expected. If an elapsed
|
||||
// time is measured that turns out to be less than a millisecond, we'll just
|
||||
// return zero which would, I think, also will be expected.
|
||||
//
|
||||
static int64_t ticksPerSecond = CLOCKS_PER_SEC;
|
||||
static double millisecondsPerTick = 1000. / ticksPerSecond;
|
||||
|
||||
clock_t endTime = clock ();
|
||||
|
||||
double tmp;
|
||||
|
||||
tmp = static_cast<double> (endTime - m_startTime) * millisecondsPerTick;
|
||||
m_elapsedReal = static_cast<int64_t> (tmp);
|
||||
|
||||
//
|
||||
// Nothing like this in MinGW, for example.
|
||||
//
|
||||
m_elapsedUser = 0;
|
||||
m_elapsedSystem = 0;
|
||||
|
||||
return m_elapsedReal;
|
||||
}
|
||||
|
||||
int64_t
|
||||
SystemWallClockMsPrivate::GetElapsedReal (void) const
|
||||
{
|
||||
return m_elapsedReal;
|
||||
}
|
||||
|
||||
int64_t
|
||||
SystemWallClockMsPrivate::GetElapsedUser (void) const
|
||||
{
|
||||
return m_elapsedUser;
|
||||
}
|
||||
|
||||
int64_t
|
||||
SystemWallClockMsPrivate::GetElapsedSystem (void) const
|
||||
{
|
||||
return m_elapsedSystem;
|
||||
}
|
||||
|
||||
SystemWallClockMs::SystemWallClockMs ()
|
||||
: m_priv (new SystemWallClockMsPrivate ())
|
||||
{}
|
||||
@@ -55,10 +126,29 @@ SystemWallClockMs::Start (void)
|
||||
{
|
||||
m_priv->Start ();
|
||||
}
|
||||
unsigned long long
|
||||
|
||||
int64_t
|
||||
SystemWallClockMs::End (void)
|
||||
{
|
||||
return m_priv->End ();
|
||||
}
|
||||
|
||||
int64_t
|
||||
SystemWallClockMs::GetElapsedReal (void) const
|
||||
{
|
||||
return m_priv->GetElapsedReal ();
|
||||
}
|
||||
|
||||
int64_t
|
||||
SystemWallClockMs::GetElapsedUser (void) const
|
||||
{
|
||||
return m_priv->GetElapsedUser ();
|
||||
}
|
||||
|
||||
int64_t
|
||||
SystemWallClockMs::GetElapsedSystem (void) const
|
||||
{
|
||||
return m_priv->GetElapsedSystem ();
|
||||
}
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
@@ -320,7 +320,7 @@ HwmpProtocol::ForwardUnicast (uint32_t sourceIface, const Mac48Address source,
|
||||
{
|
||||
NS_ASSERT(destination != Mac48Address::GetBroadcast ());
|
||||
HwmpRtable::LookupResult result = m_rtable->LookupReactive (destination);
|
||||
NS_LOG_DEBUG("Requested src = "<<source<<", dst = "<<destination<<", I am "<<GetAddress ()<<", RA = "<<result.retransmitter);
|
||||
NS_LOG_DEBUG ("Requested src = "<<source<<", dst = "<<destination<<", I am "<<GetAddress ()<<", RA = "<<result.retransmitter);
|
||||
if (result.retransmitter == Mac48Address::GetBroadcast ())
|
||||
{
|
||||
result = m_rtable->LookupProactive ();
|
||||
@@ -477,6 +477,15 @@ HwmpProtocol::ReceivePreq (IePreq preq, Mac48Address from, uint32_t interface, M
|
||||
preq.GetOriginatorSeqNumber ()
|
||||
);
|
||||
ProactivePathResolved ();
|
||||
m_rtable->AddReactivePath (
|
||||
preq.GetOriginatorAddress (),
|
||||
from,
|
||||
interface,
|
||||
preq.GetMetric (),
|
||||
MicroSeconds (preq.GetLifetime () * 1024),
|
||||
preq.GetOriginatorSeqNumber ()
|
||||
);
|
||||
ReactivePathResolved (preq.GetOriginatorAddress ());
|
||||
}
|
||||
if (!preq.IsNeedNotPrep ())
|
||||
{
|
||||
@@ -609,11 +618,6 @@ HwmpProtocol::ReceivePrep (IePrep prep, Mac48Address from, uint32_t interface, M
|
||||
NS_LOG_DEBUG("I am "<<GetAddress ()<<", resolved "<<prep.GetOriginatorAddress ());
|
||||
return;
|
||||
}
|
||||
if (result.retransmitter == Mac48Address::GetBroadcast ())
|
||||
{
|
||||
//try to look for default route
|
||||
result = m_rtable->LookupProactive ();
|
||||
}
|
||||
if (result.retransmitter == Mac48Address::GetBroadcast ())
|
||||
{
|
||||
return;
|
||||
@@ -1008,7 +1012,6 @@ HwmpProtocol::SetRoot ()
|
||||
Time randomStart = Seconds (coefficient.GetValue ());
|
||||
m_proactivePreqTimer = Simulator::Schedule (randomStart, &HwmpProtocol::SendProactivePreq, this);
|
||||
NS_LOG_DEBUG ("ROOT IS: " << m_address);
|
||||
SendProactivePreq ();
|
||||
m_isRoot = true;
|
||||
}
|
||||
void
|
||||
|
||||
@@ -78,6 +78,7 @@ public:
|
||||
* \param interface the interface where a beacon was received from
|
||||
* \param peerAddress address of station, which sent a beacon
|
||||
* \param beaconInterval beacon interval (needed by beacon loss counter)
|
||||
* \param beaconTiming beacon timing element (needed by BCA)
|
||||
*/
|
||||
void ReceiveBeacon (uint32_t interface, Mac48Address peerAddress, Time beaconInterval, Ptr<IeBeaconTiming> beaconTiming);
|
||||
//\}
|
||||
|
||||
@@ -31,6 +31,8 @@ FlameProtocolMac::FlameProtocolMac (uint32_t ifIndex, Ptr<FlameProtocol> protoco
|
||||
}
|
||||
FlameProtocolMac::~FlameProtocolMac ()
|
||||
{
|
||||
m_protocol = 0;
|
||||
m_parent = 0;
|
||||
}
|
||||
void
|
||||
FlameProtocolMac::SetParent (Ptr<MeshWifiInterfaceMac> parent)
|
||||
|
||||
@@ -127,7 +127,7 @@ FlameProtocol::GetTypeId ()
|
||||
return tid;
|
||||
}
|
||||
FlameProtocol::FlameProtocol () :
|
||||
m_address (Mac48Address ()), m_broadcastInterval (Seconds (5)), m_lastBroadcast (Simulator::Now ()),
|
||||
m_address (Mac48Address ()), m_broadcastInterval (Seconds (5)), m_lastBroadcast (Seconds (0)),
|
||||
m_maxCost (32), m_myLastSeqno (1), m_rtable (CreateObject<FlameRtable> ())
|
||||
{
|
||||
}
|
||||
@@ -137,6 +137,9 @@ FlameProtocol::~FlameProtocol ()
|
||||
void
|
||||
FlameProtocol::DoDispose ()
|
||||
{
|
||||
m_interfaces.clear ();
|
||||
m_rtable = 0;
|
||||
m_mp = 0;
|
||||
}
|
||||
bool
|
||||
FlameProtocol::RequestRoute (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
|
||||
@@ -224,8 +227,12 @@ FlameProtocol::RequestRoute (uint32_t sourceIface, const Mac48Address source, co
|
||||
m_stats.totalDropped++;
|
||||
return false;
|
||||
}
|
||||
tag.receiver = result.retransmitter;
|
||||
}
|
||||
else
|
||||
{
|
||||
tag.receiver = Mac48Address::GetBroadcast ();
|
||||
}
|
||||
tag.receiver = result.retransmitter;
|
||||
if (result.retransmitter == Mac48Address::GetBroadcast ())
|
||||
{
|
||||
m_stats.txBroadcast++;
|
||||
@@ -262,19 +269,21 @@ FlameProtocol::RemoveRoutingStuff (uint32_t fromIface, const Mac48Address source
|
||||
}
|
||||
FlameHeader flameHdr;
|
||||
packet->RemoveHeader (flameHdr);
|
||||
if ((destination == GetAddress ()) && (m_lastBroadcast + m_broadcastInterval < Simulator::Now ()))
|
||||
{
|
||||
Ptr<Packet> packet = Create<Packet> ();
|
||||
m_mp->Send(packet, Mac48Address::GetBroadcast (), 0);
|
||||
m_lastBroadcast = Simulator::Now ();
|
||||
}
|
||||
NS_ASSERT (protocolType == FLAME_PROTOCOL);
|
||||
protocolType = flameHdr.GetProtocol ();
|
||||
if ((HandleDataFrame (flameHdr.GetSeqno (), source, flameHdr, tag.transmitter, fromIface))
|
||||
|| packet->GetSize () == 0)
|
||||
if (HandleDataFrame (flameHdr.GetSeqno (), source, flameHdr, tag.transmitter, fromIface))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Start PATH_UPDATE procedure if destination is our own address and last broadcast was sent more
|
||||
// than broadcast interval ago or was not sent at all
|
||||
if ((destination == GetAddress ()) && ((m_lastBroadcast + m_broadcastInterval < Simulator::Now ())
|
||||
|| (m_lastBroadcast == Seconds (0))))
|
||||
{
|
||||
Ptr<Packet> packet = Create<Packet> ();
|
||||
m_mp->Send (packet, Mac48Address::GetBroadcast (), 0);
|
||||
m_lastBroadcast = Simulator::Now ();
|
||||
}
|
||||
NS_ASSERT (protocolType == FLAME_PROTOCOL);
|
||||
protocolType = flameHdr.GetProtocol ();
|
||||
return true;
|
||||
}
|
||||
bool
|
||||
|
||||
@@ -27,14 +27,7 @@
|
||||
namespace ns3 {
|
||||
|
||||
QosWifiMacHelper::QosWifiMacHelper ()
|
||||
{
|
||||
ObjectFactory defaultAggregator;
|
||||
defaultAggregator.SetTypeId ("ns3::MsduStandardAggregator");
|
||||
m_aggregators.insert (std::make_pair (AC_VO, defaultAggregator));
|
||||
m_aggregators.insert (std::make_pair (AC_VI, defaultAggregator));
|
||||
m_aggregators.insert (std::make_pair (AC_BE, defaultAggregator));
|
||||
m_aggregators.insert (std::make_pair (AC_BK, defaultAggregator));
|
||||
}
|
||||
{}
|
||||
|
||||
QosWifiMacHelper::~QosWifiMacHelper ()
|
||||
{}
|
||||
@@ -77,8 +70,7 @@ QosWifiMacHelper::SetMsduAggregatorForAc (AccessClass accessClass, std::string t
|
||||
std::string n2, const AttributeValue &v2,
|
||||
std::string n3, const AttributeValue &v3)
|
||||
{
|
||||
std::map<AccessClass, ObjectFactory>::iterator it;
|
||||
it = m_aggregators.find (accessClass);
|
||||
std::map<AccessClass, ObjectFactory>::iterator it = m_aggregators.find (accessClass);
|
||||
if (it != m_aggregators.end ())
|
||||
{
|
||||
it->second.SetTypeId (type);
|
||||
@@ -87,17 +79,32 @@ QosWifiMacHelper::SetMsduAggregatorForAc (AccessClass accessClass, std::string t
|
||||
it->second.Set (n2, v2);
|
||||
it->second.Set (n3, v3);
|
||||
}
|
||||
else
|
||||
{
|
||||
ObjectFactory factory;
|
||||
factory.SetTypeId (type);
|
||||
factory.Set (n0, v0);
|
||||
factory.Set (n1, v1);
|
||||
factory.Set (n2, v2);
|
||||
factory.Set (n3, v3);
|
||||
m_aggregators.insert (std::make_pair (accessClass, factory));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QosWifiMacHelper::Setup (Ptr<WifiMac> mac, enum AccessClass ac, std::string dcaAttrName) const
|
||||
{
|
||||
ObjectFactory factory = m_aggregators.find (ac)->second;
|
||||
PointerValue ptr;
|
||||
mac->GetAttribute (dcaAttrName, ptr);
|
||||
Ptr<EdcaTxopN> edca = ptr.Get<EdcaTxopN> ();
|
||||
Ptr<MsduAggregator> aggregator = factory.Create<MsduAggregator> ();
|
||||
edca->SetMsduAggregator (aggregator);
|
||||
std::map<AccessClass, ObjectFactory>::const_iterator it = m_aggregators.find (ac);
|
||||
if (it != m_aggregators.end ())
|
||||
{
|
||||
ObjectFactory factory = it->second;
|
||||
|
||||
PointerValue ptr;
|
||||
mac->GetAttribute (dcaAttrName, ptr);
|
||||
Ptr<EdcaTxopN> edca = ptr.Get<EdcaTxopN> ();
|
||||
Ptr<MsduAggregator> aggregator = factory.Create<MsduAggregator> ();
|
||||
edca->SetMsduAggregator (aggregator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -552,7 +552,23 @@ RoutingProtocol::MprComputation()
|
||||
}
|
||||
}
|
||||
|
||||
NS_LOG_DEBUG ("Size of N2: " << N2.size ());
|
||||
#ifdef NS3_LOG_ENABLE
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "[";
|
||||
for (TwoHopNeighborSet::const_iterator iter = N2.begin ();
|
||||
iter != N2.end (); iter++)
|
||||
{
|
||||
TwoHopNeighborSet::const_iterator next = iter;
|
||||
next++;
|
||||
os << iter->neighborMainAddr << "->" << iter->twoHopNeighborAddr;
|
||||
if (next != N2.end ())
|
||||
os << ", ";
|
||||
}
|
||||
os << "]";
|
||||
NS_LOG_DEBUG ("N2: " << os.str ());
|
||||
}
|
||||
#endif //NS3_LOG_ENABLE
|
||||
|
||||
// 1. Start with an MPR set made of all members of N with
|
||||
// N_willingness equal to WILL_ALWAYS
|
||||
@@ -584,30 +600,37 @@ RoutingProtocol::MprComputation()
|
||||
// 3. Add to the MPR set those nodes in N, which are the *only*
|
||||
// nodes to provide reachability to a node in N2.
|
||||
std::set<Ipv4Address> coveredTwoHopNeighbors;
|
||||
for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin (); twoHopNeigh != N2.end (); twoHopNeigh++)
|
||||
for (TwoHopNeighborSet::const_iterator twoHopNeigh = N2.begin (); twoHopNeigh != N2.end (); twoHopNeigh++)
|
||||
{
|
||||
NeighborSet::const_iterator onlyNeighbor = N.end ();
|
||||
|
||||
for (NeighborSet::const_iterator neighbor = N.begin ();
|
||||
neighbor != N.end (); neighbor++)
|
||||
bool onlyOne = true;
|
||||
// try to find another neighbor that can reach twoHopNeigh->twoHopNeighborAddr
|
||||
for (TwoHopNeighborSet::const_iterator otherTwoHopNeigh = N2.begin (); otherTwoHopNeigh != N2.end (); otherTwoHopNeigh++)
|
||||
{
|
||||
if (neighbor->neighborMainAddr == twoHopNeigh->neighborMainAddr)
|
||||
if (otherTwoHopNeigh->twoHopNeighborAddr == twoHopNeigh->twoHopNeighborAddr
|
||||
&& otherTwoHopNeigh->neighborMainAddr != twoHopNeigh->neighborMainAddr)
|
||||
{
|
||||
if (onlyNeighbor == N.end ())
|
||||
{
|
||||
onlyNeighbor = neighbor;
|
||||
}
|
||||
else
|
||||
{
|
||||
onlyNeighbor = N.end ();
|
||||
break;
|
||||
}
|
||||
onlyOne = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (onlyNeighbor != N.end ())
|
||||
if (onlyOne)
|
||||
{
|
||||
mprSet.insert (onlyNeighbor->neighborMainAddr);
|
||||
coveredTwoHopNeighbors.insert (twoHopNeigh->twoHopNeighborAddr);
|
||||
NS_LOG_LOGIC ("Neighbor " << twoHopNeigh->neighborMainAddr
|
||||
<< " is the only that can reach 2-hop neigh. "
|
||||
<< twoHopNeigh->twoHopNeighborAddr
|
||||
<< " => select as MPR.");
|
||||
|
||||
mprSet.insert (twoHopNeigh->neighborMainAddr);
|
||||
|
||||
// take note of all the 2-hop neighbors reachable by the newly elected MPR
|
||||
for (TwoHopNeighborSet::const_iterator otherTwoHopNeigh = N2.begin ();
|
||||
otherTwoHopNeigh != N2.end (); otherTwoHopNeigh++)
|
||||
{
|
||||
if (otherTwoHopNeigh->neighborMainAddr == twoHopNeigh->neighborMainAddr)
|
||||
{
|
||||
coveredTwoHopNeighbors.insert (otherTwoHopNeigh->twoHopNeighborAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove the nodes from N2 which are now covered by a node in the MPR set.
|
||||
@@ -616,6 +639,7 @@ RoutingProtocol::MprComputation()
|
||||
{
|
||||
if (coveredTwoHopNeighbors.find (twoHopNeigh->twoHopNeighborAddr) != coveredTwoHopNeighbors.end ())
|
||||
{
|
||||
NS_LOG_LOGIC ("2-hop neigh. " << twoHopNeigh->twoHopNeighborAddr << " is already covered by an MPR.");
|
||||
twoHopNeigh = N2.erase (twoHopNeigh);
|
||||
}
|
||||
else
|
||||
@@ -628,6 +652,26 @@ RoutingProtocol::MprComputation()
|
||||
// least one node in the MPR set:
|
||||
while (N2.begin () != N2.end ())
|
||||
{
|
||||
|
||||
#ifdef NS3_LOG_ENABLE
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "[";
|
||||
for (TwoHopNeighborSet::const_iterator iter = N2.begin ();
|
||||
iter != N2.end (); iter++)
|
||||
{
|
||||
TwoHopNeighborSet::const_iterator next = iter;
|
||||
next++;
|
||||
os << iter->neighborMainAddr << "->" << iter->twoHopNeighborAddr;
|
||||
if (next != N2.end ())
|
||||
os << ", ";
|
||||
}
|
||||
os << "]";
|
||||
NS_LOG_DEBUG ("Step 4 iteration: N2=" << os.str ());
|
||||
}
|
||||
#endif //NS3_LOG_ENABLE
|
||||
|
||||
|
||||
// 4.1. For each node in N, calculate the reachability, i.e., the
|
||||
// number of nodes in N2 which are not yet covered by at
|
||||
// least one node in the MPR set, and which are reachable
|
||||
|
||||
159
test.py
159
test.py
@@ -202,7 +202,8 @@ def translate_to_text(results_file, text_file):
|
||||
for example in dom.getElementsByTagName("Example"):
|
||||
result = get_node_text(example.getElementsByTagName("Result")[0])
|
||||
name = get_node_text(example.getElementsByTagName("Name")[0])
|
||||
output = "%s: Example \"%s\"\n" % (result, name)
|
||||
time = get_node_text(example.getElementsByTagName("ElapsedTime")[0])
|
||||
output = "%s: Example \"%s\" (%s)\n" % (result, name, time)
|
||||
f.write(output)
|
||||
|
||||
f.close()
|
||||
@@ -408,12 +409,13 @@ def translate_to_html(results_file, html_file):
|
||||
#
|
||||
# The table headings look like,
|
||||
#
|
||||
# +--------+--------------+
|
||||
# | Result | Example Name |
|
||||
# +--------+--------------+
|
||||
# +--------+--------------+--------------+
|
||||
# | Result | Example Name | Elapsed Time |
|
||||
# +--------+--------------+--------------+
|
||||
#
|
||||
f.write("<th> Result </th>\n")
|
||||
f.write("<th>Example Name</th>\n")
|
||||
f.write("<th>Elapsed Time</th>\n")
|
||||
|
||||
#
|
||||
# Now iterate through all of the examples
|
||||
@@ -430,6 +432,7 @@ def translate_to_html(results_file, html_file):
|
||||
#
|
||||
result = get_node_text(example.getElementsByTagName("Result")[0])
|
||||
name = get_node_text(example.getElementsByTagName("Name")[0])
|
||||
time = get_node_text(example.getElementsByTagName("ElapsedTime")[0])
|
||||
|
||||
#
|
||||
# If the example either failed or crashed, print its result status
|
||||
@@ -447,6 +450,11 @@ def translate_to_html(results_file, html_file):
|
||||
#
|
||||
f.write("<td>%s</td>\n" % name)
|
||||
|
||||
#
|
||||
# Write the elapsed time as a new tag data.
|
||||
#
|
||||
f.write("<td>%s</td>\n" % time)
|
||||
|
||||
#
|
||||
# That's it for the current example, so terminate the row.
|
||||
#
|
||||
@@ -533,37 +541,68 @@ def read_waf_config():
|
||||
# path -- it is cooked up dynamically, so we do that too.
|
||||
#
|
||||
def make_library_path():
|
||||
global LIBRARY_PATH
|
||||
have_DYLD_LIBRARY_PATH = False
|
||||
have_LD_LIBRARY_PATH = False
|
||||
have_PATH = False
|
||||
|
||||
LIBRARY_PATH = "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:'"
|
||||
keys = os.environ.keys()
|
||||
for key in keys:
|
||||
if key == "DYLD_LIBRARY_PATH":
|
||||
have_DYLD_LIBRARY_PATH = True
|
||||
if key == "LD_LIBRARY_PATH":
|
||||
have_LD_LIBRARY_PATH = True
|
||||
if key == "PATH":
|
||||
have_PATH = True
|
||||
|
||||
if sys.platform == "darwin":
|
||||
LIBRARY_PATH = "DYLD_LIBRARY_PATH='"
|
||||
if not have_DYLD_LIBRARY_PATH:
|
||||
os.environ["DYLD_LIBRARY_PATH"] = ""
|
||||
for path in NS3_MODULE_PATH:
|
||||
os.environ["DYLD_LIBRARY_PATH"] += ":" + path
|
||||
if options.verbose:
|
||||
print "os.environ[\"DYLD_LIBRARY_PATH\"] == %s" % os.environ["DYLD_LIBRARY_PATH"]
|
||||
elif sys.platform == "win32":
|
||||
LIBRARY_PATH = "PATH=$PATH:'"
|
||||
if not have_PATH:
|
||||
os.environ["PATH"] = ""
|
||||
for path in NS3_MODULE_PATH:
|
||||
os.environ["PATH"] += ';' + path
|
||||
if options.verbose:
|
||||
print "os.environ[\"PATH\"] == %s" % os.environ["PATH"]
|
||||
elif sys.platform == "cygwin":
|
||||
LIBRARY_PATH = "PATH=$PATH:'"
|
||||
|
||||
for path in NS3_MODULE_PATH:
|
||||
LIBRARY_PATH = LIBRARY_PATH + path + ":"
|
||||
|
||||
LIBRARY_PATH = LIBRARY_PATH + "'"
|
||||
|
||||
if options.verbose:
|
||||
print "LIBRARY_PATH == %s" % LIBRARY_PATH
|
||||
if not have_PATH:
|
||||
os.environ["PATH"] = ""
|
||||
for path in NS3_MODULE_PATH:
|
||||
os.environ["PATH"] += ":" + path
|
||||
if options.verbose:
|
||||
print "os.environ[\"PATH\"] == %s" % os.environ["PATH"]
|
||||
else:
|
||||
if not have_LD_LIBRARY_PATH:
|
||||
os.environ["LD_LIBRARY_PATH"] = ""
|
||||
for path in NS3_MODULE_PATH:
|
||||
os.environ["LD_LIBRARY_PATH"] += ":" + path
|
||||
if options.verbose:
|
||||
print "os.environ[\"LD_LIBRARY_PATH\"] == %s" % os.environ["LD_LIBRARY_PATH"]
|
||||
|
||||
def run_job_synchronously(shell_command, directory, valgrind):
|
||||
path_cmd = os.path.join (NS3_BUILDDIR, NS3_ACTIVE_VARIANT, shell_command)
|
||||
if valgrind:
|
||||
cmd = "%s valgrind --leak-check=full --error-exitcode=2 %s/%s/%s" % (LIBRARY_PATH, NS3_BUILDDIR, NS3_ACTIVE_VARIANT, shell_command)
|
||||
cmd = "valgrind --leak-check=full --error-exitcode=2 %s" % path_cmd
|
||||
else:
|
||||
cmd = "%s %s/%s/%s" % (LIBRARY_PATH, NS3_BUILDDIR, NS3_ACTIVE_VARIANT, shell_command)
|
||||
cmd = path_cmd
|
||||
|
||||
if options.verbose:
|
||||
print "Synchronously execute %s" % cmd
|
||||
|
||||
proc = subprocess.Popen(cmd, shell=True, cwd=directory, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
start_time = time.time()
|
||||
proc = subprocess.Popen(cmd, shell = True, cwd = directory, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout_results, stderr_results = proc.communicate()
|
||||
return (proc.returncode, stdout_results, stderr_results)
|
||||
elapsed_time = time.time() - start_time
|
||||
|
||||
if options.verbose:
|
||||
print "Return code = ", proc.returncode
|
||||
print "stderr = ", stderr_results
|
||||
|
||||
return (proc.returncode, stdout_results, stderr_results, elapsed_time)
|
||||
|
||||
#
|
||||
# This class defines a unit of testing work. It will typically refer to
|
||||
@@ -580,6 +619,7 @@ class Job:
|
||||
self.cwd = ""
|
||||
self.tmp_file_name = ""
|
||||
self.returncode = False
|
||||
self.elapsed_time = 0
|
||||
|
||||
#
|
||||
# A job is either a standard job or a special job indicating that a worker
|
||||
@@ -659,6 +699,12 @@ class Job:
|
||||
def set_returncode(self, returncode):
|
||||
self.returncode = returncode
|
||||
|
||||
#
|
||||
# The elapsed real time for the job execution.
|
||||
#
|
||||
def set_elapsed_time(self, elapsed_time):
|
||||
self.elapsed_time = elapsed_time
|
||||
|
||||
#
|
||||
# The worker thread class that handles the actual running of a given test.
|
||||
# Once spawned, it receives requests for work through its input_queue and
|
||||
@@ -711,17 +757,19 @@ class worker_thread(threading.Thread):
|
||||
# If we have an example, the shell command is all we need to
|
||||
# know. It will be something like "examples/udp-echo"
|
||||
#
|
||||
(job.returncode, standard_out, standard_err) = run_job_synchronously(job.shell_command, job.cwd,
|
||||
options.valgrind)
|
||||
(job.returncode, standard_out, standard_err, et) = run_job_synchronously(job.shell_command,
|
||||
job.cwd, options.valgrind)
|
||||
else:
|
||||
#
|
||||
# If we're a test suite, we need to provide a little more info
|
||||
# to the test runner, specifically the base directory and temp
|
||||
# file name
|
||||
#
|
||||
(job.returncode, standard_out, standard_err) = run_job_synchronously(job.shell_command +
|
||||
(job.returncode, standard_out, standard_err, et) = run_job_synchronously(job.shell_command +
|
||||
" --basedir=%s --out=%s" % (job.basedir, job.tmp_file_name), job.cwd, options.valgrind)
|
||||
|
||||
job.set_elapsed_time(et)
|
||||
|
||||
if options.verbose:
|
||||
print "returncode = %d" % job.returncode
|
||||
print "---------- beign standard out ----------"
|
||||
@@ -756,11 +804,33 @@ def run_tests():
|
||||
# For example, if the user only wants to run BVT tests, we only have
|
||||
# to build the test-runner and can ignore all of the examples.
|
||||
#
|
||||
# If the user only wants to run a single example, then we can just build
|
||||
# that example.
|
||||
#
|
||||
# If there is no constraint, then we have to build everything since the
|
||||
# user wants to run everything.
|
||||
#
|
||||
if options.kinds or options.list or (len(options.constrain) and options.constrain in core_kinds):
|
||||
proc = subprocess.Popen("./waf --target=test-runner", shell=True)
|
||||
else:
|
||||
proc = subprocess.Popen("./waf", shell=True)
|
||||
if sys.platform == "win32":
|
||||
waf_cmd = "waf --target=test-runner"
|
||||
else:
|
||||
waf_cmd = "./waf --target=test-runner"
|
||||
elif len(options.example):
|
||||
if sys.platform == "win32":
|
||||
waf_cmd = "waf --target=%s" % os.path.basename(options.example)
|
||||
else:
|
||||
waf_cmd = "./waf --target=%s" % os.path.basename(options.example)
|
||||
|
||||
else:
|
||||
if sys.platform == "win32":
|
||||
waf_cmd = "waf"
|
||||
else:
|
||||
waf_cmd = "./waf"
|
||||
|
||||
if options.verbose:
|
||||
print "Building: %s" % waf_cmd
|
||||
|
||||
proc = subprocess.Popen(waf_cmd, shell = True)
|
||||
proc.communicate()
|
||||
|
||||
#
|
||||
@@ -779,11 +849,13 @@ def run_tests():
|
||||
# handle them without doing all of the hard work.
|
||||
#
|
||||
if options.kinds:
|
||||
(rc, standard_out, standard_err) = run_job_synchronously("utils/test-runner --kinds", os.getcwd(), False)
|
||||
path_cmd = os.path.join("utils", "test-runner --kinds")
|
||||
(rc, standard_out, standard_err, et) = run_job_synchronously(path_cmd, os.getcwd(), False)
|
||||
print standard_out
|
||||
|
||||
if options.list:
|
||||
(rc, standard_out, standard_err) = run_job_synchronously("utils/test-runner --list", os.getcwd(), False)
|
||||
path_cmd = os.path.join("utils", "test-runner --list")
|
||||
(rc, standard_out, standard_err, et) = run_job_synchronously(path_cmd, os.getcwd(), False)
|
||||
print standard_out
|
||||
|
||||
if options.kinds or options.list:
|
||||
@@ -854,10 +926,11 @@ def run_tests():
|
||||
suites = options.suite + "\n"
|
||||
elif len(options.example) == 0:
|
||||
if len(options.constrain):
|
||||
(rc, suites, standard_err) = run_job_synchronously("utils/test-runner --list --constrain=%s" %
|
||||
options.constrain, os.getcwd(), False)
|
||||
path_cmd = os.path.join("utils", "test-runner --list --constrain=%s" % options.constrain)
|
||||
(rc, suites, standard_err, et) = run_job_synchronously(path_cmd, os.getcwd(), False)
|
||||
else:
|
||||
(rc, suites, standard_err) = run_job_synchronously("utils/test-runner --list", os.getcwd(), False)
|
||||
path_cmd = os.path.join("utils", "test-runner --list")
|
||||
(rc, suites, standard_err, et) = run_job_synchronously(path_cmd, os.getcwd(), False)
|
||||
else:
|
||||
suites = ""
|
||||
|
||||
@@ -888,13 +961,14 @@ def run_tests():
|
||||
#
|
||||
processors = 1
|
||||
|
||||
if 'SC_NPROCESSORS_ONLN'in os.sysconf_names:
|
||||
processors = os.sysconf('SC_NPROCESSORS_ONLN')
|
||||
else:
|
||||
proc = subprocess.Popen("sysctl -n hw.ncpu", shell = True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout_results, stderr_results = proc.communicate()
|
||||
if len(stderr_results) == 0:
|
||||
processors = int(stdout_results)
|
||||
if sys.platform != "win32":
|
||||
if 'SC_NPROCESSORS_ONLN'in os.sysconf_names:
|
||||
processors = os.sysconf('SC_NPROCESSORS_ONLN')
|
||||
else:
|
||||
proc = subprocess.Popen("sysctl -n hw.ncpu", shell = True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout_results, stderr_results = proc.communicate()
|
||||
if len(stderr_results) == 0:
|
||||
processors = int(stdout_results)
|
||||
|
||||
#
|
||||
# Now, spin up one thread per processor which will eventually mean one test
|
||||
@@ -922,6 +996,7 @@ def run_tests():
|
||||
# PASS, FAIL, CRASH and SKIP processing is done in the same place.
|
||||
#
|
||||
for test in suite_list:
|
||||
test = test.strip()
|
||||
if len(test):
|
||||
job = Job()
|
||||
job.set_is_example(False)
|
||||
@@ -934,7 +1009,8 @@ def run_tests():
|
||||
else:
|
||||
multiple = ""
|
||||
|
||||
job.set_shell_command("utils/test-runner --suite='%s'%s" % (test, multiple))
|
||||
path_cmd = os.path.join("utils", "test-runner --suite=%s%s" % (test, multiple))
|
||||
job.set_shell_command(path_cmd)
|
||||
|
||||
if options.valgrind and test in core_valgrind_skip_tests:
|
||||
job.set_is_skip(True)
|
||||
@@ -1108,6 +1184,7 @@ def run_tests():
|
||||
else:
|
||||
f.write(' <Result>CRASH</Result>\n')
|
||||
|
||||
f.write(' <ElapsedTime>%.3f</ElapsedTime>\n' % job.elapsed_time)
|
||||
f.write('</Example>\n')
|
||||
f.close()
|
||||
|
||||
@@ -1167,7 +1244,7 @@ def run_tests():
|
||||
else:
|
||||
if job.returncode == 0 or job.returncode == 1 or job.returncode == 2:
|
||||
f_to = open(xml_results_file, 'a')
|
||||
f_from = open(job.tmp_file_name, 'r')
|
||||
f_from = open(job.tmp_file_name)
|
||||
f_to.write(f_from.read())
|
||||
f_to.close()
|
||||
f_from.close()
|
||||
|
||||
@@ -248,7 +248,7 @@ runBench (void (*bench) (uint32_t), uint32_t n, char const *name)
|
||||
SystemWallClockMs time;
|
||||
time.Start ();
|
||||
(*bench) (n);
|
||||
unsigned long long deltaMs = time.End ();
|
||||
uint64_t deltaMs = time.End ();
|
||||
double ps = n;
|
||||
ps *= 1000;
|
||||
ps /= deltaMs;
|
||||
|
||||
30
wscript
30
wscript
@@ -194,8 +194,13 @@ def set_options(opt):
|
||||
help=('Compile NS-3 statically: works only on linux, without python'),
|
||||
dest='enable_static', action='store_true',
|
||||
default=False)
|
||||
opt.add_option('--doxygen-no-build',
|
||||
help=('Run doxygen to generate html documentation from source comments, '
|
||||
'but do not wait for ns-3 to finish the full build.'),
|
||||
action="store_true", default=False,
|
||||
dest='doxygen_no_build')
|
||||
|
||||
# options provided in a script in a subdirectory named "src"
|
||||
# options provided in subdirectories
|
||||
opt.sub_options('src')
|
||||
opt.sub_options('bindings/python')
|
||||
opt.sub_options('src/internet-stack')
|
||||
@@ -282,13 +287,14 @@ def configure(conf):
|
||||
env.append_value('CXXDEFINES', 'NS3_ASSERT_ENABLE')
|
||||
env.append_value('CXXDEFINES', 'NS3_LOG_ENABLE')
|
||||
|
||||
if Options.options.build_profile == 'release':
|
||||
env.append_value('CXXFLAGS', '-fomit-frame-pointer')
|
||||
env.append_value('CXXFLAGS', '-march=native')
|
||||
|
||||
env['PLATFORM'] = sys.platform
|
||||
|
||||
if conf.env['CXX_NAME'] in ['gcc', 'icc']:
|
||||
if Options.options.build_profile == 'release':
|
||||
env.append_value('CXXFLAGS', '-fomit-frame-pointer')
|
||||
if conf.check_compilation_flag('-march=native'):
|
||||
env.append_value('CXXFLAGS', '-march=native')
|
||||
|
||||
if sys.platform == 'win32':
|
||||
env.append_value("LINKFLAGS", "-Wl,--enable-runtime-pseudo-reloc")
|
||||
elif sys.platform == 'cygwin':
|
||||
@@ -595,6 +601,11 @@ def build(bld):
|
||||
raise Utils.WafError("Cannot run regression tests: building the ns-3 examples is not enabled"
|
||||
" (regression tests are based on examples)")
|
||||
|
||||
|
||||
if Options.options.doxygen_no_build:
|
||||
_doxygen(bld)
|
||||
raise SystemExit(0)
|
||||
|
||||
def shutdown(ctx):
|
||||
bld = wutils.bld
|
||||
if wutils.bld is None:
|
||||
@@ -711,9 +722,7 @@ def shell(ctx):
|
||||
env = wutils.bld.env
|
||||
wutils.run_argv([shell], env, {'NS3_MODULE_PATH': os.pathsep.join(env['NS3_MODULE_PATH'])})
|
||||
|
||||
def doxygen(bld):
|
||||
"""do a full build, generate the introspected doxygen and then the doxygen"""
|
||||
Scripting.build(bld)
|
||||
def _doxygen(bld):
|
||||
env = wutils.bld.env
|
||||
proc_env = wutils.get_proc_env()
|
||||
|
||||
@@ -735,6 +744,11 @@ def doxygen(bld):
|
||||
if subprocess.Popen(['doxygen', doxygen_config]).wait():
|
||||
raise SystemExit(1)
|
||||
|
||||
def doxygen(bld):
|
||||
"""do a full build, generate the introspected doxygen and then the doxygen"""
|
||||
Scripting.build(bld)
|
||||
_doxygen(bld)
|
||||
|
||||
def lcov_report():
|
||||
env = Build.bld.env
|
||||
variant_name = env['NS3_ACTIVE_VARIANT']
|
||||
|
||||
Reference in New Issue
Block a user