Merge with ns-3-dev.

This commit is contained in:
Sebastien Vincent
2009-11-02 18:16:09 +01:00
18 changed files with 689 additions and 163 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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 {

View File

@@ -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;
};

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
//\}

View File

@@ -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)

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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
View File

@@ -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()

View File

@@ -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
View File

@@ -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']