some cleanup of part 1 of manual

This commit is contained in:
Tom Henderson
2009-10-18 22:11:29 -07:00
parent 6a6de8bbfa
commit 42ba205efd
9 changed files with 226 additions and 146 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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