Index: .hgignore
===================================================================
--- a/.hgignore
+++ b/.hgignore
@@ -17,6 +17,7 @@
^\.waf
^doc/introspected-doxygen\.h$
.*\.py[co]$
+\.json$
\.pcap$
\.mob$
\.routes$
Index: CHANGES.html
===================================================================
--- a/CHANGES.html
+++ b/CHANGES.html
@@ -75,6 +75,11 @@
A new class SpectrumWifiPhy has been introduced that makes use of the Spectrum module. Its functionality and API is currently very similar to that of the YansWifiPhy, especially because it reuses the same InterferenceHelper and ErrorModel classes (for this release). Some example programs in the 'examples/wireless/' directory, such as 'wifi-spectrum-per-example.cc', illustrate how the SpectrumWifiPhy class can be substituted for the default YansWifiPhy PHY model.
+ We have added support for generating traces for the
+Initialize (argc, argv);
+#endif
+
}
void
Index: src/core/model/des-metrics.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/core/model/des-metrics.cc
@@ -0,0 +1,157 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2016 LLNL
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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: Peter D. Barnes, Jr.
+ */
+
+
+/**
+ * @file
+ * @ingroup simulator
+ * ns3::DesMetrics implementation.
+ */
+
+#include "des-metrics.h"
+#include "simulator.h"
+#include "system-path.h"
+
+#include // time_t, time()
+#include
+#include
+
+namespace ns3 {
+
+/* static */
+std::string DesMetrics::m_outputDir; // = "";
+
+void
+DesMetrics::Initialize (int argc, char * argv[], std::string outDir /* = "" */ )
+{
+ if (m_initialized)
+ {
+ // Running multiple tests, so close the previous output file
+ Close ();
+ }
+
+ m_initialized = true;
+
+ std::string model_name ("desTraceFile");
+ if (argc)
+ {
+ std::string arg0 = argv[0];
+ model_name = SystemPath::Split (arg0).back ();
+ }
+ std::string jsonFile = model_name + ".json";
+ if (outDir != "")
+ {
+ DesMetrics::m_outputDir = outDir;
+ }
+ if (DesMetrics::m_outputDir != "")
+ {
+ jsonFile = SystemPath::Append (DesMetrics::m_outputDir, jsonFile);
+ }
+
+ time_t current_time;
+ time (¤t_time);
+ const char * date = ctime (¤t_time);
+ std::string capture_date (date, 24); // discard trailing newline from ctime
+
+ m_os.open (jsonFile.c_str ());
+ m_os << "{" << std::endl;
+ m_os << " \"simulator_name\" : \"ns-3\"," << std::endl;
+ m_os << " \"model_name\" : \"" << model_name << "\"," << std::endl;
+ m_os << " \"capture_date\" : \"" << capture_date << "\"," << std::endl;
+ m_os << " \"command_line_arguments\" : \"";
+ if (argc)
+ {
+ for (int i = 0; i < argc; ++i)
+ {
+ if (i > 0) m_os << " ";
+ m_os << argv[i];
+ }
+ }
+ else
+ {
+ m_os << "[argv empty or not available]";
+ }
+ m_os << "\"," << std::endl;
+ m_os << " \"events\" : [" << std::endl;
+
+ m_separator = ' ';
+
+}
+
+void
+DesMetrics::Trace (const Time & now, const Time & delay)
+{
+ TraceWithContext (Simulator::GetContext (), now, delay);
+}
+
+void
+DesMetrics::TraceWithContext (uint32_t context, const Time & now, const Time & delay)
+{
+ if (!m_initialized)
+ {
+ Initialize (0, 0);
+ }
+
+ std::ostringstream ss;
+ if (m_separator == ',')
+ {
+ ss << m_separator << std::endl;
+ }
+
+ uint32_t sendCtx = Simulator::GetContext ();
+ // Force to signed so we can show NoContext as '-1'
+ int32_t send = (sendCtx != Simulator::NO_CONTEXT) ? (int32_t)sendCtx : -1;
+ int32_t recv = (context != Simulator::NO_CONTEXT) ? (int32_t)context : -1;
+
+ ss << " [\""
+ << send << "\",\""
+ << now.GetTimeStep () << "\",\""
+ << recv << "\",\""
+ << (now + delay).GetTimeStep () << "\"]";
+
+ {
+ CriticalSection cs (m_mutex);
+ m_os << ss.str ();
+ }
+
+ m_separator = ',';
+}
+
+DesMetrics::~DesMetrics (void)
+{
+ Close ();
+}
+
+void
+DesMetrics::Close (void)
+{
+ m_os << std::endl; // Finish the last event line
+
+ m_os << " ]" << std::endl;
+ m_os << "}" << std::endl;
+ m_os.close ();
+
+ m_initialized = false;
+}
+
+
+
+} // namespace ns3
+
Index: src/core/model/des-metrics.h
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/core/model/des-metrics.h
@@ -0,0 +1,170 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2016 LLNL
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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: Peter D. Barnes, Jr.
+ */
+
+#ifndef DESMETRICS_H
+#define DESMETRICS_H
+
+/**
+ * @file
+ * @ingroup simulator
+ * ns3::DesMetrics declaration.
+ */
+
+#include "nstime.h"
+#include "singleton.h"
+#include "system-mutex.h"
+
+#include // uint32_t
+#include
+#include
+
+namespace ns3 {
+
+/**
+ * @ingroup simulator
+ *
+ * @brief Event trace data collector for the DES Metrics project.
+ *
+ * This feature generates a JSON file with event trace data,
+ * including the source and destination context for each
+ * event, and the (virtual) times when the event was scheduled and
+ * when it will execute.
+ *
+ * See the DES Metrics Project page: https://wilseypa.github.io/desMetrics/
+ * for more information and analysis tools.
+ *
+ * If enabled (see below), ns-3 scripts should use CommandLine to
+ * parse arguments, which will open the JSON file with the same name
+ * as the script, and write the JSON header. Failure to use CommandLine when
+ * DES Metrics is enabled will put the trace data in the file
+ * \c desTraceFile.json instead. All examples accessible from \c test.py
+ * use CommandLine, and so generate JSON files.
+ *
+ * Output from scripts ends up in the current working directory (normally the
+ * top level directory). When \c test.py is used to run tests or examples
+ * the trace files are generated in a time-stamped subdirectory of
+ * \c testpy-output/, which \c test.py normally deletes.
+ * To keep the output of examples, use the \c --retain argument to \c test.py.
+ *
+ * The output file has the following form:
+ * \verbatim
+{
+ "simulator_name" : "ns-3",
+ "model_name" : "ipv4-raw",
+ "capture_date" : "Fri May 27 00:34:27 2016",
+ "command_line_arguments" : "ipv4-raw [ns3-dev-test-runner-debug] --test-name=ipv4-raw --stop-on-failure --fullness=QUICK --xml --tempdir=testpy-output/2016-05-27-04-33-35-CUT --out=testpy-output/2016-05-27-04-33-35-CUT/ipv4-raw.xml",
+ "events" : [
+ ["0",0,"0",0],
+ ["1",0,"0",0],
+ ["0",0,"0",0],
+ ...
+ ["0",0,"0",0]
+ ]
+} \endverbatim
+ * The first few fields are self-explanatory. The \c event record consists of
+ * the source context, the event send time, the destination context,
+ * and the event execution time. Times are given in the
+ * current Time resolution.
+ *
+ * Enabling DES Metrics
+ *
+ * Enable DES Metrics at configure time with
+ * \verbatim
+ $ waf configure ... --enable-des-metrics \endverbatim
+ *
+ * Working with DES Metrics
+ *
+ * Some useful shell pipelines:
+ *
+ * \li Run everything, retaining the results directory:
+ * \code ./test.py --nowaf --retain \endcode
+ * \li Example traces end up in \c testpy-output/, so move there:
+ * \code cd testpy-output/$(date +"%F")*_/ \endcode
+ * (Remove the `_', which is to work around a Doxygen limitation.)
+ * \li Remove the traces with less than 10 events:
+ * \code wc -l *.json | sort -nr | grep "^ *[789] " | cut -d ' ' -f 9 | xargs rm -f \endcode
+ * \li Show the largest file, and total number of trace files:
+ * \code wc -l *.json | sort -n | tail -2 \endcode
+ *
+ */
+class DesMetrics : public Singleton
+{
+public:
+
+ /**
+ * Open the DesMetrics trace file and print the header.
+ *
+ * The trace file will have the same base name as the main program,
+ * '.json' as the extension.
+ *
+ * \param argc [in] Command line argument count.
+ * \param argv [in] Command line arguments.
+ * \param outDir [in] Directory where the trace file should be written.
+ */
+ void Initialize (int argc, char * argv[], std::string outDir = "");
+
+ /**
+ * Trace an event to self at the time it is scheduled.
+ *
+ * \param now [in] The local simulation time.
+ * \param delay [in] The delay to the event.
+ */
+ void Trace (const Time & now, const Time & delay);
+
+ /**
+ * Trace an event (with context) at the time it is scheduled.
+ *
+ * \param context [in] The context (NodeId) which will receive the event.
+ * \param now [in] The local simulation time.
+ * \param delay [in] The delay to the event.
+ */
+ void TraceWithContext (uint32_t context, const Time & now, const Time & delay);
+
+ /**
+ * Destructor, closes the trace file.
+ */
+ ~DesMetrics (void);
+
+private:
+
+ /** Close the output file. */
+ void Close (void);
+
+ /**
+ * Cache the last-used output directory.
+ *
+ * This is enables repeated/re-entrant use of CommandLine, for example
+ * in \c command-line-test-suite.cc
+ */
+ static std::string m_outputDir;
+
+ bool m_initialized; //!< Have we been initialized.
+ std::ofstream m_os; //!< The output json trace file stream.
+ char m_separator; //!< The separator between event records.
+
+ /** Mutex to control access to the output file. */
+ SystemMutex m_mutex;
+
+}; // class DesMetrics
+
+
+} // namespace ns3
+
+#endif /* DESMETRICS_H */
Index: src/core/model/simulator.cc
===================================================================
--- a/src/core/model/simulator.cc
+++ b/src/core/model/simulator.cc
@@ -23,6 +23,7 @@
#include "scheduler.h"
#include "map-scheduler.h"
#include "event-impl.h"
+#include "des-metrics.h"
#include "ptr.h"
#include "string.h"
@@ -249,6 +250,9 @@
void
Simulator::ScheduleWithContext (uint32_t context, const Time &delay, EventImpl *impl)
{
+#ifdef ENABLE_DES_METRICS
+ DesMetrics::Get ()->TraceWithContext (context, Now (), delay);
+#endif
return GetImpl ()->ScheduleWithContext (context, delay, impl);
}
EventId
@@ -259,11 +263,17 @@
EventId
Simulator::DoSchedule (Time const &time, EventImpl *impl)
{
+#ifdef ENABLE_DES_METRICS
+ DesMetrics::Get ()->Trace (Now (), time);
+#endif
return GetImpl ()->Schedule (time, impl);
}
EventId
Simulator::DoScheduleNow (EventImpl *impl)
{
+#ifdef ENABLE_DES_METRICS
+ DesMetrics::Get ()->Trace (Now (), Time (0));
+#endif
return GetImpl ()->ScheduleNow (impl);
}
EventId
Index: src/core/model/test.cc
===================================================================
--- a/src/core/model/test.cc
+++ b/src/core/model/test.cc
@@ -22,6 +22,7 @@
#include "singleton.h"
#include "system-path.h"
#include "log.h"
+#include "des-metrics.h"
#include
#include
#include
@@ -1065,6 +1066,31 @@
{
TestCase *test = *i;
+#ifdef ENABLE_DES_METRICS
+ {
+ /*
+ Reorganize argv
+ Since DES Metrics uses argv[0] for the trace file name,
+ grab the test name and put it in argv[0],
+ with test-runner as argv[1]
+ then the rest of the original arguments.
+ */
+ std::string testname = test->GetName ();
+ std::string runner = "[" + SystemPath::Split (argv[0]).back () + "]";
+
+ int desargc = argc + 1;
+ char ** desargv = new char * [desargc];
+ desargv[0] = const_cast(testname.c_str ());
+ desargv[1] = const_cast(runner.c_str ());
+ for (int i = 2; i < desargc; ++i)
+ {
+ desargv[i] = argv[i - 1];
+ }
+ DesMetrics::Get ()->Initialize (desargc, desargv, m_tempDir);
+ delete [] desargv;
+ }
+#endif
+
test->Run (this);
PrintReport (test, os, xml, 0);
if (test->IsFailed ())
Index: src/core/wscript
===================================================================
--- a/src/core/wscript
+++ b/src/core/wscript
@@ -187,6 +187,7 @@
'model/hash-murmur3.cc',
'model/hash-fnv.cc',
'model/hash.cc',
+ 'model/des-metrics.cc',
]
core_test = bld.create_ns3_module_test_library('core')
@@ -299,6 +300,7 @@
'model/valgrind.h',
'model/non-copyable.h',
'model/build-profile.h',
+ 'model/des-metrics.h',
]
if sys.platform == 'win32':
Index: src/mpi/wscript
===================================================================
--- a/src/mpi/wscript
+++ b/src/mpi/wscript
@@ -27,7 +27,7 @@
# Bug #2437, using OpenMPI 1.6.5 (possibly later versions)
# if upstream OpenMPI bug clears at some point, this
# can be removed
- conf.env.append_value('CXXFLAGS', '-Wno-literal-suffix')
+ # conf.env.append_value('CXXFLAGS', '-Wno-literal-suffix')
conf.report_optional_feature("mpi", "MPI Support", True, '')
else:
conf.report_optional_feature("mpi", "MPI Support", False, 'mpic++ not found')
Index: wscript
===================================================================
--- a/wscript
+++ b/wscript
@@ -232,6 +232,10 @@
'but do not wait for ns-3 to finish the full build.'),
action="store_true", default=False,
dest='doxygen_no_build')
+ opt.add_option('--enable-des-metrics',
+ help=('Log all events in a json file with the name of the executable (which must call CommandLine::Parse(argc, argv)'),
+ action="store_true", default=False,
+ dest='enable_desmetrics')
# options provided in subdirectories
opt.recurse('src')
@@ -556,6 +560,13 @@
conf.report_optional_feature("libgcrypt", "Gcrypt library",
conf.env.HAVE_GCRYPT, "libgcrypt not found: you can use libgcrypt-config to find its location.")
+ why_not_desmetrics = "defaults to disabled"
+ if Options.options.enable_desmetrics:
+ conf.env['ENABLE_DES_METRICS'] = True
+ env.append_value('DEFINES', 'ENABLE_DES_METRICS')
+ why_not_desmetrics = "option --enable-des-metrics selected"
+ conf.report_optional_feature("DES Metrics", "DES Metrics event collection", conf.env['ENABLE_DES_METRICS'], why_not_desmetrics)
+
# for compiling C code, copy over the CXX* flags
conf.env.append_value('CCFLAGS', conf.env['CXXFLAGS'])