Merge with ns-3-dev.
authorSebastien Vincent <vincent@clarinet.u-strasbg.fr>
Mon, 02 Nov 2009 18:16:09 +0100
changeset 5799 8a1263190943
parent 5798 885f42e6bc8f (current diff)
parent 5472 5800fd778af9 (diff)
child 5800 082bd197b99a
Merge with ns-3-dev.
--- a/examples/mesh/mesh.cc	Mon Nov 02 18:08:16 2009 +0100
+++ b/examples/mesh/mesh.cc	Mon Nov 02 18:16:09 2009 +0100
@@ -158,7 +158,16 @@
    * 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);
--- a/src/common/pcap-file-test-suite.cc	Mon Nov 02 18:08:16 2009 +0100
+++ b/src/common/pcap-file-test-suite.cc	Mon Nov 02 18:16:09 2009 +0100
@@ -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 @@
   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 @@
   AddTestCase (new FileHeaderTestCase);
   AddTestCase (new RecordHeaderTestCase);
   AddTestCase (new ReadFileTestCase);
+  AddTestCase (new DiffTestCase);
 }
 
 PcapFileTestSuite pcapFileTestSuite;
--- a/src/common/pcap-file.cc	Mon Nov 02 18:08:16 2009 +0100
+++ b/src/common/pcap-file.cc	Mon Nov 02 18:16:09 2009 +0100
@@ -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 @@
   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
--- a/src/common/pcap-file.h	Mon Nov 02 18:08:16 2009 +0100
+++ b/src/common/pcap-file.h	Mon Nov 02 18:16:09 2009 +0100
@@ -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 @@
    * 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 @@
              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 @@
   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 {
--- a/src/core/system-wall-clock-ms.h	Mon Nov 02 18:08:16 2009 +0100
+++ b/src/core/system-wall-clock-ms.h	Mon Nov 02 18:16:09 2009 +0100
@@ -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 @@
    */
   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
+   * after this method returns.
+   *
+   * Returns int64_t to avoid dependency on clock_t in ns-3 code.
+   */
+  int64_t End (void);
+
+  /**
+   * \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
-   * after this method returns.
+   * 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.
    */
-  unsigned long long End (void);
+  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;
 };
--- a/src/core/test.cc	Mon Nov 02 18:08:16 2009 +0100
+++ b/src/core/test.cc	Mon Nov 02 18:16:09 2009 +0100
@@ -262,7 +262,7 @@
 void
 TestCase::DoReportStart  (void)
 {
-  m_startTime = times (&m_startTimes);
+  m_msClock.Start ();
 
   if (m_ofs == 0)
     {
@@ -319,26 +319,21 @@
 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 @@
 void
 TestSuite::DoReportStart (void)
 {
-  m_startTime = times (&m_startTimes);
-
+  m_msClock.Start ();
+  
   if (m_ofs == 0)
     {
       return;
@@ -556,25 +551,21 @@
 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;
--- a/src/core/test.h	Mon Nov 02 18:08:16 2009 +0100
+++ b/src/core/test.h	Mon Nov 02 18:16:09 2009 +0100
@@ -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 @@
   TestCase (TestCase& tc);
   TestCase& operator= (TestCase& tc);
 
+  SystemWallClockMs m_msClock;
   std::string m_name;
   bool m_verbose;
   bool m_continueOnFailure;
@@ -828,8 +832,6 @@
   std::string m_basedir;
   std::ofstream *m_ofs;
   bool m_error;
-  clock_t m_startTime;
-  struct tms m_startTimes;
 };
 
 /**
@@ -1057,6 +1059,7 @@
   TestSuite (TestSuite& ts);
   TestSuite& operator= (TestSuite& ts);
 
+  SystemWallClockMs m_msClock;
   std::string m_name;
   bool m_verbose;
   bool m_continueOnFailure;
@@ -1064,10 +1067,7 @@
   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;
 };
--- a/src/core/unix-system-wall-clock-ms.cc	Mon Nov 02 18:08:16 2009 +0100
+++ b/src/core/unix-system-wall-clock-ms.cc	Mon Nov 02 18:16:09 2009 +0100
@@ -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 @@
 {
   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
--- a/src/core/win32-system-wall-clock-ms.cc	Mon Nov 02 18:08:16 2009 +0100
+++ b/src/core/win32-system-wall-clock-ms.cc	Mon Nov 02 18:16:09 2009 +0100
@@ -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 @@
 {
   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
--- a/src/devices/mesh/dot11s/hwmp-protocol.cc	Mon Nov 02 18:08:16 2009 +0100
+++ b/src/devices/mesh/dot11s/hwmp-protocol.cc	Mon Nov 02 18:16:09 2009 +0100
@@ -320,7 +320,7 @@
 {
   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 @@
                   preq.GetOriginatorSeqNumber ()
                   );
               ProactivePathResolved ();
+              m_rtable->AddReactivePath (
+                  preq.GetOriginatorAddress (),
+                  from,
+                  interface,
+                  preq.GetMetric (),
+                  MicroSeconds (preq.GetLifetime () * 1024),
+                  preq.GetOriginatorSeqNumber ()
+                  );
+              ReactivePathResolved (preq.GetOriginatorAddress ());
             }
           if (!preq.IsNeedNotPrep ())
             {
@@ -611,11 +620,6 @@
     }
   if (result.retransmitter == Mac48Address::GetBroadcast ())
     {
-      //try to look for default route
-      result = m_rtable->LookupProactive ();
-    }
-  if (result.retransmitter == Mac48Address::GetBroadcast ())
-    {
       return;
     }
   //Forward PREP
@@ -1008,7 +1012,6 @@
   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
--- a/src/devices/mesh/dot11s/peer-management-protocol.h	Mon Nov 02 18:08:16 2009 +0100
+++ b/src/devices/mesh/dot11s/peer-management-protocol.h	Mon Nov 02 18:16:09 2009 +0100
@@ -78,6 +78,7 @@
    * \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);
   //\}
--- a/src/devices/mesh/flame/flame-protocol-mac.cc	Mon Nov 02 18:08:16 2009 +0100
+++ b/src/devices/mesh/flame/flame-protocol-mac.cc	Mon Nov 02 18:16:09 2009 +0100
@@ -31,6 +31,8 @@
 }
 FlameProtocolMac::~FlameProtocolMac ()
 {
+  m_protocol = 0;
+  m_parent = 0;
 }
 void
 FlameProtocolMac::SetParent (Ptr<MeshWifiInterfaceMac> parent)
--- a/src/devices/mesh/flame/flame-protocol.cc	Mon Nov 02 18:08:16 2009 +0100
+++ b/src/devices/mesh/flame/flame-protocol.cc	Mon Nov 02 18:16:09 2009 +0100
@@ -127,7 +127,7 @@
   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 @@
 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 @@
                   m_stats.totalDropped++;
                   return false;
                 }
+              tag.receiver = result.retransmitter;
             }
-          tag.receiver = result.retransmitter;
+          else
+            {
+              tag.receiver = Mac48Address::GetBroadcast ();
+            }
           if (result.retransmitter == Mac48Address::GetBroadcast ())
             {
               m_stats.txBroadcast++;
@@ -262,19 +269,21 @@
     }
   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
--- a/src/helper/qos-wifi-mac-helper.cc	Mon Nov 02 18:08:16 2009 +0100
+++ b/src/helper/qos-wifi-mac-helper.cc	Mon Nov 02 18:16:09 2009 +0100
@@ -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 @@
                                           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 @@
       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);
+    }
 }
 
 
--- a/src/routing/olsr/olsr-routing-protocol.cc	Mon Nov 02 18:08:16 2009 +0100
+++ b/src/routing/olsr/olsr-routing-protocol.cc	Mon Nov 02 18:16:09 2009 +0100
@@ -552,7 +552,23 @@
         }
     }
 
-  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,31 +600,38 @@
   // 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 ())
+              onlyOne = false;
+              break;
+            }
+        }
+      if (onlyOne)
+        {
+          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)
                 {
-                  onlyNeighbor = neighbor;
-                }
-              else
-                {
-                  onlyNeighbor = N.end ();
-                  break;
+                  coveredTwoHopNeighbors.insert (otherTwoHopNeigh->twoHopNeighborAddr);
                 }
             }
         }
-      if (onlyNeighbor != N.end ())
-        {
-          mprSet.insert (onlyNeighbor->neighborMainAddr);
-          coveredTwoHopNeighbors.insert (twoHopNeigh->twoHopNeighborAddr);
-        }
     }
   // Remove the nodes from N2 which are now covered by a node in the MPR set.
   for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin ();
@@ -616,6 +639,7 @@
     {
       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 @@
   // 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
--- a/test.py	Mon Nov 02 18:08:16 2009 +0100
+++ b/test.py	Mon Nov 02 18:16:09 2009 +0100
@@ -202,7 +202,8 @@
     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 @@
     #
     # 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 @@
         #
         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
@@ -448,6 +451,11 @@
         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.
         #
         f.write("</tr>\n")
@@ -533,37 +541,68 @@
 # 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 @@
         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 @@
     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 @@
                     # 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 @@
         # 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)
+            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:
-            proc = subprocess.Popen("./waf", shell=True)
+            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 @@
     # 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 @@
         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 @@
     #
     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 @@
     # 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 @@
             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 @@
             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 @@
             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()
--- a/utils/bench-packets.cc	Mon Nov 02 18:08:16 2009 +0100
+++ b/utils/bench-packets.cc	Mon Nov 02 18:16:09 2009 +0100
@@ -248,7 +248,7 @@
   SystemWallClockMs time;
   time.Start ();
   (*bench) (n);
-  unsigned long long deltaMs = time.End ();
+  uint64_t deltaMs = time.End ();
   double ps = n;
   ps *= 1000;
   ps /= deltaMs;
--- a/wscript	Mon Nov 02 18:08:16 2009 +0100
+++ b/wscript	Mon Nov 02 18:16:09 2009 +0100
@@ -194,8 +194,13 @@
                    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 @@
         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 @@
             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 @@
     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 @@
     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']