Skip to content

Commit 8d71603

Browse files
author
Peter D. Barnes, Jr.
committedSep 3, 2016
DES Metrics implementation.
1 parent 38632b0 commit 8d71603

11 files changed

+393
-0
lines changed
 

‎.hgignore

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
^\.waf
1818
^doc/introspected-doxygen\.h$
1919
.*\.py[co]$
20+
\.json$
2021
\.pcap$
2122
\.mob$
2223
\.routes$

‎CHANGES.html

+5
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ <h2>New API:</h2>
7575
</li>
7676
<li> A new class <b>SpectrumWifiPhy</b> 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.
7777
</li>
78+
<li> We have added support for generating traces for the
79+
<a href="https://wilseypa.github.io/desMetrics/>DES Metrics</a> project.
80+
These can be enabled by adding <tt>--enable-des-metrics</tt> at configuration;
81+
you must also use <tt>CommandLine</tt> in your script. See the API docs
82+
for class <tt>DesMetrics</tt> for more details.
7883
</ul>
7984
<h2>Changes to existing API:</h2>
8085
<ul>

‎RELEASE_NOTES

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ New user-visible features
4242
this model matches the API and behavior of YansWifiPhy closely, but
4343
over time is expected to support a different PHY abstraction and error
4444
models.
45+
- (core) DES Metrics support, see the API docs for class DesMetrics.
4546

4647
Bugs fixed
4748
----------

‎src/core/model/command-line.cc

+6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <sstream>
2727

2828
#include "command-line.h"
29+
#include "des-metrics.h"
2930
#include "log.h"
3031
#include "config.h"
3132
#include "global-value.h"
@@ -152,6 +153,11 @@ CommandLine::Parse (int argc, char *argv[])
152153
}
153154
HandleArgument (name, value);
154155
}
156+
157+
#ifdef ENABLE_DES_METRICS
158+
DesMetrics::Get ()->Initialize (argc, argv);
159+
#endif
160+
155161
}
156162

157163
void

‎src/core/model/des-metrics.cc

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2+
/*
3+
* Copyright (c) 2016 LLNL
4+
*
5+
* This program is free software; you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License version 2 as
7+
* published by the Free Software Foundation;
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program; if not, write to the Free Software
16+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+
*
18+
* Author: Peter D. Barnes, Jr. <pdbarnes@llnl.gov>
19+
*/
20+
21+
22+
/**
23+
* @file
24+
* @ingroup simulator
25+
* ns3::DesMetrics implementation.
26+
*/
27+
28+
#include "des-metrics.h"
29+
#include "simulator.h"
30+
#include "system-path.h"
31+
32+
#include <ctime> // time_t, time()
33+
#include <sstream>
34+
#include <string>
35+
36+
namespace ns3 {
37+
38+
/* static */
39+
std::string DesMetrics::m_outputDir; // = "";
40+
41+
void
42+
DesMetrics::Initialize (int argc, char * argv[], std::string outDir /* = "" */ )
43+
{
44+
if (m_initialized)
45+
{
46+
// Running multiple tests, so close the previous output file
47+
Close ();
48+
}
49+
50+
m_initialized = true;
51+
52+
std::string model_name ("desTraceFile");
53+
if (argc)
54+
{
55+
std::string arg0 = argv[0];
56+
model_name = SystemPath::Split (arg0).back ();
57+
}
58+
std::string jsonFile = model_name + ".json";
59+
if (outDir != "")
60+
{
61+
DesMetrics::m_outputDir = outDir;
62+
}
63+
if (DesMetrics::m_outputDir != "")
64+
{
65+
jsonFile = SystemPath::Append (DesMetrics::m_outputDir, jsonFile);
66+
}
67+
68+
time_t current_time;
69+
time (&current_time);
70+
const char * date = ctime (&current_time);
71+
std::string capture_date (date, 24); // discard trailing newline from ctime
72+
73+
m_os.open (jsonFile.c_str ());
74+
m_os << "{" << std::endl;
75+
m_os << " \"simulator_name\" : \"ns-3\"," << std::endl;
76+
m_os << " \"model_name\" : \"" << model_name << "\"," << std::endl;
77+
m_os << " \"capture_date\" : \"" << capture_date << "\"," << std::endl;
78+
m_os << " \"command_line_arguments\" : \"";
79+
if (argc)
80+
{
81+
for (int i = 0; i < argc; ++i)
82+
{
83+
if (i > 0) m_os << " ";
84+
m_os << argv[i];
85+
}
86+
}
87+
else
88+
{
89+
m_os << "[argv empty or not available]";
90+
}
91+
m_os << "\"," << std::endl;
92+
m_os << " \"events\" : [" << std::endl;
93+
94+
m_separator = ' ';
95+
96+
}
97+
98+
void
99+
DesMetrics::Trace (const Time & now, const Time & delay)
100+
{
101+
TraceWithContext (Simulator::GetContext (), now, delay);
102+
}
103+
104+
void
105+
DesMetrics::TraceWithContext (uint32_t context, const Time & now, const Time & delay)
106+
{
107+
if (!m_initialized)
108+
{
109+
Initialize (0, 0);
110+
}
111+
112+
std::ostringstream ss;
113+
if (m_separator == ',')
114+
{
115+
ss << m_separator << std::endl;
116+
}
117+
118+
uint32_t sendCtx = Simulator::GetContext ();
119+
// Force to signed so we can show NoContext as '-1'
120+
int32_t send = (sendCtx != Simulator::NO_CONTEXT) ? (int32_t)sendCtx : -1;
121+
int32_t recv = (context != Simulator::NO_CONTEXT) ? (int32_t)context : -1;
122+
123+
ss << " [\""
124+
<< send << "\",\""
125+
<< now.GetTimeStep () << "\",\""
126+
<< recv << "\",\""
127+
<< (now + delay).GetTimeStep () << "\"]";
128+
129+
{
130+
CriticalSection cs (m_mutex);
131+
m_os << ss.str ();
132+
}
133+
134+
m_separator = ',';
135+
}
136+
137+
DesMetrics::~DesMetrics (void)
138+
{
139+
Close ();
140+
}
141+
142+
void
143+
DesMetrics::Close (void)
144+
{
145+
m_os << std::endl; // Finish the last event line
146+
147+
m_os << " ]" << std::endl;
148+
m_os << "}" << std::endl;
149+
m_os.close ();
150+
151+
m_initialized = false;
152+
}
153+
154+
155+
156+
} // namespace ns3
157+

‎src/core/model/des-metrics.h

+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2+
/*
3+
* Copyright (c) 2016 LLNL
4+
*
5+
* This program is free software; you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License version 2 as
7+
* published by the Free Software Foundation;
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program; if not, write to the Free Software
16+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+
*
18+
* Author: Peter D. Barnes, Jr. <pdbarnes@llnl.gov>
19+
*/
20+
21+
#ifndef DESMETRICS_H
22+
#define DESMETRICS_H
23+
24+
/**
25+
* @file
26+
* @ingroup simulator
27+
* ns3::DesMetrics declaration.
28+
*/
29+
30+
#include "nstime.h"
31+
#include "singleton.h"
32+
#include "system-mutex.h"
33+
34+
#include <stdint.h> // uint32_t
35+
#include <fstream>
36+
#include <string>
37+
38+
namespace ns3 {
39+
40+
/**
41+
* @ingroup simulator
42+
*
43+
* @brief Event trace data collector for the DES Metrics project.
44+
*
45+
* This feature generates a JSON file with event trace data,
46+
* including the source and destination context for each
47+
* event, and the (virtual) times when the event was scheduled and
48+
* when it will execute.
49+
*
50+
* See the DES Metrics Project page: https://wilseypa.github.io/desMetrics/
51+
* for more information and analysis tools.
52+
*
53+
* If enabled (see below), ns-3 scripts should use CommandLine to
54+
* parse arguments, which will open the JSON file with the same name
55+
* as the script, and write the JSON header. Failure to use CommandLine when
56+
* DES Metrics is enabled will put the trace data in the file
57+
* \c desTraceFile.json instead. All examples accessible from \c test.py
58+
* use CommandLine, and so generate JSON files.
59+
*
60+
* Output from scripts ends up in the current working directory (normally the
61+
* top level directory). When \c test.py is used to run tests or examples
62+
* the trace files are generated in a time-stamped subdirectory of
63+
* \c testpy-output/, which \c test.py normally deletes.
64+
* To keep the output of examples, use the \c --retain argument to \c test.py.
65+
*
66+
* The output file has the following form:
67+
* \verbatim
68+
{
69+
"simulator_name" : "ns-3",
70+
"model_name" : "ipv4-raw",
71+
"capture_date" : "Fri May 27 00:34:27 2016",
72+
"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",
73+
"events" : [
74+
["0",0,"0",0],
75+
["1",0,"0",0],
76+
["0",0,"0",0],
77+
...
78+
["0",0,"0",0]
79+
]
80+
} \endverbatim
81+
* The first few fields are self-explanatory. The \c event record consists of
82+
* the source context, the event send time, the destination context,
83+
* and the event execution time. Times are given in the
84+
* current Time resolution.
85+
*
86+
* <b> Enabling DES Metrics </b>
87+
*
88+
* Enable DES Metrics at configure time with
89+
* \verbatim
90+
$ waf configure ... --enable-des-metrics \endverbatim
91+
*
92+
* <b> Working with DES Metrics </b>
93+
*
94+
* Some useful shell pipelines:
95+
*
96+
* \li Run everything, retaining the results directory: <br/>
97+
* \code ./test.py --nowaf --retain \endcode
98+
* \li Example traces end up in \c testpy-output/, so move there: <br/>
99+
* \code cd testpy-output/$(date +"%F")*_/ \endcode
100+
* (Remove the `_', which is to work around a Doxygen limitation.)
101+
* \li Remove the traces with less than 10 events: <br/>
102+
* \code wc -l *.json | sort -nr | grep "^ *[789] " | cut -d ' ' -f 9 | xargs rm -f \endcode
103+
* \li Show the largest file, and total number of trace files: <br/>
104+
* \code wc -l *.json | sort -n | tail -2 \endcode
105+
*
106+
*/
107+
class DesMetrics : public Singleton<DesMetrics>
108+
{
109+
public:
110+
111+
/**
112+
* Open the DesMetrics trace file and print the header.
113+
*
114+
* The trace file will have the same base name as the main program,
115+
* '.json' as the extension.
116+
*
117+
* \param argc [in] Command line argument count.
118+
* \param argv [in] Command line arguments.
119+
* \param outDir [in] Directory where the trace file should be written.
120+
*/
121+
void Initialize (int argc, char * argv[], std::string outDir = "");
122+
123+
/**
124+
* Trace an event to self at the time it is scheduled.
125+
*
126+
* \param now [in] The local simulation time.
127+
* \param delay [in] The delay to the event.
128+
*/
129+
void Trace (const Time & now, const Time & delay);
130+
131+
/**
132+
* Trace an event (with context) at the time it is scheduled.
133+
*
134+
* \param context [in] The context (NodeId) which will receive the event.
135+
* \param now [in] The local simulation time.
136+
* \param delay [in] The delay to the event.
137+
*/
138+
void TraceWithContext (uint32_t context, const Time & now, const Time & delay);
139+
140+
/**
141+
* Destructor, closes the trace file.
142+
*/
143+
~DesMetrics (void);
144+
145+
private:
146+
147+
/** Close the output file. */
148+
void Close (void);
149+
150+
/**
151+
* Cache the last-used output directory.
152+
*
153+
* This is enables repeated/re-entrant use of CommandLine, for example
154+
* in \c command-line-test-suite.cc
155+
*/
156+
static std::string m_outputDir;
157+
158+
bool m_initialized; //!< Have we been initialized.
159+
std::ofstream m_os; //!< The output json trace file stream.
160+
char m_separator; //!< The separator between event records.
161+
162+
/** Mutex to control access to the output file. */
163+
SystemMutex m_mutex;
164+
165+
}; // class DesMetrics
166+
167+
168+
} // namespace ns3
169+
170+
#endif /* DESMETRICS_H */

0 commit comments

Comments
 (0)