some cleanup of part 1 of manual
This commit is contained in:
@@ -125,7 +125,8 @@ public:
|
||||
|
||||
This is defined in the node.cc file as follows:
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
TypeId
|
||||
Node::GetTypeId (void)
|
||||
{
|
||||
@@ -148,15 +149,16 @@ Node::GetTypeId (void)
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
Look at the TypeId of an ns-3 @code{Object} class as an extended form of run
|
||||
time type information (RTTI). The C++ language includes simple kind of RTTI
|
||||
Consider the TypeId of an ns-3 @code{Object} class as an extended form of run
|
||||
time type information (RTTI). The C++ language includes a simple kind of RTTI
|
||||
in order to support @code{dynamic_cast} and @code{typeid} operators.
|
||||
|
||||
The ``@code{.SetParent<Object> ()}'' call in the declaration above is used in
|
||||
conjunction with our object aggregation mechanisms to allow safe up- and
|
||||
down-casing in inheritance trees during @code{GetObject}.
|
||||
down-casting in inheritance trees during @code{GetObject}.
|
||||
|
||||
The ``@code{.AddConstructor<Node> ()}'' call is used in conjunction with our
|
||||
abstract object factory mechanisms to allow us to construct C++ objects without
|
||||
@@ -183,7 +185,7 @@ without even knowing the concrete C++ type
|
||||
@verbatim
|
||||
ObjectFactory factory;
|
||||
const std::string typeId = "ns3::Node'';
|
||||
factory.SetTypeId(typeId);
|
||||
factory.SetTypeId (typeId);
|
||||
Ptr<Object> node = factory.Create <Object> ();
|
||||
@end verbatim
|
||||
|
||||
@@ -259,7 +261,8 @@ and some type of global default value.
|
||||
In the ns-3 attribute system, these value definitions and accessor
|
||||
functions are moved into the TypeId class; e.g.:
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
NS_OBJECT_ENSURE_REGISTERED (DropTailQueue);
|
||||
|
||||
TypeId DropTailQueue::GetTypeId (void)
|
||||
@@ -276,7 +279,8 @@ TypeId DropTailQueue::GetTypeId (void)
|
||||
|
||||
return tid;
|
||||
}
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
The AddAttribute() method is performing a number of things with this
|
||||
value:
|
||||
@@ -295,11 +299,19 @@ section, we will provide an example script that shows how users
|
||||
may manipulate these values.
|
||||
|
||||
Note that initialization of the attribute relies on the macro
|
||||
NS_OBJECT_ENSURE_REGISTERED (DropTailQueue) being called; if you leave
|
||||
@code{NS_OBJECT_ENSURE_REGISTERED} (DropTailQueue) being called; if you leave
|
||||
this out of your new class implementation, your attributes will not be
|
||||
initialized correctly.
|
||||
|
||||
@subsection Basic usage
|
||||
While we have described how to create attributes, we still haven't
|
||||
described how to access and manage these values. For instance, there is no
|
||||
@code{globals.h} header file where these are stored; attributes are
|
||||
stored with their classes. Questions that naturally arise are how
|
||||
do users easily learn about all of the attributes of their models, and
|
||||
how does a user access these attributes, or document their values
|
||||
as part of the record of their simulation?
|
||||
|
||||
@subsection Default values and command-line arguments
|
||||
|
||||
Let's look at how a user script might access these values.
|
||||
This is based on the script found at @code{samples/main-attribute-value.cc},
|
||||
@@ -341,7 +353,8 @@ Now, we will create a few objects using the low-level API; here,
|
||||
our newly created queues will not have a m_maxPackets initialized to
|
||||
100 packets but to 80 packets, because of what we did above with
|
||||
default values.
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
Ptr<Node> n0 = CreateObject<Node> ();
|
||||
|
||||
Ptr<PointToPointNetDevice> net0 = CreateObject<PointToPointNetDevice> ();
|
||||
@@ -349,7 +362,8 @@ default values.
|
||||
|
||||
Ptr<Queue> q = CreateObject<DropTailQueue> ();
|
||||
net0->AddQueue(q);
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
At this point, we have created a single node (Node 0) and a
|
||||
single PointToPointNetDevice (NetDevice 0) and added a
|
||||
@@ -358,10 +372,10 @@ DropTailQueue to it.
|
||||
Now, we can manipulate the MaxPackets value of the already
|
||||
instantiated DropTailQueue. Here are various ways to do that.
|
||||
|
||||
@subsubsection Pointer-based access
|
||||
@subsection Pointer-based access
|
||||
|
||||
We assume that a smart pointer (Ptr) to a relevant network device is
|
||||
in hand; here, it is the net0 pointer.
|
||||
in hand; in the current example, it is the @code{net0} pointer.
|
||||
|
||||
One way to change the value is to access a pointer to the
|
||||
underlying queue and modify its attribute.
|
||||
@@ -369,11 +383,11 @@ underlying queue and modify its attribute.
|
||||
First, we observe that we can get a pointer to the (base class)
|
||||
queue via the PointToPointNetDevice attributes, where it is called
|
||||
TxQueue
|
||||
@verbatim
|
||||
@example
|
||||
PointerValue tmp;
|
||||
net0->GetAttribute ("TxQueue", tmp);
|
||||
Ptr<Object> txQueue = tmp.GetObject ();
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
Using the GetObject function, we can perform a safe downcast
|
||||
to a DropTailQueue, where MaxPackets is a member
|
||||
@@ -409,44 +423,52 @@ Now, let's set it to another value (60 packets)
|
||||
NS_LOG_INFO ("3. txQueue limit changed: " << limit.Get () << " packets");
|
||||
@end verbatim
|
||||
|
||||
@subsubsection Namespace-based access
|
||||
@subsection Namespace-based access
|
||||
|
||||
An alternative way to get at the attribute is to use the configuration namespace.
|
||||
Here, this attribute resides on a known path in this namespace; this approach
|
||||
is useful if one doesn't have access to the underlying pointers and would like
|
||||
to configure a specific attribute with a single statement.
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
Config::Set ("/NodeList/0/DeviceList/0/TxQueue/MaxPackets", UintegerValue (25));
|
||||
txQueue->GetAttribute ("MaxPackets", limit);
|
||||
NS_LOG_INFO ("4. txQueue limit changed through namespace: " <<
|
||||
limit.Get () << " packets");
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
We could have also used wildcards to set this value for all nodes and all net
|
||||
devices (which in this simple example has the same effect as the previous Set())
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
Config::Set ("/NodeList/*/DeviceList/*/TxQueue/MaxPackets", UintegerValue (15));
|
||||
txQueue->GetAttribute ("MaxPackets", limit);
|
||||
NS_LOG_INFO ("5. txQueue limit changed through wildcarded namespace: " <<
|
||||
limit.Get () << " packets");
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
@subsubsection Object Name Service-based access
|
||||
@subsection Object Name Service-based access
|
||||
|
||||
Another way to get at the attribute is to use the object name service facility.
|
||||
Here, this attribute is found using a name string. This approach is useful if
|
||||
one doesn't have access to the underlying pointers and it is difficult to
|
||||
determine the required concrete configuration namespaced path.
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
Names::Add ("server", serverNode);
|
||||
Names::Add ("server/eth0", serverDevice);
|
||||
|
||||
...
|
||||
|
||||
Config::Set ("/Names/server/eth0/TxQueue/MaxPackets", UintegerValue (25));
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
@xref{Object names} for a fuller treatment of the ns-3 configuration namespace.
|
||||
|
||||
@subsection Setting through constructors helper classes
|
||||
|
||||
@@ -466,7 +488,8 @@ or from the higher-level helper APIs, such as:
|
||||
"LayoutType", StringValue ("RowFirst"));
|
||||
@end verbatim
|
||||
|
||||
@subsection Value classes
|
||||
@subsection Implementation details
|
||||
@subsubsection Value classes
|
||||
Readers will note the new FooValue classes which are subclasses of the
|
||||
AttributeValue base class. These can be thought of as
|
||||
an intermediate class that can be used to convert from raw types to the
|
||||
@@ -489,14 +512,14 @@ the attribute system:
|
||||
@item ATTRIBUTE_HELPER_CPP
|
||||
@end itemize
|
||||
|
||||
@subsection Initialization order
|
||||
@subsubsection Initialization order
|
||||
|
||||
In general, the attribute code to assign values to the underlying
|
||||
class member variables is executed after an object is constructed.
|
||||
But what if you need the values assigned before the constructor
|
||||
body executes, because you need them in the logic of the constructor?
|
||||
There is a way to do this, used for example in the class
|
||||
@code{ns3::ConfigStore}: call @code{ObjectBase::ConstructSelf()}
|
||||
@code{ns3::ConfigStore}: call @code{ObjectBase::ConstructSelf ()}
|
||||
as follows:
|
||||
|
||||
@verbatim
|
||||
@@ -546,7 +569,8 @@ Here, we discuss the impact on a user who wants to add a new class to
|
||||
ns-3; what additional things must be done to hook it into this system.
|
||||
|
||||
We've already introduced what a TypeId definition looks like:
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
TypeId
|
||||
RandomWalk2dMobilityModel::GetTypeId (void)
|
||||
{
|
||||
@@ -568,7 +592,8 @@ RandomWalk2dMobilityModel::GetTypeId (void)
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
The declaration for this in the class declaration is one-line public
|
||||
member method:
|
||||
@@ -599,7 +624,9 @@ the conversions to/from strings and attribute values. Most of this can be
|
||||
copy/pasted with macro-ized code. For instance, consider class
|
||||
declaration for Rectangle in the @code{src/mobility/} directory:
|
||||
|
||||
@verbatim
|
||||
@subsection Header file
|
||||
@smallformat
|
||||
@example
|
||||
/**
|
||||
* \brief a 2d rectangle
|
||||
*/
|
||||
@@ -612,35 +639,42 @@ class Rectangle
|
||||
double yMin;
|
||||
double yMax;
|
||||
};
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
One macro call and two operators, must be added below the class declaration
|
||||
in order to turn a Rectangle into a value usable by the @code{Attribute}
|
||||
system:
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
std::ostream &operator << (std::ostream &os, const Rectangle &rectangle);
|
||||
std::istream &operator >> (std::istream &is, Rectangle &rectangle);
|
||||
|
||||
ATTRIBUTE_HELPER_HEADER (Rectangle);
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
@subsection Implementation file
|
||||
In the class definition (@code{.cc} file), the code looks like this:
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
ATTRIBUTE_HELPER_CPP (Rectangle);
|
||||
|
||||
std::ostream &
|
||||
operator << (std::ostream &os, const Rectangle &rectangle)
|
||||
{
|
||||
os << rectangle.xMin << "|" << rectangle.xMax << "|" << rectangle.yMin << "|" << rectangle.yMax;
|
||||
os << rectangle.xMin << "|" << rectangle.xMax << "|" << rectangle.yMin << "|"
|
||||
<< rectangle.yMax;
|
||||
return os;
|
||||
}
|
||||
std::istream &
|
||||
operator >> (std::istream &is, Rectangle &rectangle)
|
||||
{
|
||||
char c1, c2, c3;
|
||||
is >> rectangle.xMin >> c1 >> rectangle.xMax >> c2 >> rectangle.yMin >> c3 >> rectangle.yMax;
|
||||
is >> rectangle.xMin >> c1 >> rectangle.xMax >> c2 >> rectangle.yMin >> c3
|
||||
>> rectangle.yMax;
|
||||
if (c1 != '|' ||
|
||||
c2 != '|' ||
|
||||
c3 != '|')
|
||||
@@ -649,7 +683,8 @@ operator >> (std::istream &is, Rectangle &rectangle)
|
||||
}
|
||||
return is;
|
||||
}
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
These stream operators simply convert from a string representation of the
|
||||
Rectangle ("xMin|xMax|yMin|yMax") to the underlying Rectangle, and the
|
||||
@@ -679,7 +714,8 @@ file to the scratch directory:
|
||||
Let's edit it to add the ConfigStore feature. First, add an include statement
|
||||
to include the contrib module, and then add these lines:
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
#include "contrib-module.h"
|
||||
...
|
||||
int main (...)
|
||||
@@ -693,7 +729,8 @@ int main (...)
|
||||
|
||||
Simulator::Run ();
|
||||
}
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
There are three attributes that govern the behavior of the ConfigStore:
|
||||
"Mode", "Filename", and "FileFormat". The Mode (default "None") configures
|
||||
@@ -705,12 +742,16 @@ the ConfigStore format is Xml or RawText format.
|
||||
|
||||
So, using the above modified program, try executing the following
|
||||
waf command and
|
||||
@verbatim
|
||||
./waf --command-template="%s --ns3::ConfigStore::Filename=csma-bridge-config.xml --ns3::ConfigStore::Mode=Save --ns3::ConfigStore::FileFormat=Xml" --run scratch/csma-bridge
|
||||
@end verbatim
|
||||
@smallformat
|
||||
@example
|
||||
./waf --command-template="%s --ns3::ConfigStore::Filename=csma-bridge-config.xml
|
||||
--ns3::ConfigStore::Mode=Save --ns3::ConfigStore::FileFormat=Xml" --run scratch/csma-bridge
|
||||
@end example
|
||||
@end smallformat
|
||||
After running, you can open the csma-bridge-config.xml file and it will
|
||||
display the configuration that was applied to your simulation; e.g.
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ns3>
|
||||
<default name="ns3::V4Ping::Remote" value="102.102.102.102"/>
|
||||
@@ -723,7 +764,9 @@ display the configuration that was applied to your simulation; e.g.
|
||||
<default name="ns3::QstaWifiMac::MaxMissedBeacons" value="10"/>
|
||||
<default name="ns3::QstaWifiMac::ActiveProbing" value="false"/>
|
||||
...
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
This file can be archived with your simulation script and output data.
|
||||
|
||||
While it is possible to generate a sample config file and lightly
|
||||
@@ -749,7 +792,8 @@ separate file called "output-attributes.xml". (Note-- to get this
|
||||
input xml file to begin with, it is sometimes helpful to run the
|
||||
program to generate an output xml file first, then hand-edit that
|
||||
file and re-input it for the next simulation run).
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
#include "contrib-module.h"
|
||||
...
|
||||
int main (...)
|
||||
@@ -778,7 +822,8 @@ int main (...)
|
||||
outputConfig.ConfigureAttributes ();
|
||||
Simulator::Run ();
|
||||
}
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
@subsection GTK-based ConfigStore
|
||||
|
||||
@@ -794,24 +839,28 @@ sudo apt-get install libgtk2.0-0 libgtk2.0-dev
|
||||
@end verbatim
|
||||
To check whether it is configured or not, check the output of the
|
||||
./waf configure step:
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
---- Summary of optional NS-3 features:
|
||||
Threading Primitives : enabled
|
||||
Real Time Simulator : enabled
|
||||
GtkConfigStore : not enabled (library 'gtk+-2.0 >= 2.12' not found)
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
In the above example, it was not enabled, so it cannot be used until a
|
||||
suitable version is installed and ./waf configure; ./waf is rerun.
|
||||
|
||||
Usage is almost the same as the non-GTK-based version, but there
|
||||
are no ConfigStore attributes involved:
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
// Invoke just before entering Simulator::Run ()
|
||||
GtkConfigStore config;
|
||||
config.ConfigureDefaults ();
|
||||
config.ConfigureAttributes ();
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
Now, when you run the script, a GUI should pop up, allowing you to open
|
||||
menus of attributes on different nodes/objects, and then launch the
|
||||
|
||||
@@ -12,6 +12,7 @@ it, and details on its implementation.
|
||||
* Using the Callback API::
|
||||
* Bound Callbacks::
|
||||
* Callback locations in ns-3::
|
||||
* Traced Callbacks::
|
||||
* Implementation details::
|
||||
@end menu
|
||||
|
||||
@@ -35,7 +36,6 @@ public:
|
||||
|
||||
class B {
|
||||
public:
|
||||
void ReceiveInput ( // parameters);
|
||||
void DoSomething (void);
|
||||
...
|
||||
|
||||
@@ -94,6 +94,10 @@ optimal way to design a generic simulator.
|
||||
@node Callbacks Background
|
||||
@section Background
|
||||
|
||||
@cartouche
|
||||
Readers familiar with programming callbacks may skip this tutorial section.
|
||||
@end cartouche
|
||||
|
||||
The basic mechanism that allows one to address the problem above is known as
|
||||
a @emph{callback}. The ultimate goal is to allow one piece of code to call
|
||||
a function (or method in C++) without any specific inter-module dependency.
|
||||
@@ -358,16 +362,19 @@ Consider also the following main program snippet:
|
||||
@end verbatim
|
||||
|
||||
This is an example of a C-style callback -- one which does not include or need
|
||||
a @code{this} pointer. The funtion template @code{Callback} is esentially the
|
||||
a @code{this} pointer. The function template @code{Callback} is esentially the
|
||||
declaration of the variable containing the pointer-to-function. In the example
|
||||
above, we explicitly showed a pointer to a function that returned an integer and
|
||||
took a single integer as a parameter, The @code{Callback} template function is
|
||||
a generic version of that -- it is used to declare the type of a callback.
|
||||
|
||||
@strong{Note1:} Readers unfamiliar with C++ templates may consult
|
||||
@uref{http://www.cplusplus.com/doc/tutorial/templates/,,this reference}.
|
||||
|
||||
The @code{Callback} template requires one mandatory argument (the return type
|
||||
of the function to be assigned to this callback) and up to five optional
|
||||
arguments, which each specify the type of the arguments (if your particular
|
||||
callback function has more than five arguments, then this can be easily handled
|
||||
callback function has more than five arguments, then this can be handled
|
||||
by extending the callback implementation).
|
||||
|
||||
So in the above example, we have a declared a callback named "one" that will
|
||||
@@ -451,7 +458,7 @@ invoked. Consider this example, also from main-callback.cc:
|
||||
@end verbatim
|
||||
|
||||
Here, we pass an additional object pointer to the @code{MakeCallback<>} function.
|
||||
Recall from the example above that @code{Operator()} will use the pointer to
|
||||
Recall from the background section above that @code{Operator()} will use the pointer to
|
||||
member syntax when it executes on an object:
|
||||
|
||||
@verbatim
|
||||
@@ -505,7 +512,7 @@ later -- when the @code{Callback} is called via @code{operator()}. All of
|
||||
the parameters are provided by the calling function.
|
||||
|
||||
What if it is desired to allow the client function (the one that provides the
|
||||
callback) to provide some of the parameters? Alexandrescu calls the process of
|
||||
callback) to provide some of the parameters? @uref{http://erdani.com/book/main.html,,Alexandrescu} calls the process of
|
||||
allowing a client to specify one of the parameters @emph{binding}. One of the
|
||||
parameters of @code{operator()} has been bound (fixed) by the client.
|
||||
|
||||
@@ -539,7 +546,7 @@ takes the parameters to be bound. In the case of the example above,
|
||||
MakeBoundCallback (&CsmaHelper::SniffEvent, pcap));
|
||||
@end verbatim
|
||||
|
||||
Will create a specific callback implementation that knows to add in the extra
|
||||
will create a specific callback implementation that knows to add in the extra
|
||||
bound arguments. Conceptually, it extends the specific functor described above
|
||||
with one or more bound arguments
|
||||
|
||||
@@ -581,16 +588,24 @@ function call:
|
||||
(*m_p.*m_pmi)(m_boundArg, arg);
|
||||
@end verbatim
|
||||
|
||||
@node Traced Callbacks
|
||||
@section Traced Callbacks
|
||||
@cartouche
|
||||
Placeholder subsection
|
||||
@end cartouche
|
||||
@section Callback locations in @command{ns-3}
|
||||
@node Callback locations in ns-3
|
||||
@section Callback locations in @command{ns-3}
|
||||
|
||||
Where are callbacks frequently used in @command{ns-3}? Here are some of the
|
||||
more visible ones to typical users:
|
||||
|
||||
@subsection Socket API
|
||||
@subsection Layer-2/Layer-3 API
|
||||
@subsection Tracing subsystem
|
||||
@subsection Routing
|
||||
@itemize @bullet
|
||||
@item Socket API
|
||||
@item Layer-2/Layer-3 API
|
||||
@item Tracing subsystem
|
||||
@item API between IP and routing subsystems
|
||||
@end itemize
|
||||
|
||||
@node Implementation details
|
||||
@section Implementation details
|
||||
@@ -600,8 +615,9 @@ itself. The actual Callback code is quite complicated and very template-intense
|
||||
a deep understanding of the code is not required. If interested, expert users may
|
||||
find the following useful:
|
||||
|
||||
The code was originally written based on the techniques described
|
||||
@uref{http://www.codeproject.com/cpp/TTLFunction.asp,,here}.
|
||||
The code was originally written based on the techniques described in
|
||||
@uref{http://www.codeproject.com/cpp/TTLFunction.asp,,
|
||||
http://www.codeproject.com/cpp/TTLFunction.asp}.
|
||||
It was subsequently rewritten to follow the architecture outlined in
|
||||
@uref{http://www.amazon.com/Modern-C\%2B\%2B-Design-Programming-Patterns/dp/0201704315/ref=pd_bbs_sr_1/102-0157303-1900156?ie=UTF8\&s=books\&qid=1187982662\&sr=1-1,,Modern C++ Design: Generic Programming and Design Patterns Applied-- Alexandrescu}, chapter 5, "Generalized Functors".
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ for details on the ORBIT testbed.
|
||||
A simulation of this kind is shown in the following figure:
|
||||
|
||||
@float Figure,fig:testbed
|
||||
@center @caption{Example Implementation of Testbed Emulation.}
|
||||
@caption{Example Implementation of Testbed Emulation.}
|
||||
@center @image{figures/testbed, 5in}
|
||||
@end float
|
||||
|
||||
@@ -44,7 +44,7 @@ is shown in the following figure:
|
||||
|
||||
@float Figure,fig:emulated-channel
|
||||
@caption{Implementation overview of emulated channel.}
|
||||
@image{figures/emulated-channel, 5in}
|
||||
@image{figures/emulated-channel, 6in}
|
||||
@end float
|
||||
|
||||
Here, you will see that there is a single host with a number of virtual machines
|
||||
|
||||
@@ -24,11 +24,12 @@ the document should be discussed on the ns-developers@@isi.edu mailing list.
|
||||
|
||||
This is an @command{ns-3} reference manual.
|
||||
Primary documentation for the @command{ns-3} project is available in
|
||||
four forms:
|
||||
five forms:
|
||||
@itemize @bullet
|
||||
@item @uref{http://www.nsnam.org/docs/tutorial/tutorial.html,,ns-3 Tutorial}
|
||||
@item @uref{http://www.nsnam.org/doxygen/index.html,,ns-3 Doxygen}: Documentation of the public APIs of the simulator
|
||||
@item Reference Manual (this document)
|
||||
@item @uref{http://www.nsnam.org/tutorials.html,, ns-3 Testing and Validation manual}
|
||||
@item @uref{http://www.nsnam.org/wiki/index.php,, ns-3 wiki}
|
||||
@end itemize
|
||||
|
||||
@@ -62,6 +63,8 @@ along with this program. If not, see @uref{http://www.gnu.org/licenses/}.
|
||||
|
||||
@vskip 0pt plus 1filll
|
||||
@insertcopying
|
||||
@page
|
||||
@center This page is intentionally blank.
|
||||
@end titlepage
|
||||
|
||||
@c So the toc is printed at the start.
|
||||
|
||||
@@ -98,7 +98,7 @@ When the reference count falls to zero, the object is deleted.
|
||||
|
||||
@itemize @bullet
|
||||
@item When the client code obtains a pointer from the object itself
|
||||
through object creation, or via QueryInterface, it does not have
|
||||
through object creation, or via GetObject, it does not have
|
||||
to increment the reference count.
|
||||
@item When client code obtains a pointer from another source (e.g.,
|
||||
copying a pointer) it must call @code{Ref()} to increment the
|
||||
@@ -154,7 +154,9 @@ using @code{CreateObject()} instead.
|
||||
|
||||
For objects deriving from @code{class RefCountBase}, or other
|
||||
objects that support usage of the smart pointer class
|
||||
(in particular, the ns-3 Packet class),
|
||||
(in particular, the ns-3 Packet class does not derive from RefCountBase
|
||||
in order to avoid a vtable, but separately implements @code{Ref ()} and
|
||||
@code{Unref ()}),
|
||||
a templated helper function is available and recommended to be used:
|
||||
@verbatim
|
||||
Ptr<B> b = Create<B> ();
|
||||
@@ -241,7 +243,7 @@ now use the Ptr to the Ipv4 object that was previously aggregated to
|
||||
the node.
|
||||
|
||||
Another example of how one might use aggregation is to add optional
|
||||
models to objects. For in
|
||||
models to objects.
|
||||
For instance, an existing Node object may have an ``Energy Model''
|
||||
object aggregated to it at run time (without modifying
|
||||
and recompiling the node class). An existing model (such as a wireless
|
||||
|
||||
@@ -52,4 +52,4 @@ Part 6 describes additional support for simulation, such as animators.
|
||||
|
||||
The project maintains a separate manual devoted to testing and
|
||||
validation of ns-3 code (see the
|
||||
@uref{http://www.nsnam.org/tutorials.html,, ns-3 Testing and Validation manual})j
|
||||
@uref{http://www.nsnam.org/tutorials.html,, ns-3 Testing and Validation manual}).
|
||||
|
||||
@@ -99,7 +99,7 @@ things that you wouldn't find in the bits on the wire).
|
||||
|
||||
@float Figure,fig:packets
|
||||
@caption{Implementation overview of Packet class.}
|
||||
@image{figures/packet}
|
||||
@image{figures/packet, 4in}
|
||||
@end float
|
||||
|
||||
Figure @ref{fig:packets} is a high-level overview of the Packet
|
||||
@@ -222,9 +222,11 @@ applied is:
|
||||
Packet (uint8_t const *buffer, uint32_t size);
|
||||
@end verbatim
|
||||
Here is an example:
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
Ptr<Packet> pkt1 = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello"), 5);
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
Packets are freed when there are no more references to them, as with
|
||||
all ns-3 objects referenced by the Ptr class.
|
||||
@@ -258,7 +260,8 @@ examples within the source code.
|
||||
Once you have a header (or you have a preexisting header), the following
|
||||
Packet API can be used to add or remove such headers.
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
/**
|
||||
* Add header to this packet. This method invokes the
|
||||
* Header::GetSerializedSize and Header::Serialize
|
||||
@@ -284,11 +287,13 @@ Packet API can be used to add or remove such headers.
|
||||
* \returns the number of bytes read from the packet.
|
||||
*/
|
||||
uint32_t PeekHeader (Header &header) const;
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
For instance, here are the typical operations to add and remove a UDP header.
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
// add header
|
||||
Ptr<Packet> packet = Create<Packet> ();
|
||||
UdpHeader udpHeader;
|
||||
@@ -299,7 +304,8 @@ For instance, here are the typical operations to add and remove a UDP header.
|
||||
UdpHeader udpHeader;
|
||||
packet->RemoveHeader (udpHeader);
|
||||
// Read udpHeader fields as needed
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
@subsection Adding and removing Tags
|
||||
|
||||
@@ -355,7 +361,8 @@ An example is the UdpEchoServer class, which takes the received packet
|
||||
and "turns it around" to send back to the echo client.
|
||||
|
||||
The Packet API for byte tags is given below.
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
/**
|
||||
* \param tag the new tag to add to this packet
|
||||
*
|
||||
@@ -399,10 +406,12 @@ The Packet API for byte tags is given below.
|
||||
* invoke the Print method of each tag stored in the packet.
|
||||
*/
|
||||
void PrintByteTags (std::ostream &os) const;
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
The Packet API for packet tags is given below.
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
/**
|
||||
* \param tag the tag to store in this packet
|
||||
*
|
||||
@@ -451,7 +460,8 @@ The Packet API for packet tags is given below.
|
||||
* packet tags.
|
||||
*/
|
||||
PacketTagIterator GetPacketTagIterator (void) const;
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
Here is a simple example illustrating the use of tags from the
|
||||
code in @code{src/internet-stack/udp-socket-impl.cc}:
|
||||
|
||||
@@ -35,7 +35,7 @@ default; this marks a change in policy starting with ns-3.4}
|
||||
@end itemize
|
||||
@item to obtain randomness across multiple simulation runs, you must either
|
||||
set the seed differently or set the run number differently. To set a seed, call
|
||||
@code{SeedManager::SetSeed(uint32_t)} at the beginning of the program;
|
||||
@code{SeedManager::SetSeed (uint32_t)} at the beginning of the program;
|
||||
to set a run number with the same seed, call
|
||||
@code{SeedManager::SetRun (uint32_t)} at the beginning of the program;
|
||||
@xref{Seeding and independent replications}
|
||||
@@ -53,7 +53,7 @@ ns-3.
|
||||
@node Background
|
||||
@section Background
|
||||
|
||||
Simulations use a lot of random numbers; the study in [cite]
|
||||
Simulations use a lot of random numbers; one study
|
||||
found that most network simulations spend as much as 50%
|
||||
of the CPU generating random numbers. Simulation users need
|
||||
to be concerned with the quality of the (pseudo) random numbers and
|
||||
@@ -62,7 +62,7 @@ the independence between different streams of random numbers.
|
||||
Users need to be concerned with a few issues, such as:
|
||||
@itemize @bullet
|
||||
@item the seeding of the random number generator and whether a
|
||||
simulation run is deterministic or not,
|
||||
simulation outcome is deterministic or not,
|
||||
@item how to acquire different streams of random numbers that are
|
||||
independent from one another, and
|
||||
@item how long it takes for streams to cycle
|
||||
@@ -96,8 +96,7 @@ streams of random numbers, each of which consists of
|
||||
2.3x10^15 substreams. Each substream has a period
|
||||
(@emph{i.e.}, the number of random numbers before overlap) of
|
||||
7.6x10^22. The period of the entire generator is
|
||||
3.1x10^57. Figure ref-streams provides a graphical idea of
|
||||
how the streams and substreams fit together.
|
||||
3.1x10^57.
|
||||
|
||||
Class @code{ns3::RandomVariable} is the public interface to this
|
||||
underlying random number generator. When users create new
|
||||
@@ -167,7 +166,7 @@ from within the program; the user can set the
|
||||
@end verbatim
|
||||
|
||||
Another way to control this is by passing a command-line argument; since
|
||||
this is an ns3 GlobalValue instance, it is equivalently done such as follows:
|
||||
this is an ns-3 GlobalValue instance, it is equivalently done such as follows:
|
||||
@verbatim
|
||||
./waf --command-template="%s --RngRun=3" --run program-name
|
||||
@end verbatim
|
||||
@@ -198,42 +197,25 @@ numbers before overlapping.
|
||||
@section Base class public API
|
||||
|
||||
Below are excerpted a few public methods of @code{class RandomVariable}
|
||||
that deal with the global configuration and state of the RNG.
|
||||
@verbatim
|
||||
that access the next value in the substream.
|
||||
@smallformat
|
||||
@example
|
||||
/**
|
||||
* \brief Set seeding behavior
|
||||
*
|
||||
* Specify whether the POSIX device /dev/random is to
|
||||
* be used for seeding. When this is used, the underlying
|
||||
* generator is seeded with data from /dev/random instead of
|
||||
* being seeded based upon the time of day. Defaults to true.
|
||||
* \brief Returns a random double from the underlying distribution
|
||||
* \return A floating point random value
|
||||
*/
|
||||
static void UseDevRandom(bool udr = true);
|
||||
|
||||
/**
|
||||
* \brief Use the global seed to force precisely reproducible results.
|
||||
*/
|
||||
static void UseGlobalSeed(uint32_t s0, uint32_t s1, uint32_t s2,
|
||||
uint32_t s3, uint32_t s4, uint32_t s5);
|
||||
|
||||
double GetValue (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the run number of this simulation
|
||||
* \brief Returns a random integer integer from the underlying distribution
|
||||
* \return Integer cast of ::GetValue()
|
||||
*/
|
||||
static void SetRunNumber(uint32_t n);
|
||||
uint32_t GetInteger (void) const;
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
/**
|
||||
* \brief Get the internal state of the RNG
|
||||
*
|
||||
* This function is for power users who understand the inner workings
|
||||
* of the underlying RngStream method used. It returns the internal
|
||||
* state of the RNG via the input parameter.
|
||||
* \param seed Output parameter; gets overwritten with the internal state
|
||||
* of the RNG.
|
||||
*/
|
||||
void GetSeed(uint32_t seed[6]) const;
|
||||
@end verbatim
|
||||
|
||||
We have already described the seeding configuration above.
|
||||
We have already described the seeding configuration above. Different
|
||||
RandomVariable subclasses may have additional API.
|
||||
|
||||
@node Types of RandomVariables
|
||||
@section Types of RandomVariables
|
||||
@@ -255,6 +237,9 @@ class RandomVariable.
|
||||
@item @code{class DeterministicVariable }
|
||||
@item @code{class LogNormalVariable }
|
||||
@item @code{class TriangularVariable }
|
||||
@item @code{class GammaVariable }
|
||||
@item @code{class ErlangVariable }
|
||||
@item @code{class ZipfVariable }
|
||||
@end itemize
|
||||
|
||||
@node Semantics of RandomVariable objects
|
||||
@@ -270,7 +255,8 @@ any heap-allocated RandomVariables.
|
||||
RandomVariable objects can also be used in ns-3 attributes, which means
|
||||
that values can be set for them through the ns-3 attribute system.
|
||||
An example is in the propagation models for WifiNetDevice:
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
TypeId
|
||||
RandomPropagationDelayModel::GetTypeId (void)
|
||||
{
|
||||
@@ -285,7 +271,8 @@ RandomPropagationDelayModel::GetTypeId (void)
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
Here, the ns-3 user can change the default random variable for this
|
||||
delay model (which is a UniformVariable ranging from 0 to 1) through
|
||||
the attribute system.
|
||||
@@ -328,14 +315,12 @@ Let's review what things you should do when creating a simulation.
|
||||
|
||||
@itemize @bullet
|
||||
@item Decide whether you are running with a fixed seed or random seed;
|
||||
a random seed is the default,
|
||||
a fixed seed is the default,
|
||||
@item Decide how you are going to manage independent replications, if
|
||||
applicable,
|
||||
@item Convince yourself that you are not drawing more random values
|
||||
than the cycle length, if you are running a long simulation, and
|
||||
than the cycle length, if you are running a very long simulation, and
|
||||
@item When you publish, follow the guidelines above about documenting your
|
||||
use of the random number generator.
|
||||
@end itemize
|
||||
|
||||
The program @emph{samples/main-random.cc} has some examples of usage.
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
@node Tracing
|
||||
@chapter Tracing
|
||||
|
||||
The tracing subsystem is one of the most important mechansisms to understand in
|
||||
The tracing subsystem is one of the most important mechanisms to understand in
|
||||
@command{ns-3}. In most cases, @command{ns-3} users will have a brilliant idea
|
||||
for some new and improved networking feature. In order to verify that this
|
||||
idea works, the researcher will make changes to an existing system and then run
|
||||
experiments to see how the new feature behaves by gathering some form of statistic
|
||||
that captures the behavior of the feature.
|
||||
experiments to see how the new feature behaves by gathering statistics
|
||||
that capture the behavior of the feature.
|
||||
|
||||
In other words, the whole point of running a simulation is to generate output for
|
||||
further study. In @command{ns-3}, the subsystem that enables a researcher to do
|
||||
@@ -37,7 +37,7 @@ way is to just directly print the information to the standard output, as in,
|
||||
@end verbatim
|
||||
|
||||
This is workable in small environments, but as your simulations get more and more
|
||||
compliated, you end up with more and more prints and the task of parsing and
|
||||
complicated, you end up with more and more prints and the task of parsing and
|
||||
performing computations on the output begins to get harder and harder.
|
||||
|
||||
Another thing to consider is that every time a new tidbit is needed, the software
|
||||
@@ -74,7 +74,7 @@ Trace sources are entities that can signal events that happen in a simulation an
|
||||
provide access to interesting underlying data. For example, a trace source could
|
||||
indicate when a packet is received by a net device and provide access to the
|
||||
packet contents for interested trace sinks. A trace source might also indicate
|
||||
when an iteresting state change happens in a model. For example, the congestion
|
||||
when an interesting state change happens in a model. For example, the congestion
|
||||
window of a TCP model is a prime candidate for a trace source.
|
||||
|
||||
Trace sources are not useful by themselves; they must be connected to other pieces
|
||||
@@ -92,7 +92,7 @@ or models of the simulator.
|
||||
There can be zero or more consumers of trace events generated by a trace source.
|
||||
One can think of a trace source as a kind of point-to-multipoint information link.
|
||||
|
||||
The ``transport protocol'' for this conceptual point-to-multipoint link as an
|
||||
The ``transport protocol'' for this conceptual point-to-multipoint link is an
|
||||
@code{ns-3} @code{Callback}.
|
||||
|
||||
Recall from the Callback Section that callback facility is a way to allow two
|
||||
@@ -100,7 +100,8 @@ modules in the system to communicate via function calls while at the same time
|
||||
decoupling the calling function from the called class completely. This is the
|
||||
same requirement as outlined above for the tracing system.
|
||||
|
||||
Basically, a trace source @emph{is} a callback. When a trace sink expresses
|
||||
Basically, a trace source @emph{is} a callback to which multiple
|
||||
functions may be registered. When a trace sink expresses
|
||||
interest in receiving trace events, it adds a callback to a list of callbacks
|
||||
held by the trace source. When an interesting event happens, the trace source
|
||||
invokes its @code{operator()} providing zero or more parameters. This tells
|
||||
@@ -112,7 +113,8 @@ functions.
|
||||
|
||||
It will be useful to go walk a quick example just to reinforce what we've said.
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
#include ``ns3/object.h''
|
||||
#include ``ns3/uinteger.h''
|
||||
#include ``ns3/traced-value.h''
|
||||
@@ -121,7 +123,8 @@ It will be useful to go walk a quick example just to reinforce what we've said.
|
||||
#include <iostream>
|
||||
|
||||
using namespace ns3;
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
The first thing to do is include the required files. As mentioned above, the
|
||||
trace system makes heavy use of the Object and Attribute systems. The first
|
||||
@@ -139,7 +142,8 @@ operator--, operator+, operator==, etc.
|
||||
What this all means is that you will be able to trace changes to an object
|
||||
made using those operators.
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
class MyObject : public Object
|
||||
{
|
||||
public:
|
||||
@@ -158,7 +162,8 @@ made using those operators.
|
||||
MyObject () {}
|
||||
TracedValue<uint32_t> m_myInt;
|
||||
};
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
Since the tracing system is integrated with Attributes, and Attributes work
|
||||
with Objects, there must be an @command{ns-3} @code{Object} for the trace source
|
||||
@@ -170,29 +175,33 @@ source to the outside world. The @code{TracedValue} declaration provides the
|
||||
infrastructure that overloads the operators mentioned above and drives the callback
|
||||
process.
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
void
|
||||
IntTrace (Int oldValue, Int newValue)
|
||||
{
|
||||
std::cout << ``Traced `` << oldValue << `` to `` << newValue << std::endl;
|
||||
}
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
This is the definition of the trace sink. It corresponds directly to a callback
|
||||
function. This function will be called whenever one of the operators of the
|
||||
@code{TracedValue} is executed.
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
Ptr<MyObject> myObject = CreateObject<MyObject> ();
|
||||
|
||||
myObject->TraceConnectWithoutContext ("MyInt", MakeCallback(&IntTrace));
|
||||
myObject->TraceConnectWithoutContext ("MyInteger", MakeCallback(&IntTrace));
|
||||
|
||||
myObject->m_myInt = 1234;
|
||||
}
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
In this snippet, the first thing that needs to be done is to create the object
|
||||
in which the trace source lives.
|
||||
@@ -238,7 +247,8 @@ called a @emph{config path}.
|
||||
For example, one might find something that looks like the following in the system
|
||||
(taken from @code{examples/tcp-large-transfer.cc})
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
void CwndTracer (uint32_t oldval, uint32_t newval) {}
|
||||
|
||||
...
|
||||
@@ -246,7 +256,8 @@ For example, one might find something that looks like the following in the syste
|
||||
Config::ConnectWithoutContext (
|
||||
"/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",
|
||||
MakeCallback (&CwndTracer));
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
This should look very familiar. It is the same thing as the previous example,
|
||||
except that a static member function of class @code{Config} is being called instead
|
||||
@@ -258,13 +269,15 @@ must be an @code{Attribute} of an @code{Object}. In fact, if you had a pointer
|
||||
the @code{Object} that has the ``CongestionWindow'' @code{Attribute} handy (call it
|
||||
@code{theObject}), you could write this just like the previous example:
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
void CwndTracer (uint32_t oldval, uint32_t newval) {}
|
||||
|
||||
...
|
||||
|
||||
theObject->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndTracer));
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
It turns out that the code for @code{Config::ConnectWithoutContext} does exactly that.
|
||||
This function takes a path that represents a chain of @code{Object} pointers and follows
|
||||
@@ -297,16 +310,18 @@ This socket, the type of which turns out to be an @code{ns3::TcpSocketImpl} defi
|
||||
an attribute called ``CongestionWindow'' which is a @code{TracedValue<uint32_t>}.
|
||||
The @code{Config::ConnectWithoutContext} now does a,
|
||||
|
||||
@verbatim
|
||||
@smallformat
|
||||
@example
|
||||
object->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndTracer));
|
||||
@end verbatim
|
||||
@end example
|
||||
@end smallformat
|
||||
|
||||
using the object pointer from ``SocketList/0'' which makes the connection between
|
||||
the trace source defined in the socket to the callback -- @code{CwndTracer}.
|
||||
|
||||
Now, whenever a change is made to the @code{TracedValue<uint32_t>} representing the
|
||||
congestion window in the TCP socket, the registered callback will be executed and
|
||||
the function @code{Cwndtracer} will be called printing out the old and new values
|
||||
the function @code{CwndTracer} will be called printing out the old and new values
|
||||
of the TCP congestion window.
|
||||
|
||||
@node Using the Tracing API
|
||||
|
||||
Reference in New Issue
Block a user