Part III
Online Interactions
March 20, 2006
In addition to creating scenarios, running simulations often
involve a lot of
online activities such as debugging, tuning parameters and collecting
results. A
set of RUV system
commands and utility
components are developed to facilitate these tasks.
The intent of this document is to describe these facilities in
greater
details in the context of running simulations. To best demonstrate when
and how
to use these facilities, the following example is used throughout this
document.
|
EXAMPLE 1
In this example, three identical TCP connections are set
up in the network
that consists of two routers and six hosts. Three bulk sources are set
up in
three of the hosts and three corresponding sinks are set up in the
other three
hosts. And the three connections share the same bottleneck with 10Kbps
bandwidth
and a 6000KB buffer. The scenario is clearly illustrated in Fig.1.
Figure 1 The network scenario constructed in this example

Without further explanations, the script that builds
this scenario is shown
below:
1 cd [mkdir drcl.comp.Component /example]
2 # create topology: 3 set link_ [java::new drcl.inet.Link] 4 $link_ setPropDelay 0.3; # 300ms 5 set adjMatrix_ [java::new {int[][]} 8 {{3} {3} {3} {0 1 2 4} {3 5 6 7} {4} {4} {4}}] 6 java::call drcl.inet.InetUtil createTopology [! .] $adjMatrix_ $link_
7 # router builder: 8 set rb [mkdir drcl.inet.NodeBuilder .routerBuilder] 9 $rb setBandwidth 1.0e7; #10Mbps
10 # source builder: 11 set hb1 [cp $rb .hostBuilder1] 12 [mkdir drcl.inet.transport.TCP $hb1/tcp] setMSS 1024; # bytes 13 set src_ [mkdir drcl.inet.application.BulkSource $hb1/source] 14 $src_ setDataUnit 1024 15 connect -c $src_/down@ -and $hb1/tcp/up@
16 # sink builder: 17 set hb2 [cp $rb .hostBuilder2] 18 mkdir drcl.inet.transport.TCPSink $hb2/tcpsink 19 set sink_ [mkdir drcl.inet.application.BulkSink $hb2/sink] 20 connect -c $sink_/down@ -and $hb2/tcpsink/up@
21 # build nodes 22 $rb build [! n?]; # build routers 23 $hb1 build [! h0-2]; # build sources 24 $hb2 build [! h5-7]; # build sinks
25 # Configure the bottleneck bandwidth and buffer 26 ! n3 setBandwidth 3 1.0e4; # 10Kbps at interface 3 27 ! n3 setBufferSize 3 6000; # ~10 packets at interface 3
28 # Set up TCP connections 29 ! h0/tcp setPeer 5 30 ! h1/tcp setPeer 6 31 ! h2/tcp setPeer 7
32 # setup static routes 33 java::call drcl.inet.InetUtil setupRoutes [! h0] [! h5] "bidirection" 34 java::call drcl.inet.InetUtil setupRoutes [! h1] [! h6] "bidirection" 35 java::call drcl.inet.InetUtil setupRoutes [! h2] [! h7] "bidirection"
|
The above script can be download here
(inet3_ex1.tcl).
The hierarchical structure of a component system in J-Sim is
exactly the
same as that of a file system in today's operating systems. To reduce
learning
time, J-Sim defines the same set of commands, as in the UNIX, to
manipulate
and navigate a component system. The major differences of a component
system and
a file system are:
- Components are "physically" connected
to one another. No physical relation exists between files.
- Components are run-time
instances. Data moves from one component to another and get
processed. Files are containers of data. They do not process
data themselves.
- Components are objects. One can get their references and
configure them directly. Files are static means.
They are accessed by run-time programs.
So in addition to existing commands, J-Sim defines another set
of commands
for connecting components and observing the component topology.
All
these commands, along with other run-time activities such as simulation
control
and system reset, are explained in details in the following subsections.
The same set of UNIX file system commands are available in
J-Sim.
They are listed below.
| Command |
Description |
cd |
Change the current working component (directory). |
cp |
Copy components. |
cat |
Print the content of a component. |
ls |
List the content of a component directory. |
mkdir |
Create components. |
mv |
Move or rename components. |
pwd |
Print the current working component (directory). |
rm |
Remove components. |
Using these commands in general is not different from using
them in UNIX. A
component is like a directory. It may contain other
components and
ports. The convention in UNIX for "hiding" a file by starting
a
file name with "." is retained in J-Sim. One can use the
"-a" option with a command to include all the
hidden objects
(component or port). Ports are by default hidden even with
the
"-a" option. To include ports, one
can use the "-p"
option. The hidden ports (beginning with ".") can only be
seen
with both options present.
Some syntaxes may be different from those in UNIX. For
example, to create a
component, one needs to specify the component class when using the "mkdir"
command. Several new syntaxes are introduced to enhance usability
specially for
component systems. For example, the "cp",
"mv",
"mkdir"
and "rm"
commands returns
the references of the objects in operation. Also the "cp"
command allows to copy one component to multiple destinations with the
"-d" option. A Java object reference
that is stored in a Tcl
variable can be used to start a path expression (line 11, 12, 13, 15
etc. in Example
1). A set of new
path expressions are also introduced to make it easier to
specify a range or
a set of objects (line 23, 24 in Example
1). Refer to the RUV
system
commands reference page for these details.
|
EXAMPLE 2
Examples of using the "mkdir"
command
has been seen in Example
1. In this example, we demonstrate using the other commands
(except "cat"
which will be separately explained in next subsection) to navigate the
component system and make some changes to the
system. The commands are almost trivial without further explanations.
TCL0> source inet3_ex1.tcl TCL0> pwd /example/
TCL0> ls n4 n3 h7 h6 h5 h2 h1 h0 8 objects listed.
TCL0> ls -al .hostBuilder1 drcl.inet.NodeBuilder child:3, port:1 .hostBuilder2 drcl.inet.NodeBuilder child:3, port:1 .link0 drcl.inet.Link child:0, port:4 .link1 drcl.inet.Link child:0, port:4 .link2 drcl.inet.Link child:0, port:4 .link3 drcl.inet.Link child:0, port:4 .link4 drcl.inet.Link child:0, port:4 .link5 drcl.inet.Link child:0, port:4 .link6 drcl.inet.Link child:0, port:4 .routerBuilder drcl.inet.NodeBuilder child:1, port:1 h0 drcl.inet.Node child:3, port:2 h1 drcl.inet.Node child:3, port:2 h2 drcl.inet.Node child:3, port:2 h5 drcl.inet.Node child:3, port:2 h6 drcl.inet.Node child:3, port:2 h7 drcl.inet.Node child:3, port:2 n3 drcl.inet.Node child:1, port:5 n4 drcl.inet.Node child:1, port:5 18 objects listed.
TCL0> cd h0
TCL0> ls -al csl drcl.inet.core.CoreServiceLayer child:4, port:4 source drcl.inet.application.BulkSource child:0, port:4 tcp drcl.inet.transport.TCP child:0, port:8 3 objects listed.
TCL0> ls -al ../h5 csl drcl.inet.core.CoreServiceLayer child:4, port:4 sink drcl.inet.application.BulkSink child:0, port:4 tcpsink drcl.inet.transport.TCPSink child:0, port:5 3 objects listed.
TCL0> cp ../h5/sink . Warning: /example/h0/ already exists. Add a trailing slash maybe? Nothing is copied. java0x0
TCL0> cp ../h5/sink ./ ;# The trailing slash is necessary. java0xdf ;# The command returns the reference of the copy. TCL0> ls -al csl drcl.inet.core.CoreServiceLayer child:4, port:4 sink drcl.inet.application.BulkSink child:0, port:4 source drcl.inet.application.BulkSource child:0, port:4 tcp drcl.inet.transport.TCP child:0, port:8 4 objects listed. TCL0> cp sink -d sink2 sink3 java0xf1 ;# The command returns the reference of the copies (in array). TCL0> ls -al csl drcl.inet.core.CoreServiceLayer child:4, port:4 sink drcl.inet.application.BulkSink child:0, port:4 sink2 drcl.inet.application.BulkSink child:0, port:4 sink3 drcl.inet.application.BulkSink child:0, port:4 source drcl.inet.application.BulkSource child:0, port:4 tcp drcl.inet.transport.TCP child:0, port:8 6 objects listed. TCL0> rm sink* java0xfc ;# The command returns the reference of the removed components (in array). TCL0> ls -al csl drcl.inet.core.CoreServiceLayer child:4, port:4 source drcl.inet.application.BulkSource child:0, port:4 tcp drcl.inet.transport.TCP child:0, port:8 3 objects listed.
|
The "cat"
command is
used to print the "content" of a component. There are two types of
data for the content of a component.
- the information obtained from the
String drcl.comp.Component.info()
method, and
- the connections and wires in the component.
The info() method of a component is
implemented by the component
implementer and provides useful information such as properties,
configurations
and/or the run-time states of the component. By default, without any
option, the
cat
command returns the info()
information. One can use the "-c" option to
print only the connections
and wires information, or the "-d" information
to print both types of
information.
There are many options available when displaying the
connections and wires
information. Refer to the cat
command
in the script reference page for details.
|
EXAMPLE 3
Continued from Example
1, we exercise the "cat"
command in this example.
TCL0> source inet3_ex1.tcl TCL0> pwd /example/
TCL0> cd h0
TCL0> cat -c ----- /example/h0/ -----: Connections: Wire 1 ---> 0@ csl/0@down <--- /example/.link0/0@ Wire 2 ---> /example/.link0/0@ <--- 0@ csl/0@down Wire 3 <--> tcp/down@ csl/19@up Wire 4 ---> tcp/up@ <--- source/down@ Wire 5 ---> source/down@ <--- tcp/up@
TCL0> mv tcp ../ java0xdb
TCL0> cat -c ----- /example/h0/ -----: Connections: Wire 1 ---> 0@ csl/0@down <--- /example/.link0/0@ Wire 2 ---> /example/.link0/0@ <--- 0@ csl/0@down Wire 3 <--> /example/tcp/down@ csl/19@up Wire 4 ---> source/down@ <--- /example/tcp/up@ Wire 5 ---> /example/tcp/up@ <--- source/down@
TCL0> mv ../tcp ./ java0xf1
TCL0> cat -c ----- /example/h0/ -----: Connections: Wire 1 ---> 0@ csl/0@down <--- /example/.link0/0@ Wire 2 ---> /example/.link0/0@ <--- 0@ csl/0@down Wire 3 <--> tcp/down@ csl/19@up Wire 4 ---> tcp/up@ <--- source/down@ Wire 5 ---> source/down@ <--- tcp/up@
|
|
TCL0> cat ../n3 ----- /example/n3/ -----: Node: 3 ;# All these are from drcl.inet.Node.info() Number of identities: 1 3 timeout NaN Routing Table: (0,5,0)(0,-1,0) ??-{3} timeout:NaN (0,0,0)(0,-1,0) ??-{0} timeout:NaN (0,6,0)(0,-1,0) ??-{3} timeout:NaN (0,1,0)(0,-1,0) ??-{1} timeout:NaN (0,7,0)(0,-1,0) ??-{3} timeout:NaN (0,2,0)(0,-1,0) ??-{2} timeout:NaN Interfaces: 0: BufferMode=byte, BufferSize=2147483647, Bandwidth=1.0E7, MTU=2147483647, LinkEmu=false 1: BufferMode=byte, BufferSize=2147483647, Bandwidth=1.0E7, MTU=2147483647, LinkEmu=false 2: BufferMode=byte, BufferSize=2147483647, Bandwidth=1.0E7, MTU=2147483647, LinkEmu=false 3: BufferMode=byte, BufferSize=6000, Bandwidth=10000.0, MTU=2147483647, LinkEmu=false
|
|
A set of commands are available for connecting two or more
components.
They are listed below.
| Command |
Description |
connect/disconnect |
establish/tear down connections between components. |
attach/detach |
attach/detach one or more ports to/from components. |
pipe |
connect a series components/ports in a pipe fashion. |
watch |
add/remove a system watcher. |
Components are connected at ports while ports are connected by
"wires". A port is duplex (can send and receive simultaneously) and
can have separate wires joined for inputting and outputting but at most
one for
each. So one can connect an end of a wire to the output point of a port
and then
the other end of the wire to the input point of another port to form a
unidirectional connection between the two ports. It is achieved by the connect
command with the "-to" option. When the connect
command is used with the "-and" option, a
bi-directional connection is
establish between ports by setting up two unidirectional connections
between
them. Also note that when two ports are connected, their joined wires
are merged
into one wire.
|
EXAMPLE 4
(Aside from Example 1)
In this example, we construct the system by
concatenating four relay
components and a counting component. The scenario is illustrated in the
following figure and the online session that builds the scenario and
checks the
results is recorded as follows.
Figure 2 The scenario for Example 4.

1 TCL0> mkdir drcl.comp.lib.Relay source relay1 relay2 relay3; 2 TCL0> mkdir drcl.comp.tool.DataCounter counter; 3 TCL0> connect -c source/port@ -to relay1/port@; 4 TCL0> connect -c relay1/port@ -to relay2/port@; 5 TCL0> connect -c relay2/port@ -to relay3/port@; 6 TCL0> connect -c relay3/port@ -to counter/port@; 7 TCL0> cat -c 8 ----- / -----: 9 Connections: 10 Wire 1 ---> counter/port@ <--- relay3/port@ 11 Wire 2 ---> relay3/port@ <--- relay2/port@ 12 Wire 3 ---> relay2/port@ <--- relay1/port@ 13 Wire 4 ---> relay1/port@ <--- source/port@
14 TCL0> setflag echo true source relay?; # Turns on the echo flag of all the relay components 15 TCL0> cat source 16 ----- /source/ -----: 17 Copy enabled: false 18 Echo enabled: true 19 TCL0> cat counter 20 ----- /counter/ -----: 21 Nothing being counted.
22 TCL0> inject "test" source/port@; # Inject data into source 23 TCL0> cat counter 24 ----- /counter/ -----: 25 #Ports being monitored: 1 26 counter/port@: 1
27 TCL0> for {set i 0} {$i < 100} {incr i} {inject "test" source/port@}; 28 TCL0> cat counter 29 ----- /counter/ -----: 30 #Ports being monitored: 1 31 counter/port@: 101
In the above online session, we inject
data (the "test" string) to "source" (line
22). Since the "echo" flag is turned on (line 14, will be further
described in Section 2),
"source" echoes back the data at
port@ which causes the data to be forwarded to "relay1",
and then "relay2" and so on, and finally, the
data arrives at "counter" and stops. As shown
by "cat" (line 23-26), the counter receives
one copy of data at its port@.
We then inject 100 copies of data into "source"
(line 27), and then check the counter again (line 28). The counter
shows receipt of 101 copies of data (line 29-31), as expected.
|
In addition to join a port with wires, a port can "attach" its
input point to a wire to listen on the wire without causing joined
wires to be
merged. This is achieved by the "attach"
command. This command is commonly used to hook up a port of an
instrument
component to multiple ports of interest without disturbing the
connections of
the ports.
|
EXAMPLE 5
(Aside from Example 1)
Varying from Example
4, now instead of connecting
the counter component at the end of the relay components, we "attach"
the counter to all the relay components as follows:
Figure 3: The scenario for Example 5.

1 TCL0> mkdir drcl.comp.lib.Relay source relay1 relay2 relay3; 2 TCL0> mkdir drcl.comp.tool.DataCounter counter; 3 TCL0> connect -c source/port@ -to relay1/port@; 4 TCL0> connect -c relay1/port@ -to relay2/port@; 5 TCL0> connect -c relay2/port@ -to relay3/port@; 6 TCL0> attach -c counter/port@ -to relay?/port@; 7 TCL0> cat -c 8 ----- / -----: 9 Connections: 10 Wire 1 ---> relay3/port@ counter/port@ <--- relay2/port@ 11 Wire 2 ---> counter/port@ <--- relay3/port@ 12 Wire 3 ---> relay2/port@ counter/port@ <--- relay1/port@ 13 Wire 4 ---> relay1/port@ <--- source/port@
14 TCL0> setflag echo true source relay?; # Turns on the echo flag of all the relay components 15 TCL0> cat counter 16 ----- /counter/ -----: 17 Nothing being counted.
18 TCL0> inject "test" source/port@; # Inject data into source 19 TCL0> cat counter 20 ----- /counter/ -----: 21 #Ports being monitored: 1 22 counter/port@: 3
23 TCL0> for {set i 0} {$i < 100} {incr i} {inject "test" source/port@}; 24 TCL0> cat counter 25 ----- /counter/ -----: 26 #Ports being monitored: 1 27 counter/port@: 303
|
|
EXAMPLE 6 (Aside from Example 1)
Varying from
Example 5, what would happen if we use "connect"
instead of "attach"?
1 TCL0> mkdir drcl.comp.lib.Relay source relay1 relay2 relay3; 2 TCL0> mkdir drcl.comp.tool.DataCounter counter; 3 TCL0> connect -c source/port@ -to relay1/port@; 4 TCL0> connect -c relay1/port@ -to relay2/port@; 5 TCL0> connect -c relay2/port@ -to relay3/port@; 6 TCL0> connect -c relay?/port@ -to counter/port@; 7 TCL0> cat -c 8 ----- / -----: 9 Connections: 10 Wire 1 <--> relay2/port@ relay3/port@ ---> counter/port@ <--- relay1/port@ 11 Wire 2 ---> relay1/port@ <--- source/port@
Figure 4 What the scenario is like if "connect"
is used.

12 TCL0> setflag echo true source relay?; # Turns on the echo flag of all the relay components 13 TCL0> ! relay?/port@ setExecutionBoundary true; # Relay is an Extension; by default, it's not execution boundary. # Make them execution boundary in order to see what goes on # with this setup 14 TCL0> inject "test" source/port@; # What if we inject data to source? 15 TCL0> cat counter 16 ----- /counter/ -----: 17 #Ports being monitored: 1 18 counter/port@: 31839 # Ouch!
19 TCL0> setflag echo false relay?; # Turn off the echo flag to stop this madness. 20 TCL0> cat counter 21 ----- /counter/ -----: 22 #Ports being monitored: 1 23 counter/port@: 76151 24 TCL0> cat counter 25 ----- /counter/ -----: 26 #Ports being monitored: 1 27 counter/port@: 76151 # The counting stops.
|
The pipe
command use either
"connect"
or "attach"
to put together a series of ports in a pipe fashion.
|
EXAMPLE 7
(Aside from Example 1)
This example is the same as Example
4 except that we
use "pipe"
to connect
instead of "connect".
1 mkdir drcl.comp.lib.Relay source relay1 relay2 relay3; 2 mkdir drcl.comp.tool.DataCounter counter; 3 pipe -c source/port@ relay1/port@ relay2/port@ relay3/port@ counter/port@; 4 setflag echo true source relay?; 5 TCL0> cat -c 6 ----- / -----: 7 Connections: 8 Wire 1 ---> counter/port@ <--- relay3/port@ 9 Wire 2 ---> relay3/port@ <--- relay2/port@ 10 Wire 3 ---> relay2/port@ <--- relay1/port@ 11 Wire 4 ---> relay1/port@ <--- source/port@
12 TCL0> for {set i 0} {$i < 100} {incr i} {inject "test" source/port@}; 13 TCL0> cat counter 14 ----- /counter/ -----: 15 #Ports being monitored: 1 16 counter/port@: 100
|
The RUV
system contains a
system monitor component. One can attach it to a port of interest to
observe the
data coming from that port. This is called creating a system
watcher and
is achieved by the "watch"
command. The command simply creates a port at the system monitor and
then
attaches (not connects) the port to the port specified.
|
EXAMPLE 8 (Aside from Example 1)
This example is the same as Example
7 except that we
add system watchers to watch the data flow at the relay components.
1 mkdir drcl.comp.lib.Relay source relay1 relay2 relay3; 2 mkdir drcl.comp.tool.DataCounter counter; 3 pipe -c source/port@ relay1/port@ relay2/port@ relay3/port@ counter/port@; 4 setflag echo true source relay?; 5 watch -label RELAY1 -add relay1/port@; # Adds the RELAY1 and RELAY3 watcher. 6 watch -label RELAY3 -add relay3/port@; 7 TCL0> cat -d # The "-d" option: to observe connections across component boundaries 8 ----- / -----: 9 Connections: 10 Wire 1 ---> .system/monitor/.info@(IN) 11 Wire 2 ---> counter/port@(IN&OUT) .system/monitor/RELAY3@(IN&OUT) <--- relay3/port@(IN&OUT) 12 Wire 3 ---> relay3/port@(IN&OUT) <--- relay2/port@(IN&OUT) 13 Wire 4 ---> relay2/port@(IN&OUT) .system/monitor/RELAY1@(IN&OUT) <--- relay1/port@(IN&OUT) 14 Wire 5 ---> relay1/port@(IN&OUT) <--- source/port@(IN&OUT) 15 No extra info is provided in drcl.comp.Component
16 TCL0> inject test source/port@ 17 RELAY1| test 18 RELAY3| test
19 TCL0> attach -c /.system/monitor/RELAY2@ -to relay2/port@; # same as watch -label RELAY2 -add relay2/port@ 20 TCL0> watch -label RELAY1 -remove relay1/port@; # Removes the RELAY1 watcher. 21 TCL0> inject test source/port@ 22 RELAY2| test 23 RELAY3| test
|
After we inject the data to "source"
at line 16, the watchers print out the data string (line 17-18) when it
arrives at "relay1" and "relay3"
respectively. Similar to what is going on at line 21-23. |
The execution of a component system is governed by a runtime
behind
the scene. The runtime is
responsible for creating threads for components to process incoming
data. One of
the salient features of J-Sim is that the component system and the
runtime is
completely decoupled. On one hand, component writing does not concern
about
runtime operations, in other words, the operations are completely
hidden in the
component API's. On the other hand, one may apply different runtime
implementations to the same component system without modifying the
component
implementations.
Different from the simulation
engine to traditional simulation softwares, the simulation
engine (or
simulation runtime, preferably) in J-Sim is built as one kind of
runtime
implementations. In particular, a
simulation runtime differs from a "normal" runtime in that a simulation
runtime jumps
in time if there is no activity in the system so that it can
keep the system
busy all the time. (See Real-time
Process-based Simulation for details)
The base class of the runtime is drcl.comp.ACARuntime.
It defines a set of methods to control the operations of a runtime
which are
consistent with general simulation controls. These methods are listed
below.
| Table
1: The methods of the base runtime class. |
| Method |
Description |
void
stop() |
Stop the runtime immediately. |
void
stop(double time_) |
Stop the runtime at the specified time later. |
void
stopAt(double time_) |
Stop the runtime at the time specified. |
void
resume() |
Resume the runtime. |
void
resumeFor(double time_) |
Resume the runtime for the time specified and
then stop it. |
void
resumeTo(double time_) |
Resume the runtime and then stop it at the time
specified. |
void
reset() |
Reset the runtime. |
double
getTime() |
Obtain the current time of the runtime. |
void
setTimeScale(double scale_)
double getTimeScale() |
Set/get the scale of the
runtime time axis, relative to the wall time. Specifically, one second
in runtime = scale_ seconds in wall time. |
void
setWorkforce(int amount_)
int getWorkforce() |
Set/get the maximum number of
threads that are allowed to be simultaneously active. |
String
info() |
Print the runtime information, including the
current state, the elapsed time, system and performance statistics,
states of threads and so on. |
|
The following discussion is generally true for all runtime
implementations.
It also applies to a simulation runtime.
The time in a runtime advances in proportional to the wall
time with a ratio
defined by the setTimeScale(double) method.
The time in a runtime
starts at time 0.0. It stops advancing when the runtime is inactive or
stopped.
It resumes when the runtime resumes. Note that the sequential
event-driven type
of simulations is an extreme case of the J-Sim runtime if we set the
maximum
number of threads allowed to be 1 and the time scale to be positive
infinity.
A runtime is initially in the "inactive" state. It
automatically starts
and enters the "running" state when the activities (sending data) in
the component system start. Components generally operate in the passive
mode.
They do not send data until they receive data. Components of data
sources are
the only exception. They must be declared as ActiveComponent.
And an ActiveComponent
can be started by calling its run() method,
which start the
activities of a component system.
A runtime automatically enters the "inactive" state when there
is
no more activity in the component system. When a runtime is stopped by
the stop(...)
method, it enters the "suspended" state. When in this state, it will
not become "running" by starting an ActiveComponent.
The only way to leave the "suspended" state is calling one of the resume(...)
methods. The state diagram of a runtime is shown in Fig.5.
Figure 5: The state diagram of a runtime.

To set up a simulation runtime for a component system, we use
the following
command:
| Command |
Description |
attach_simulator
?event|<# threads>?
<path1>
?<path2>...? |
Hook up a simulation runtime with the component system
(specified by paths) and specify the maximum number of threads that can
be simultaneously active. Default is the maximum integer
value. Or one can specify to use a single-threaded
event-based simulation runtime. |
| EXAMPLE 9
Continued from Example
1. We now add a simulation runtime to the system, start the
simulation and play around the simulation controls.
TCL0> source inet3_ex1.tcl TCL0> pwd /example/
TCL0> set sim [attach_simulator .] TCL0> $sim info SMMT --- State:INACTIVE --- Workforce:1 # simulator name / state / # of threads allowed # of threads created: 0 # of events: 0 Event processing rate: NaN(#/s) # = # of events / wall time elapsed Time: 0.0 # current simulation time Wall time elapsed: 0.0 sec.
TCL0> cat h0,h5/s* # check the initial progress of the h0 source and h5 sink ----- /example/h0/source/ -----: # review: h0-h5 is one of the three connections being set up Progress: 0/0 ----- /example/h5/sink/ -----: Progress: 0/0 TCL0> ! h0,h5 run # run the source and the sink TCL0> $sim stop # and then stop the simulation TCL0> cat h0,h5/s* # check the progress of the source and the sink ----- /example/h0/source/ -----: Progress: 368/188416 # in #packets / #bytes ----- /example/h5/sink/ -----: Progress: 243/124416
TCL0> $sim info SMMT --- State:SUSPENDED --- Workforce:1 # of threads created: 5 # of events: 16035 Event processing rate: 7126.666666666667(#/s) Time: 113.75835680000017 Wall time elapsed: 2.25 sec.
TCL0> $sim reset # reset the runtime TCL0> $sim info SMMT --- State:INACTIVE --- Workforce:1 # of threads created: 0 # of events: 0 Event processing rate: NaN(#/s) Time: 0.0 Wall time elapsed: 0.0 sec.
|
In addition to save the runtime instance in a Tcl variable (as
"sim"
in the previous example), we can use the "rt"
command to access the runtime of a component system:
| Command |
Description |
rt
<path> |
Print the runtime information, including the current
state, the elapsed time, system and performance statistics, states of
threads and so on. |
rt
<path> <method>
?<argument1>...? |
Invoke a method of the runtime. |
The second form of the rt command
can be used to invoke one of the methods listed in Table
1. The methods regarding simulation controls are particularly
listed below:
| Command |
Description |
rt
<path> stop ?<time>? |
Stop the runtime immediately or at the specified time
later. |
rt
<path> stopAt <time> |
Stop the runtime at the time specified. |
rt
<path> resume |
Resume the runtime. |
rt
<path> resumeFor <time> |
Resume the runtime for the time specified and then stop
it. |
rt
<path> resumeTo <time> |
Resume the runtime and then stop it at the time
specified. |
rt
<path> reset |
Reset the runtime. |
| EXERCISE
Re-do Example
9 by using the rt command
instead of the runtime instance itself.
|
|
In addition to the rt
command,
J-Sim defines a set of commands to help starting (active) components,
resetting components and the runtime. They are particularly useful in
starting
and re-starting a scenario.
| Command |
Description |
run
<path1> ?<path2>...? |
Start the components (and the active components within)
specified by the paths. |
stop
<path1> ?<path2>...? |
Stop the components (and the active components within)
specified by the paths. |
resume
<path1> ?<path2>...? |
Resume the components (and the active components
within) specified by the paths. |
reset
<path1> ?<path2>...? |
Reset the components specified by the paths. |
reboot
<path1> ?<path2>...? |
Reset the components specified by the paths, and the
runtime(s) associated with the components. |
|
EXAMPLE 10
Similar to Example 9,
but using the rt,
run,
reset,
reboot
commands to play around the simulation controls.
TCL0> source inet3_ex1.tcl TCL0> pwd /example/
TCL0> attach_simulator . TCL0> cat h0,h5/s* # check the initial progress of the h0 source and h5 sink ----- /example/h0/source/ -----: # review: h0-h5 is one of the three connections being set up Progress: 0 ----- /example/h5/sink/ -----: Progress: 0 TCL0> run h0,h5 # run the source and the sink TCL0> rt . stop TCL0> cat h0,h5/s* # check the progress of the source and the sink ----- /example/h0/source/ -----: Progress: 507/259584 # in #packets / #bytes ----- /example/h5/sink/ -----: Progress: 381/195072 TCL0> rt . SMMT --- State:SUSPENDED --- Workforce:1 # of threads created: 5 # of events: 25055 Event processing rate: 10022.0(#/s) Time: 175.95363680000077 Wall time elapsed: 2.5 sec. TCL0> reset h0/source; # reset the source TCL0> cat h0,h5/s* ----- /example/h0/source/ -----: Progress: 0/0 ----- /example/h5/sink/ -----: Progress: 381/195072
TCL0> reboot .; # reboot the system TCL0> cat h0,h5/s* # everything should be ready for re-starting ----- /example/h0/source/ -----: Progress: 0/0 ----- /example/h5/sink/ -----: Progress: 0/0 TCL0> rt . SMMT --- State:INACTIVE --- Workforce:1 # of threads created: 0 # of events: 0 Event processing rate: NaN(#/s) Time: 0.0 Wall time elapsed: 0.0 sec.
|
A component is equipped with several flags which control how
different
types of diagnosis messages are exported by the component at the infoport
and event ports.
These messages include trace,
debug,
garbage,
error
and event.
For details of the formats of these messages, refer to the component
architecture white paper or the links to the message classes
above. This
section explains how to make use of these
flags to control components to export only the messages of interest and
how to
read the messages that are printed on the terminal.
The main commands for the purpose is setflag
and getflag.
The general
syntaxes are listed in the following table.
| Table
2: setflag and getflag. |
| Command |
Description |
setflag
<flag1> ?<flag2>...? true|false
?recursively? <path1>
?<path2>...? |
Enables/disables the flags of
the specified components (and components within if recursively). |
setflag
debug true|false -at <list of levels>
?recursively? <path1>
?<path2>...? |
Enables/disables the debug
flag of the specified components (and components within if recursively)
at the debug levels specified. See Section 2.2
for details. |
getflag
<path1> ?<path2>...? |
Print out what flags are
turned on at the components specified. |
|
Note that the setflag
command
can be generally used to enable/disable all the flags that are defined
in a
component class if the class follows the following "setter" pattern in
defining access of the flag:
public void set<flag>Enabled(boolean enabled_)
For example, the drcl.comp.lib.Relay
class defines the "echo" flag and it declares the following method
(note the capital "E" in "Echo"):
public void setEchoEnabled(boolean enabled_)
So it is valid to use setflag
to
enable/disable the echo flag of a relay component like the following
script:
TCL0> setflag echo true example/relay
By default, the getflag
command only examines the defined component flags and prints out the
enabled
ones. With the "-l" option, the command tries to find all the
flags defined for the component and then prints out all the enabled
ones.
EXAMPLE 11 (Aside from Example 1)
TCL0> mkdir drcl.comp.lib.Relay relay; TCL0> setflag echo copy true relay; TCL0> getflag relay /relay/: Enabled ErrorNotice EventExport
TCL0> getflag -l relay /relay/: Enabled ErrorNotice EventExport Copy Echo
|
In the following subsections, the discussion is mainly focused
on the defined
component flags.
Trace messages are exported whenever some data arrives at, or
departs from, a
component. They are the basic facility to verify the operations of a
system and,
when the system goes wrong, to identify the components that cause the
problem.
This facility is built in in J-Sim, component writers do not need to be
concerned when writing a component. One can further control the trace
messages
exported on individual ports of a component, and also use the "-at"
option of the setflag command to export only the "send" or
"data" (data arrival) traces.
| EXAMPLE 12
Continued from Example
1, this example enables the trace flag of one TCP component (h0/tcp)
to observe what kind of data arrives at and departs from a TCP
component. Specifically, we turn on the "send" and "data" traces for h0/tcp/down@,
and only the "data" trace for h0/tcp/up@.
|
1 TCL0> source inet3_ex1.tcl 2 TCL0> attach_simulator .; 3 TCL0> setflag trace true h0/tcp/down@ 4 TCL0> setflag trace true -at data h0/tcp/up@
5 TCL0> run .; rt . stopAt 10.0; # start the simulation and stop it at 10.0. 6 TCL0> DATA| 0.0| /example/h0/tcp/up@| BYTE_STREAM_QUERY| (new context) 7 DATA| 0.0| /example/h0/tcp/up@| BYTE_STREAM_SEND--offset:0--length:65536--data:<null_byte[]>| (new context) 8 SEND| 0.0| /example/h0/tcp/down@| sz562(INET)sz20--src:----dest:#5--prot:0--TTL:0/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq0--AWND:0--TS0.0__<EMPTY_BODY>__>__ 9 DATA| 3.1498191999999987| /example/h0/tcp/down@| sz50(INET)sz20--src:#5--dest:#0--prot:0--TTL:3/255--ToS:#0__<sz30(TCP)sz30--s:0--d:0--seq0--AWND:65536--TS-1.0--Ack:512,0.0__<EMPTY_BODY>__>__| (new context) 10 SEND| 3.1498191999999987| /example/h0/tcp/down@| sz562(INET)sz20--src:----dest:#5--prot:0--TTL:0/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq512--AWND:0--TS3.1498191999999987__<EMPTY_BODY>__>__ 11 SEND| 3.1498191999999987| /example/h0/tcp/down@| sz562(INET)sz20--src:----dest:#5--prot:0--TTL:0/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq1024--AWND:0--TS3.1498191999999987__<EMPTY_BODY>__>__ 12 DATA| 3.1498191999999987| /example/h0/tcp/up@| BYTE_STREAM_SEND--offset:0--length:512--data:<null_byte[]>| (new context) 13 DATA| 6.2996384| /example/h0/tcp/down@| sz50(INET)sz20--src:#5--dest:#0--prot:0--TTL:3/255--ToS:#0__<sz30(TCP)sz30--s:0--d:0--seq0--AWND:65536--TS-1.0--Ack:1024,3.1498191999999987__<EMPTY_BODY>__>__| (new context) 14 SEND| 6.2996384| /example/h0/tcp/down@| sz562(INET)sz20--src:----dest:#5--prot:0--TTL:0/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq1536--AWND:0--TS6.2996384__<EMPTY_BODY>__>__ 15 SEND| 6.2996384| /example/h0/tcp/down@| sz562(INET)sz20--src:----dest:#5--prot:0--TTL:0/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq2048--AWND:0--TS6.2996384__<EMPTY_BODY>__>__ 16 DATA| 6.2996384| /example/h0/tcp/up@| BYTE_STREAM_SEND--offset:0--length:512--data:<null_byte[]>| (new context) 17 DATA| 6.7492384| /example/h0/tcp/down@| sz50(INET)sz20--src:#5--dest:#0--prot:0--TTL:3/255--ToS:#0__<sz30(TCP)sz30--s:0--d:0--seq0--AWND:65536--TS-1.0--Ack:1536,3.1498191999999987__<EMPTY_BODY>__>__| (new context) 18 SEND| 6.7492384| /example/h0/tcp/down@| sz562(INET)sz20--src:----dest:#5--prot:0--TTL:0/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq2560--AWND:0--TS6.7492384__<EMPTY_BODY>__>__ 19 SEND| 6.7492384| /example/h0/tcp/down@| sz562(INET)sz20--src:----dest:#5--prot:0--TTL:0/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq3072--AWND:0--TS6.7492384__<EMPTY_BODY>__>__ 20 DATA| 6.7492384| /example/h0/tcp/up@| BYTE_STREAM_SEND--offset:0--length:512--data:<null_byte[]>| (new context)
|
| At time 0.0 (line 6-8), the
application (BulkSource) fills up the sending buffer at TCP and TCP
sends the first packet at its down port. After a round-trip delay, at
line 9, the ACK of the first data packet comes back, the TCP sends out
two data packets (due to increase of window size by one) (line 10-11)
and the application pushes one unit (512 bytes) of data to keep the
sending buffer full (line 12). Same process repeats at line
13-16 and line 17-20 for receiving ACKs of the second and the third
data packets respectively. |
While trace messages can be used to identify the erroneous
components,
exporting of appropriate debug messages help further diagnose what
exactly the
problems are. J-Sim provides standard API's to export debug
messages.
The following block of codes serves as a template of exporting a debug
message:
if (isDebugEnabled()) { debug(.../* the debug messsage */); }
|
To have finer controls on exporting of debug messages, J-Sim
provides API's
to define and enable/disable up to 16 debug levels:
| Method |
Description |
String[]
getDebugLevelNames() |
Returns the names of defined debug
levels or null if no debug level is defined.
A subclass should override this method if it defines any debug levels. |
void
setDebugEnabledAt(boolean enabled_,
int level_) |
Enables/disables the debug level(s)
specified where 0 <= level_ < 16
specifies a single level or one may specify multiple levels in a bit
mask with a 4-bit shift, i.e., 24
< level_ < 220. |
void
setDebugEnabledAt(boolean enabled_,
int[] levels_) |
Enables/disables multiple debug
levels. Each level value in levels_ may be
specified as described above. |
void
setDebugEnabledAt(boolean enabled_,
String[] levels_) |
Enables/disables multiple debug
levels by using debug level names. |
boolean
isDebugEnabledAt(int level_) |
Returns true if the specified debug
level(s) are all enabled. The argument may be specified as described
above. |
When writing a component with debug levels defined, one should
follow the
following code block to export a debug message of a certain debug level:
if (isDebugEnabled() && isDebugEnabledAt(.../*level*/) { debug(.../* the debug messsage */); }
|
| EXAMPLE 13
This example shows part of the codes in drcl.inet.transport.TCP
that define the debug levels for this component.
public class TCP extends drcl.inet.Protocol { // initialization codes... ...
// defining five debug levels... static final String[] DEBUG_LEVELS = {"ack", "dupack", "send", "timeout", "rtt", "sample"}; public static final int DEBUG_ACK = 0; // receipt of acks public static final int DEBUG_DUPACK = 1; // receipt of duplicate acks public static final int DEBUG_SEND = 2; // send packets public static final int DEBUG_TIMEOUT = 3; // retransmission timeout public static final int DEBUG_RTT = 4; // update of RTT estimation public static final int DEBUG_SAMPLE = 5; // important samples of events in other debug levels
// Component subclass that defines debug levels must implement this method public String[] getDebugLevelNames() { return DEBUG_LEVELS; } ...
// fields, methods...
... // somewhere in some method that reports RTT estimation when the estimation is updated if (isDebugEnabled() && isDebugEnabledAt(DEBUG_RTT)) { debug(.../* message reporting current RTT estimation */); } ... }
|
With appropriate setting in the codes, one may use the second
form of setflag
(Table 2) to enable/disable
debug levels of a component,
and getflag
to display what debug
levels are defined and which of them are enabled.
| EXAMPLE 14 (Aside from Example 1)
In this example, we exercise the setflag
and getflag
commands to enable/disable/display the debug levels and the debug flag
on a TCP component.
|
TCL0> mkdir drcl.inet.transport.TCP tcp; TCL0> getflag tcp /tcp/: Enabled ErrorNotice EventExport (available debug levels: ack dupack send timeout rtt)
TCL0> setflag debug true tcp TCL0> getflag tcp /tcp/: Enabled Debug (ack dupack send timeout rtt) ErrorNotice EventExport (available debug levels: ack dupack send timeout rtt) ;# all debug levels are enabled
TCL0> setflag debug false tcp TCL0> getflag tcp /tcp/: Enabled ErrorNotice EventExport (available debug levels: ack dupack send timeout rtt) ;# all debug levels are disabled
TCL0> setflag debug true -at "dupack timeout" tcp TCL0> getflag tcp /tcp/: Enabled Debug (dupack timeout) ErrorNotice EventExport (available debug levels: ack dupack send timeout rtt) ;# two debug levels are enabled as specified
|
| EXAMPLE 15
Continued from Example
1, this example enables the "dupack" (receipt of duplicate
acks) and "timeout" (retransmission timeout) debug levels on all TCP
components to observe how TCP behaves upon these events.
|
TCL0> source inet3_ex1.tcl TCL0> attach_simulator .; TCL0> setflag debug true -at "dupack timeout" .../tcp; TCL0> run .; rt . stopAt 40; # start the simulation and stop it at 40.0. TCL0> DEBUG| 17.090038400000005| /example/h1/tcp/| DUPACK3: 8, window shrinked: window=(8,17,15,progress:9/7,CWMD:7)(4096,8704,7680,progress:4608/3584,CWND:3584.0), retransmit 8 DEBUG| 18.888438400000005| /example/h0/tcp/| DUPACK3: 8, window shrinked: window=(8,17,15,progress:9/7,CWMD:7)(4096,8704,7680,progress:4608/3584,CWND:3584.0), retransmit 8 DEBUG| 20.237238400000006| /example/h2/tcp/| DUPACK3: 14, window shrinked: window=(14,29,24,progress:15/10,CWMD:10)(7168,14848,12288,progress:7680/5120,CWND:5120.0), retransmit 14 DEBUG| 20.686838400000006| /example/h2/tcp/| DUPACK4: 14, fast_recovery, window += MSS: window=(14,29,25,progress:15/11,CWMD:11)(7168,14848,12800,progress:7680/5632,CWND:5632.0) DEBUG| 21.136438400000007| /example/h2/tcp/| DUPACK5: 14, fast_recovery, window += MSS: window=(14,29,26,progress:15/12,CWMD:12)(7168,14848,13312,progress:7680/6144,CWND:6144.0) DEBUG| 21.586038400000007| /example/h2/tcp/| DUPACK6: 14, fast_recovery, window += MSS: window=(14,29,27,progress:15/13,CWMD:13)(7168,14848,13824,progress:7680/6656,CWND:6656.0) DEBUG| 22.035638400000007| /example/h2/tcp/| DUPACK7: 14, fast_recovery, window += MSS: window=(14,29,28,progress:15/14,CWMD:14)(7168,14848,14336,progress:7680/7168,CWND:7168.0) DEBUG| 22.485238400000007| /example/h1/tcp/| DUPACK4: 8, fast_recovery, window += MSS: window=(8,17,16,progress:9/8,CWMD:8)(4096,8704,8192,progress:4608/4096,CWND:4096.0) DEBUG| 23.384438400000008| /example/h0/tcp/| DUPACK4: 8, fast_recovery, window += MSS: window=(8,17,16,progress:9/8,CWMD:8)(4096,8704,8192,progress:4608/4096,CWND:4096.0) DEBUG| 23.834038400000008| /example/h0/tcp/| DUPACK5: 8, fast_recovery, window += MSS: window=(8,17,17,progress:9/9,CWMD:9)(4096,8704,8704,progress:4608/4608,CWND:4608.0) DEBUG| 34.13483840000001| /example/h1/tcp/| RXT TIMEOUT: rxtseq=10/5120 DEBUG| 34.13483840000001| /example/h1/tcp/| TIMEOUT: timer backoff to 2 times DEBUG| 35.18363840000001| /example/h0/tcp/| RXT TIMEOUT: rxtseq=10/5120 DEBUG| 35.18363840000001| /example/h0/tcp/| TIMEOUT: timer backoff to 2 times DEBUG| 36.43323840000001| /example/h2/tcp/| RXT TIMEOUT: rxtseq=16/8192 DEBUG| 36.43323840000001| /example/h2/tcp/| TIMEOUT: timer backoff to 2 times
|
Data is discarded by a component, due to, for example, some
capacity or policy
setting, in the form of garbage messages. Different from other types of
messages, garbage messages may be used as part of the system
operation.
For example, a drcl.net.tool.NamTrace
component takes garbage messages to
generate appropriate "drop" events in a NAM trace. In such a
case, one may enable exporting the garbage messages but disable their
display on
a displayable instrument component by turning on the garbage flag and
turning
off the garbage display flag.
| EXAMPLE 16 (Aside from Example 1)
In this example, we exercise the setflag
and getflag
commands to enable/disable/display the garbage and garbage display
flags on a queue component.
TCL0> mkdir drcl.inet.core.queue.DropTail q; TCL0> getflag q /q/: Enabled ErrorNotice EventExport # the garbage and garbageDisplay flags are disabled by default TCL0> setflag garbagedisplay true q TCL0> getflag q /q/: Enabled Garbage(display) ErrorNotice EventExport # the garbage and garbageDisplay flags are both enabled TCL0> setflag garbage false q TCL0> getflag q /q/: Enabled ErrorNotice EventExport # the garbage and garbageDisplay flags are both disabled TCL0> setflag garbage true q TCL0> getflag q /q/: Enabled Garbage ErrorNotice EventExport # only the garbage flag is enabled
|
| EXAMPLE 17
Continued from Example
1, this example enables the garbage flag of the queue
component on the bottleneck link, as well as the "sample" (important
events) debug level on h0/tcp to observe how
TCP reacts upon these events.
|
TCL0> source inet3_ex1.tcl TCL0> attach_simulator . TCL0> setflag debug true -at sample h0/tcp TCL0> setflag garbagedisplay true n3/csl/q3 TCL0> run .; rt . stopAt 40; # start the simulation and stop it at 40.0. TCL0> DEBUG| 0.0| /example/h0/tcp/| Sending: SeqNo=0, Size=512 DEBUG| 3.1498191999999987| /example/h0/tcp/| ACK: 1/512, window=(1,1,3,progress:0/2,CWMD:2)(512,512,1536,progress:0/1024,CWND:1024.0), timeout adjusted to 12.4498192 DEBUG| 3.1498191999999987| /example/h0/tcp/| Sending: SeqNo=1, Size=512 DEBUG| 3.1498191999999987| /example/h0/tcp/| Sending: SeqNo=2, Size=512 DEBUG| 6.2996384| /example/h0/tcp/| ACK: 2/1024, window=(2,3,5,progress:1/3,CWMD:3)(1024,1536,2560,progress:512/1536,CWND:1536.0), timeout adjusted to 14.0996384 DEBUG| 6.2996384| /example/h0/tcp/| Sending: SeqNo=3, Size=512 DEBUG| 6.2996384| /example/h0/tcp/| Sending: SeqNo=4, Size=512 DEBUG| 6.7492384| /example/h0/tcp/| ACK: 3/1536, window=(3,5,7,progress:2/4,CWMD:4)(1536,2560,3584,progress:1024/2048,CWND:2048.0), timeout adjusted to 13.9492384 DEBUG| 6.7492384| /example/h0/tcp/| Sending: SeqNo=5, Size=512 DEBUG| 6.7492384| /example/h0/tcp/| Sending: SeqNo=6, Size=512 GARBAGE| 8.848537600000002| /example/n3/csl/q3/| sz562(INET)sz20--src:#2--dest:#7--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq7168--AWND:0--TS8.547638400000002__<EMPTY_BODY>__>__| exceeds capacity GARBAGE| 9.298137600000004| /example/n3/csl/q3/| sz562(INET)sz20--src:#1--dest:#6--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq4096--AWND:0--TS8.997238400000004__<EMPTY_BODY>__>__| exceeds capacity GARBAGE| 9.747737600000006| /example/n3/csl/q3/| sz562(INET)sz20--src:#1--dest:#6--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq5120--AWND:0--TS9.446838400000006__<EMPTY_BODY>__>__| exceeds capacity GARBAGE| 10.197337600000006| /example/n3/csl/q3/| sz562(INET)sz20--src:#1--dest:#6--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq6144--AWND:0--TS9.896438400000006__<EMPTY_BODY>__>__| exceeds capacity GARBAGE| 10.646937600000006| /example/n3/csl/q3/| sz562(INET)sz20--src:#1--dest:#6--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq7168--AWND:0--TS10.346038400000007__<EMPTY_BODY>__>__| exceeds capacity DEBUG| 10.795638400000007| /example/h0/tcp/| ACK: 4/2048, window=(4,7,9,progress:3/5,CWMD:5)(2048,3584,4608,progress:1536/2560,CWND:2560.0), timeout adjusted to 18.595638400000006 DEBUG| 10.795638400000007| /example/h0/tcp/| Sending: SeqNo=7, Size=512 DEBUG| 10.795638400000007| /example/h0/tcp/| Sending: SeqNo=8, Size=512 GARBAGE| 11.096537600000007| /example/n3/csl/q3/| sz562(INET)sz20--src:#0--dest:#5--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq4096--AWND:0--TS10.795638400000007__<EMPTY_BODY>__>__| exceeds capacity DEBUG| 11.245238400000007| /example/h0/tcp/| ACK: 5/2560, window=(5,9,11,progress:4/6,CWMD:6)(2560,4608,5632,progress:2048/3072,CWND:3072.0), timeout adjusted to 19.745238400000005 DEBUG| 11.245238400000007| /example/h0/tcp/| Sending: SeqNo=9, Size=512 DEBUG| 11.245238400000007| /example/h0/tcp/| Sending: SeqNo=10, Size=512 GARBAGE| 11.546137600000007| /example/n3/csl/q3/| sz562(INET)sz20--src:#0--dest:#5--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq5120--AWND:0--TS11.245238400000007__<EMPTY_BODY>__>__| exceeds capacity DEBUG| 11.694838400000007| /example/h0/tcp/| ACK: 6/3072, window=(6,11,13,progress:5/7,CWMD:7)(3072,5632,6656,progress:2560/3584,CWND:3584.0), timeout adjusted to 20.594838400000008 DEBUG| 11.694838400000007| /example/h0/tcp/| Sending: SeqNo=11, Size=512 DEBUG| 11.694838400000007| /example/h0/tcp/| Sending: SeqNo=12, Size=512 GARBAGE| 11.995737600000007| /example/n3/csl/q3/| sz562(INET)sz20--src:#0--dest:#5--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq6144--AWND:0--TS11.694838400000007__<EMPTY_BODY>__>__| exceeds capacity DEBUG| 12.144438400000007| /example/h0/tcp/| ACK: 7/3584, window=(7,13,15,progress:6/8,CWMD:8)(3584,6656,7680,progress:3072/4096,CWND:4096.0), timeout adjusted to 21.644438400000006 DEBUG| 12.144438400000007| /example/h0/tcp/| Sending: SeqNo=13, Size=512 DEBUG| 12.144438400000007| /example/h0/tcp/| Sending: SeqNo=14, Size=512 GARBAGE| 12.445337600000007| /example/n3/csl/q3/| sz562(INET)sz20--src:#0--dest:#5--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq7168--AWND:0--TS12.144438400000007__<EMPTY_BODY>__>__| exceeds capacity GARBAGE| 12.894937600000008| /example/n3/csl/q3/| sz562(INET)sz20--src:#2--dest:#7--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq8192--AWND:0--TS12.594038400000008__<EMPTY_BODY>__>__| exceeds capacity GARBAGE| 13.344537600000008| /example/n3/csl/q3/| sz562(INET)sz20--src:#2--dest:#7--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq9216--AWND:0--TS13.043638400000008__<EMPTY_BODY>__>__| exceeds capacity GARBAGE| 13.794137600000008| /example/n3/csl/q3/| sz562(INET)sz20--src:#2--dest:#7--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq10240--AWND:0--TS13.493238400000008__<EMPTY_BODY>__>__| exceeds capacity GARBAGE| 14.243737600000008| /example/n3/csl/q3/| sz562(INET)sz20--src:#2--dest:#7--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq11264--AWND:0--TS13.942838400000008__<EMPTY_BODY>__>__| exceeds capacity GARBAGE| 14.693337600000008| /example/n3/csl/q3/| sz562(INET)sz20--src:#2--dest:#7--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq12288--AWND:0--TS14.392438400000009__<EMPTY_BODY>__>__| exceeds capacity GARBAGE| 15.142937600000009| /example/n3/csl/q3/| sz562(INET)sz20--src:#2--dest:#7--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq13312--AWND:0--TS14.842038400000009__<EMPTY_BODY>__>__| exceeds capacity GARBAGE| 15.592537600000009| /example/n3/csl/q3/| sz562(INET)sz20--src:#2--dest:#7--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq14336--AWND:0--TS15.291638400000009__<EMPTY_BODY>__>__| exceeds capacity GARBAGE| 16.042137600000007| /example/n3/csl/q3/| sz562(INET)sz20--src:#1--dest:#6--prot:6--TTL:2/255--ToS:#0__<sz542(TCP)sz30--s:0--d:0--seq8192--AWND:0--TS15.74123840000001__<EMPTY_BODY>__>__| exceeds capacity DEBUG| 17.539638400000005| /example/h0/tcp/| ACK: 8/4096, window=(8,15,17,progress:7/9,CWMD:9)(4096,7680,8704,progress:3584/4608,CWND:4608.0), timeout adjusted to 28.739638400000004 DEBUG| 17.539638400000005| /example/h0/tcp/| Sending: SeqNo=15, Size=512 DEBUG| 17.539638400000005| /example/h0/tcp/| Sending: SeqNo=16, Size=512 DEBUG| 18.888438400000005| /example/h0/tcp/| DUPACK3: 8, window shrinked: window=(8,17,15,progress:9/7,CWMD:7)(4096,8704,7680,progress:4608/3584,CWND:3584.0), retransmit 8 DEBUG| 18.888438400000005| /example/h0/tcp/| RESending: SeqNo=8, Size=512 DEBUG| 23.384438400000008| /example/h0/tcp/| DUPACK4: 8, fast_recovery, window += MSS: window=(8,17,16,progress:9/8,CWMD:8)(4096,8704,8192,progress:4608/4096,CWND:4096.0) DEBUG| 23.834038400000008| /example/h0/tcp/| DUPACK5: 8, fast_recovery, window += MSS: window=(8,17,17,progress:9/9,CWMD:9)(4096,8704,8704,progress:4608/4608,CWND:4608.0) DEBUG| 24.283638400000008| /example/h0/tcp/| ACK: 10/5120, end of fast recovery, window restored: window=(10,17,14,progress:7/4,CWMD:4)(5120,8704,7168,progress:3584/2048,CWND:2048.0) DEBUG| 24.283638400000008| /example/h0/tcp/| ACK: 10/5120, window=(10,17,14,progress:7/4,CWMD:4)(5120,8704,7168,progress:3584/2048,CWND:2176.0), timeout adjusted to 35.18363840000001 DEBUG| 35.18363840000001| /example/h0/tcp/| RXT TIMEOUT: rxtseq=10/5120 DEBUG| 35.18363840000001| /example/h0/tcp/| RESending: SeqNo=10, Size=512 DEBUG| 37.43425759999999| /example/h0/tcp/| (*********) Left slow start and entered congestion avoidance, sthld=1024 DEBUG| 37.43425759999999| /example/h0/tcp/| ACK: 12/6144, window=(12,11,14,progress:-1/2,CWMD:2)(6144,5632,7168,progress:-512/1024,CWND:1024.0), timeout adjusted to 48.53425759999999 DEBUG| 37.43425759999999| /example/h0/tcp/| RESending: SeqNo=12, Size=512 DEBUG| 37.43425759999999| /example/h0/tcp/| RESending: SeqNo=13, Size=512 DEBUG| 39.98487679999996| /example/h0/tcp/| ACK: 14/7168, window=(14,14,16,progress:0/2,CWMD:2)(7168,7168,8192,progress:0/1024,CWND:1280.0), timeout adjusted to 50.68487679999996 DEBUG| 39.98487679999996| /example/h0/tcp/| RESending: SeqNo=14, Size=512 DEBUG| 39.98487679999996| /example/h0/tcp/| RESending: SeqNo=15, Size=512
|
A component may be disabled from receiving data by turning off
the
"component" flag. In simulation, this feature is useful to set up a
failure. For example, disable a link to simulate a link
failure, disable a
node to simulate a node failure or disable a protocol component to
simulate a
protocol failure. To be precise, a disabled component does
not respond to
arriving data, but it may still originate data especially if the
component is an
active component (drcl.comp.ActiveComponent).
| EXAMPLE 18 (Aside from Example 1)
In this example, we exercise the setflag
and getflag
commands to enable/disable/display the "component" flag on a counter
component. (note: this example only works with J-Sim v1.2.1-patch1)
TCL0> mkdir drcl.comp.tool.DataCounter counter TCL0> mkdir counter/in@; TCL0> getflag counter /counter/: Enabled ErrorNotice EventExport TCL0> cat counter ----- /counter/ -----: Nothing being counted.
TCL0> inject "a string" counter/in@ TCL0> cat counter ----- /counter/ -----: #Ports being monitored: 1 /counter/in@: 1
TCL0> setflag component false counter TCL0> inject "string 2" counter/in@ TCL0> cat counter ----- /counter/ -----: #Ports being monitored: 1 /counter/in@: 1
TCL0> getflag counter /counter/: ErrorNotice EventExport TCL0> setflag component true counter TCL0> inject "string 3" counter/in@ TCL0> cat counter ----- /counter/ -----: #Ports being monitored: 1 /counter/in@: 2
|
| EXAMPLE 19
Continued from Example
1, this example "turns off" the link between n3
and n4 at time 5.0 and brings it back on at
time 60.0.
|
TCL0> source inet3_ex1.tcl TCL0> attach_simulator . TCL0> setflag debug true -at "sample" h0/tcp TCL0> setflag garbagedisplay true n3/csl/q3 TCL0> run .; rt . stopAt 5.0; # run the simulation until time 5.0 DEBUG| 0.0| /example/h0/tcp/| Sending: SeqNo=0, Size=512 DEBUG| 3.1498191999999987| /example/h0/tcp/| ACK: 1/512, window=(1,1,3,progress:0/2,CWMD:2)(512,512,1536,progress:0/1024,CWND:1024.0), timeout adjusted to 12.4498192 DEBUG| 3.1498191999999987| /example/h0/tcp/| Sending: SeqNo=1, Size=512 DEBUG| 3.1498191999999987| /example/h0/tcp/| Sending: SeqNo=2, Size=512 TCL0> setflag component false n3/3@/-/.. # disable the link between n3 and n4 TCL0> rt . resumeTo 60.0; # run the simulation until time 60.0 DEBUG| 12.4498192| /example/h0/tcp/| RXT TIMEOUT: rxtseq=1/512 DEBUG| 12.4498192| /example/h0/tcp/| RESending: SeqNo=1, Size=512 DEBUG| 31.0498192| /example/h0/tcp/| RXT TIMEOUT: rxtseq=1/512 DEBUG| 31.0498192| /example/h0/tcp/| RESending: SeqNo=1, Size=512 TCL0> setflag component true n3/3@/-/.. # bring back the link TCL0> rt . resumeTo 80.0 # run the simulation until time 80.0 TCL0> DEBUG| 68.2498192| /example/h0/tcp/| RXT TIMEOUT: rxtseq=1/512 DEBUG| 68.2498192| /example/h0/tcp/| RESending: SeqNo=1, Size=512 DEBUG| 70.50043839999998| /example/h0/tcp/| (*********) Left slow start and entered congestion avoidance, sthld=1024 DEBUG| 70.50043839999998| /example/h0/tcp/| ACK: 2/1024, window=(2,2,4,progress:0/2,CWMD:2)(1024,1024,2048,progress:0/1024,CWND:1024.0), timeout adjusted to 79.00043839999998 DEBUG| 70.50043839999998| /example/h0/tcp/| RESending: SeqNo=2, Size=512 DEBUG| 70.50043839999998| /example/h0/tcp/| Sending: SeqNo=3, Size=512 DEBUG| 72.75105759999995| /example/h0/tcp/| ACK: 3/1536, window=(3,4,5,progress:1/2,CWMD:2)(1536,2048,2560,progress:512/1024,CWND:1280.0), timeout adjusted to 80.55105759999995 DEBUG| 72.75105759999995| /example/h0/tcp/| Sending: SeqNo=4, Size=512 DEBUG| 73.20065759999996| /example/h0/tcp/| ACK: 4/2048, window=(4,5,7,progress:1/3,CWMD:3)(2048,2560,3584,progress:512/1536,CWND:1536.0), timeout adjusted to 79.90065759999996 DEBUG| 73.20065759999996| /example/h0/tcp/| Sending: SeqNo=5, Size=512 DEBUG| 73.20065759999996| /example/h0/tcp/| Sending: SeqNo=6, Size=512 DEBUG| 75.00167679999993| /example/h0/tcp/| ACK: 5/2560, window=(5,7,8,progress:2/3,CWMD:3)(2560,3584,4096,progress:1024/1536,CWND:1706.0), timeout adjusted to 81.30167679999992 DEBUG| 75.00167679999993| /example/h0/tcp/| Sending: SeqNo=7, Size=512 DEBUG| 75.45127679999993| /example/h0/tcp/| ACK: 6/3072, window=(6,8,9,progress:2/3,CWMD:3)(3072,4096,4608,progress:1024/1536,CWND:1876.0), timeout adjusted to 81.35127679999994 DEBUG| 75.45127679999993| /example/h0/tcp/| Sending: SeqNo=8, Size=512 DEBUG| 75.90087679999993| /example/h0/tcp/| ACK: 7/3584, window=(7,9,10,progress:2/3,CWMD:3)(3584,4608,5120,progress:1024/1536,CWND:2046.0), timeout adjusted to 81.00087679999993 DEBUG| 75.90087679999993| /example/h0/tcp/| Sending: SeqNo=9, Size=512 DEBUG| 77.2522959999999| /example/h0/tcp/| ACK: 8/4096, window=(8,10,12,progress:2/4,CWMD:4)(4096,5120,6144,progress:1024/2048,CWND:2216.0), timeout adjusted to 82.15229599999991 DEBUG| 77.2522959999999| /example/h0/tcp/| Sending: SeqNo=10, Size=512 DEBUG| 77.2522959999999| /example/h0/tcp/| Sending: SeqNo=11, Size=512 DEBUG| 77.7018959999999| /example/h0/tcp/| ACK: 9/4608, window=(9,12,13,progress:3/4,CWMD:4)(4608,6144,6656,progress:1536/2048,CWND:2344.0), timeout adjusted to 82.40189599999991 DEBUG| 77.7018959999999| /example/h0/tcp/| Sending: SeqNo=12, Size=512 DEBUG| 78.15149599999991| /example/h0/tcp/| ACK: 10/5120, window=(10,13,14,progress:3/4,CWMD:4)(5120,6656,7168,progress:1536/2048,CWND:2472.0), timeout adjusted to 82.65149599999991 DEBUG| 78.15149599999991| /example/h0/tcp/| Sending: SeqNo=13, Size=512 DEBUG| 79.50291519999988| /example/h0/tcp/| ACK: 11/5632, window=(11,14,16,progress:3/5,CWMD:5)(5632,7168,8192,progress:1536/2560,CWND:2600.0), timeout adjusted to 83.80291519999987 DEBUG| 79.50291519999988| /example/h0/tcp/| Sending: SeqNo=14, Size=512 DEBUG| 79.50291519999988| /example/h0/tcp/| Sending: SeqNo=15, Size=512 DEBUG| 79.95251519999988| /example/h0/tcp/| ACK: 12/6144, window=(12,16,17,progress:4/5,CWMD:5)(6144,8192,8704,progress:2048/2560,CWND:2702.0), timeout adjusted to 84.15251519999988 DEBUG| 79.95251519999988| /example/h0/tcp/| Sending: SeqNo=16, Size=512
|
|
The expression "n3/3@/-/.."
refers to the component which is the host component of the port that is
connected to "n3/3@",
that is, the link component between nodes n3 and n4.
|
The script
command schedules
a script to be executed by the specified runtime at a specified future
time
instance. It is useful in constructing a complex simulation
scenario by
scripting. The basic form of the command is as follows:
-
script <script> -at <time> ?later? -on <simulation_runtime>
?-period <period>?
If "later" is present, then the script is executed at a
relative
future time instance. If the period option is present, the script
schedules
itself recursively in the specified period after being executed the
first time
at the specified time instance.
| EXAMPLE 20
In this example, we complete a scenario from Example 1. The
scenario starts source 0 at time 0.0, source 1 at time 200.0, source 2
at time 400.0 and stops at time 600.0. And also we print the
simulation time every 100.0 seconds.
... (Example 1) ... set sim [attach_simulator .] $sim stop; # stop the simulation first to complete the scenario run h0/source h5-7/sink; # start source 0 and all sinks script "run h1/source" -at 200.0 -on $sim; # schedule source 1 script "run h2/source" -at 400.0 -on $sim; # schedule source 2 script "puts [$sim getTime]" -at 100.0 -period 100.0 -on $sim; # to print simulation time $sim resumeTo 600.0; # run the simulation until 600.0
|
The wait_until
command blocks
the terminal input until the specified condition becomes true. The
scenario in
the previous example may be constructed using wait_until:
| EXAMPLE 21
Similar to the
previous example, the scenario starts source 0 at time 0.0,
source 1 at time 200.0, source 2 at time 400.0 and stops at time 600.0.
... (Example 1) ... set sim [attach_simulator .] run h0/source h5-7/sink; # start source 0 and all sinks $sim stopAt 200.0 wait_until {$sim isStopped} run h1/source; # start source 1 $sim stopAt 400.0 wait_until {$sim isStopped} run h2/source; # start source 2 $sim stopAt 600.0 wait_until {$sim isStopped}
|
Note that wait_until
cannot be used in other commands/statements such as if, for, foreach,
while and
so on. The reason is that this command
can only block the
interpreter after the command is executed (the
argument script cannot be
executed while the command is executed). If this command is contained
in another
command, then the interpreter is blocked after the containing command
is
finished, which is not what this command is about. The problem can be
solved if
the interpreter is made not to block itself while it is executing a
command.
The explore
command
explores the component topology viewed from a specific
component. It is
particularly useful in reviewing the network topology online. One may
specify
components being treated as transparent or excluded during topology
exploration.
The usage is demonstrated in the following example.
Similar to the diagnosis procedure, collecting results in
J-Sim replies on
two things:
- components which originate interested results; and
- appropriate instrument components
which collect the results.
This section introduces three instrument components that help
to collect
results for different purposes.
The drcl.comp.io.FileComponent
component saves incoming data to a file.
To use it, connect a FileComponent to the
port at which the target component
originates interested results. Moreover, the FileComponent
component recognizes component
events. It can filter out other fields in a
component event and only
print out the information of time and the event object if the "event
filtering" flag is enabled. By default, the flag is disabled.
| EXAMPLE 23
In this example, we complete another scenario from Example 1. The
scenario starts source 0 and stops the simulation at time
100.0. The CWND events originated by h0/tcp are saved in a
file named "cwnd.trace".
... (Example 1) ... set cwndFile_ [mkdir drcl.comp.io.FileComponent .cwndFile] setflag EventFiltering true $cwndFile_ $cwndFile_ open "cwnd.trace" attach -c $cwndFile_/in@ -to h0/tcp/cwnd@
set sim [attach_simulator .] run h0/source h5/sink; # start source 0 and sink 0 $sim stopAt 20.0; # stop the simulation at time 20.0
The resulting trace file looks like the following:
2.2506192 2.0 4.501238399999999 3.0 4.9508384 4.0 6.751857599999998 5.0 7.201457599999999 6.0 7.651057599999999 7.0 8.1006576 8.0 9.0024768 9.0 9.452076800000002 10.0 9.901676800000002 11.0 10.351276800000003 12.0 10.800876800000003 13.0 11.250476800000003 14.0 11.700076800000003 15.0 12.149676800000003 16.0 12.599276800000004 16.0625 13.048876800000004 16.125 13.498476800000004 16.1875 13.948076800000004 16.25 14.397676800000005 16.3125 14.847276800000005 16.375 15.296876800000005 16.4375 15.746476800000005 16.5 16.196076800000004 16.5625 16.6456768 16.625 17.0952768 16.6875 17.5448768 16.75 17.9944768 16.8125 18.4440768 16.875 18.8936768 16.9375
|
The drcl.comp.tool.Plotter
component displays incoming data on an xy
plot. The Plotter component is able to display multiple
datasets on a plot
as well as display multiple plots at the same time. Multiple
plots are
ordered by the ID's starting from 0. So as the datasets on a
plot. The
port ID and the port group ID of the port at which data arrives are
used as the
dataset ID and the plot ID respectively, to draw the data on its
corresponding
plot. For example, the data coming in at port
2@5 is drawn as the point in
dataset 2 of plot 5.
The Plotter component recognizes a wide range of data
format. If the
incoming data is an event,
then the
event object is treated as incoming data and further processed as
follows. If
the data is a String, then the String is parsed to get the raw data
which is
further processed as follows. If the data is a double array,
then the
first element is treated as x-value and the second element as
y-value. If
the data is a Double/drcl.data.DoubleObj
value, then the value is treated as y-value and
the current time as x-value.
| EXAMPLE 24
Same scenario as in Example
20, this example outputs the CWND events of all the TCP
components to the Plotter component to observe the CWND events online.
... (Example 1) ... set plot_ [mkdir drcl.comp.tool.Plotter .plot] foreach i "0 1 2" { attach -c $plot_/$i@0 -to h$i/tcp/cwnd@ } set sim [attach_simulator .] $sim stop; # stop the simulation first to complete the scenario run h0/source h5-7/sink; # start source 0 and all sinks script "run h1/source" -at 200.0 -on $sim; # schedule source 1 script "run h2/source" -at 400.0 -on $sim; # schedule source 2 script "puts [$sim getTime]" -at 100.0 -period 100.0 -on $sim; # to print simulation time $sim resumeTo 600.0; # run the simulation until 600.0
The result is displayed online as shown in the following
window:
|
Instead of displaying the plots online, Plotter may also be
used to save
results in the defined format by outputting the results to a FileComponent.
| EXAMPLE 25
This example is the same as the previous one except that the
results are saved in a file named "ex1.plot" instead of being displayed
online.
... (Example 1) ... set plot_ [mkdir drcl.comp.tool.Plotter .plot] set file_ [mkdir drcl.comp.io.FileComponent .file] $file_ open "ex1.plot" connect -c $plot_/.output@ -to $file_/in@ setflag plot false $plot_ foreach i "0 1 2" { attach -c $plot_/$i@0 -to h$i/tcp/cwnd@ } set sim [attach_simulator .] $sim stop; # stop the simulation first to complete the scenario start h0/source h5-7/sink; # start source 0 and all sinks script "start h1/source" -at 200.0 -on $sim; # schedule source 1 script "start h2/source" -at 400.0 -on $sim; # schedule source 2 script "puts [$sim getTime]" -at 100.0 -period 100.0 -on $sim; # to print simulation time $sim resumeTo 600.0; # run the simulation until 600.0
The resulting trace file looks like the following:
### NEW PLOT--0--CWND--'- Time -' ##### NEW SET--0--0--/example/h0/tcp/cwnd@ 0--0--2.2506192--2.0--/example/h0/tcp/cwnd@ 0--0--4.501238399999999--3.0--/example/h0/tcp/cwnd@ 0--0--4.9508384--4.0--/example/h0/tcp/cwnd@ 0--0--6.751857599999998--5.0--/example/h0/tcp/cwnd@ 0--0--7.201457599999999--6.0--/example/h0/tcp/cwnd@ 0--0--7.651057599999999--7.0--/example/h0/tcp/cwnd@ 0--0--8.1006576--8.0--/example/h0/tcp/cwnd@ 0--0--9.0024768--9.0--/example/h0/tcp/cwnd@ 0--0--9.452076800000002--10.0--/example/h0/tcp/cwnd@ 0--0--9.901676800000002--11.0--/example/h0/tcp/cwnd@
... (snip) ...
0--0--204.12887680000102--11.08984375--/example/h0/tcp/cwnd@ ##### NEW SET--0--1--/example/h1/tcp/cwnd@ 0--1--204.57847680000103--2.0--/example/h1/tcp/cwnd@ 0--0--205.02807680000103--11.1796875--/example/h0/tcp/cwnd@ 0--0--205.47767680000103--11.26953125--/example/h0/tcp/cwnd@ 0--0--205.92727680000104--11.359375--/example/h0/tcp/cwnd@ 0--0--206.37687680000104--11.44921875--/example/h0/tcp/cwnd@ 0--0--206.82647680000105--11.5390625--/example/h0/tcp/cwnd@ 0--0--207.27607680000105--11.62890625--/example/h0/tcp/cwnd@ 0--0--207.72567680000105--11.71875--/example/h0/tcp/cwnd@ 0--0--208.17527680000106--11.80859375--/example/h0/tcp/cwnd@ 0--0--208.62487680000106--11.8984375--/example/h0/tcp/cwnd@ 0--0--209.07447680000107--11.98828125--/example/h0/tcp/cwnd@ 0--0--209.52407680000107--12.078125--/example/h0/tcp/cwnd@ 0--1--209.97367680000107--3.0--/example/h1/tcp/cwnd@
... (snip) ...
0--0--405.99927679999337--8.0--/example/h0/tcp/cwnd@ ##### NEW SET--0--2--/example/h2/tcp/cwnd@ 0--2--406.0--1.0--/example/h2/tcp/cwnd@ 0--0--406.44887679999334--9.0--/example/h0/tcp/cwnd@ 0--0--406.8984767999933--10.0--/example/h0/tcp/cwnd@ 0--0--407.3480767999933--11.0--/example/h0/tcp/cwnd@ 0--1--408.24727679999324--6.0--/example/h1/tcp/cwnd@ 0--1--408.6968767999932--7.0--/example/h1/tcp/cwnd@ 0--1--409.1464767999932--8.0--/example/h1/tcp/cwnd@ 0--1--409.59607679999317--9.0--/example/h1/tcp/cwnd@ 0--0--410.04567679999315--12.0--/example/h0/tcp/cwnd@ 0--0--410.4952767999931--13.0--/example/h0/tcp/cwnd@ 0--0--410.9448767999931--14.0--/example/h0/tcp/cwnd@ 0--0--411.3944767999931--5.0--/example/h0/tcp/cwnd@ 0--0--411.3944767999931--5.19921875--/example/h0/tcp/cwnd@ 0--2--411.84407679999305--2.0--/example/h2/tcp/cwnd@
... (snip) ...
|
In addition to be integrated as part of the component system,
Plotter can be
used as a standalone Java Program with the following usage:
java drcl.comp.tool.Plotter
?-1? <file1> ?<file2>...?
where Plotter draws data in each file in a separate plot unless the "-1"
option (one plot) is present.
| EXAMPLE 26
Display the trace file obtained in Example 23:
java drcl.comp.tool.Plotter cwnd.trace

Display the trace file obtained in Example 25:
java drcl.comp.tool.Plotter ex1.plot

|
To better manipulate the figures (set title, x/y labels,
export to EPS files), one may start a J-Sim terminal and then
type in the following commands:
set plot [mkdir drcl.comp.tool.Plotter plot]
$plot load <file_name>
Then use the published methods of the Plotter component to
manipulate the figures:
fill(int plotID_) // Fill the plot in the window.
repaint(int plotID_) // Repaint the plot.
exportEPS(int plotID_, String epsFileName_)
addLegend(int plotID_, int dataset_, String legend_)
setLegend(int plotID_, int dataset_, String legend_)
setTitle(int plotID_, String title_)
setXLabel(int plotID_, String xlabel_)
setXLog(int plotID_, boolean on_)
setXRange(int plotID_, int min_, int max_)
setYLabel(int plotID_, String ylabel_)
setYLog(int plotID_, boolean on_)
setYRange(int plotID_, int min_, int max_)
For example, use "$plot fill 0" to fill plot 0 in its window.
The NamTrace component is an
instrument class that probes appropriate
components to collect interested events and produce trace outputs in
the NAM (VINT/UCB
Network Animator) trace format. The class
drcl.inet.tool.NamTrace inherits a large portion of
functionality
from its parent class drcl.net.tool.NamTrace.
Unless explicitly specified, the discussion
in the rest of the section applies to the parent class.
Currently, NamTrace supports the
following NAM events/configurations: node,
link, queue, color and packet. The first four events are usually used
in the
initial/configuration part of a trace that defines the network topology
and the
color index. Packet events are collected from probing appropriate
components in
the system. In all cases, the traces are produced at the output port of
the NamTrace component. To save
the output in a file, one must connect a file
component (e.g., drcl.comp.io.FileComponent)
to the output port of the
NamTrace
component.
In what follows, we describe the format of each event type,
commonly used
values for each field of an event and the methods to produce the event.
For
details, please refer to the
formal NAM documentation.
Node Event
The format of a node event in a NAM trace is as follows:
n -t <time> -s <source> -d <destination> -S <state> -v <shape> -c <color> -o <previous_color> -A <label>
The destination field is only used for "interface event".
State can
be one of
A node event can be added using one of the following methods
in NamTrace:
public void addNode(double time_, long source_, long dest_, String state_, String shape_,
String color_, String prevColor_, String label_)
public void addNode(double time_, long source_, String state_, String shape_,
String color_, String prevColor_, String label_)
public void addNode(long source_, String state_, String shape_, String color_, String label_)
public void addNode(double time_, long source_, String state_, String color_)
The first method contains the most complete set of arguments
for a node
event. The other three use subsets of the arguments to specify
a node
event. In particular, the third method is useful in
describing a node in a
network topology at the beginning of a NAM trace. The last one is
useful in
marking a node state change with a specified color. The state of a node
may be
"up" or "down". Simple shapes, such as "circle",
"square" and so on, are recognized.
Link Event
The format of a link event in a NAM trace is as follows:
l -t <time> -s <source> -d <destination> -S <state> -c <color> -r <bandwidth> -D <propagation_delay> -o <orientation>
A link event can be added using one of the following methods
in NamTrace:
public void addLink(double time_, long source_, long dest_, String state_, String color_,
String bandwidth_, String propagationDelay_, String orientation_)
public void addLink(long source_, long dest_, String state_, String bandwidth_,
String propagationDelay_, String orientation_)
public void addLink(double time_, long source_, long dest_, String state_, String color_)
The first method contains the most complete set of arguments
for a link
event. The second one is useful in describing a link in a network
topology at
the beginning of a NAM trace. The last one is useful in marking a link
state
change with a specified color. The source and destination are the two
ends of
the link. The state of a link may be "up" or "down". The
examples of the orientation of the link are "left", "right",
"up", "down", or null for automatic layout.
Queue Event
The format of a queue event in a NAM trace is as follows:
q -t <time> -s <source> -d <destination> -a <attribute>
A queue event can be added using one of the following methods
in NamTrace:
public void addQueue(double time_, long source_, long dest_, String attribute_)
public void addQueue(long source_, long dest_, String attribute_)
The first method contains the most complete set of arguments
for a queue
event. The second one is useful in describing a queue in a network
topology at
the beginning of a NAM trace. A link can be associated with two queues,
one for
each end. The source and destination (of the link) specifies
the queue at
the source end of the link. The attribute is the angle between the line
along
which the queue packets are displayed and the horizontal line. For
example, 90
degrees may be represented by "0.5" or "90deg".
Color Index
A color index can be added using one of the following methods
in NamTrace:
public void addColor(double time_, int colorid_, String colorName_)
public void addColor(int colorid_, String colorName_)
public void addColors(String[] colorNames_)
public void addColors()
The last three methods without the time argument are useful in
specifying a
color index at the beginning of a NAM trace. The last method adds the
default
color indices to the NAM trace. NAM recognizes all the X11 color names.
Packet Event
NamTrace collects packet events by
probing appropriate components
in the system, and then produces corresponding traces at the output
port. Listed below are all the fields in a packet event and how
NamTrace
produces them:
- Event type: NAM defines five types of packet events:
- enqueue: when a packet is enqueued
to the buffer before transmitted over a link;
- dequeue: when a packet is removed
from the buffer before transmitted over a link;
- drop: when a packet is dropped from
the buffer due to buffer overflow;
- hop: when a link starts transmitting
a packet;
- receive: when a packet is completely
received at the other end of a link.
These five events fully describe a packet's whereabouts over a link. As
this information cannot be identified from a packet, it is put as part
of the ID of the port where the probed packet comes (see example
below).
- Source: The source of the "link", that is, the one end
where the packet is originated. As this information cannot be
identified from a packet, it is put as part of the ID of the port where
the probed packet comes (see example below).
- Destination: Same as source, this is the other end of the
link. It is put as part of the ID of the port where the probed packet
comes (see example below).
- Time of the event: Obtained from the component API (
Component.getTime()).
- Packet Type: Obtained from the
getPacketType(Packet) method. By default,
drcl.net.tool.NamTrace obtains this information from the
packet itself (Packet.getPacketType()). A
NamTrace subclass may override this method to interpret
the packets for the interests of the simulation.
- Extent: Is the packet size in bytes; obtained from the
probed packet.
- ID: The ID of the packets being transmitted over the link;
must be unique for each packet transmitted over the link. This is
automatically maintained and produced by
NamTrace.
- Conversation ID: Obtained from the
getConversationID(Packet) method. By default,
drcl.net.tool.NamTrace returns nothing for this field. The
drcl.inet.tool.NamTrace overrides the
method and recognizes TCP packets by putting the sequence number and
the acknowledged sequence number in this field.
- Attribute: Is the color index; obtained from
getColorID(Packet) method. By default,
drcl.net.tool.NamTrace always returns 0. The
drcl.inet.tool.NamTrace recognizes
drcl.inet.InetPacket and its source and destination
fields. It dynamically assigns a new color to new (source, destination)
and (destination, source) pairs.
To collect packet events over a link, one must connect a
NamTrace component to
five places, each for a type of packet events, for one direction.
Fig.11
illustrates how this is done for one direction of a link in the INET
framework.
| Figure 11: |
Example of attaching a NamTrace
component to collect packet events for the link from node 3 to node 7.
Note how the first three fields (event type, source and destination)
are directly put in the ID of the ports. |
 |
|
(a) Single QueueNI component
(default CSL decomposition since J-Sim v1.2).
|
 |
|
(b) Queue - NI combination.
|
|
It is tedious to hook up a NamTrace
component to every interested link
even for a small network. As the task is repetitive in nature, we
provide a
utility method in drcl.inet.InetUtil to
automate the task for a network that
consists of INET nodes:
public static drcl.inet.tool.NamTrace setNamTraceOn(Component net_, String filename_, String[] colors_)
| EXAMPLE 27 (Aside from Example 1)
This example demonstrates how a NamTrace
component is set up by "hands" and how the utility method helps the
task. Suppose the following network is constructed.

# Creates the NamTrace component and connects it to a FileComponent set outfile "result.nam" set nam [mkdir -q drcl.inet.tool.NamTrace .nam] set file [mkdir drcl.comp.io.FileComponent .file] connect -c $nam/output@ -to $file/in@ $file open $outfile
# attach NamTrace to nodes (single QueueNI component) attach -c "$nam/+ -s 0 -d 1@" -with h0/csl/ni0/pull@; # 0 --> 1 enqueue attach -c "$nam/- -s 0 -d 1@" -to h0/csl/ni0/.deq@; # dequeue attach -c "$nam/h -s 0 -d 1@" -to h0/csl/ni0/.deq@; # hop attach -c "$nam/r -s 0 -d 1@" -to .link0/1@; # receive disconnect h0/csl/ni0/.info@ attach -c "$nam/d -s 0 -d 1@" -to h0/csl/ni0/.info@;# drop attach -c "$nam/+ -s 1 -d 0@" -with n1/csl/ni0/pull@; # 1 --> 0 enqueue attach -c "$nam/- -s 1 -d 0@" -to n1/csl/ni0/.deq@; # dequeue attach -c "$nam/h -s 1 -d 0@" -to n1/csl/ni0/.deq@; # hop attach -c "$nam/r -s 1 -d 0@" -to .link0/0@; # receive disconnect n1/csl/ni0/.info@ attach -c "$nam/d -s 1 -d 0@" -to n1/csl/ni0/.info@;# drop attach -c "$nam/+ -s 1 -d 2@" -with n1/csl/ni1/pull@; # 1 --> 2 enqueue attach -c "$nam/- -s 1 -d 2@" -to n1/csl/ni1/.deq@; # dequeue attach -c "$nam/h -s 1 -d 2@" -to n1/csl/ni1/.deq@; # hop attach -c "$nam/r -s 1 -d 2@" -to .link1/1@; # receive disconnect n1/csl/ni1/.info@ attach -c "$nam/d -s 1 -d 2@" -to n1/csl/ni1/.info@;# drop attach -c "$nam/+ -s 2 -d 1@" -with h2/csl/ni0/pull@; # 2 --> 1 enqueue attach -c "$nam/- -s 2 -d 1@" -to h2/csl/ni0/.deq@; # dequeue attach -c "$nam/h -s 2 -d 1@" -to h2/csl/ni0/.deq@; # hop attach -c "$nam/r -s 2 -d 1@" -to .link1/0@; # receive disconnect h2/csl/ni0/.info@ attach -c "$nam/d -s 2 -d 1@" -to h2/csl/ni0/.info@;# drop setflag garbage true .../ni*; # enable garbage to collect dropped packets
# write head blocks to the nam trace file $nam addColors [_to_string_array "red blue yellow green black orange"] $nam addNode 0 UP square OliveDrab src $nam addNode 1 UP circle blue router $nam addNode 2 UP square OliveDrab sink $nam addLink 0 1 UP 1.0e6 0.1 right $nam addLink 1 2 UP 1.0e4 0.6 right $nam addQueue 0 1 0 $nam addQueue 1 0 0 $nam addQueue 1 2 0 $nam addQueue 2 1 0
|
#(Queue - NI combination) #h0/csl/q0/up@ #h0/csl/q0/output@ #h0/csl/q0/output@ #h0/csl/q0/.info@ #h0/csl/q0/.info@ #n1/csl/q0/up@ #n1/csl/q0/output@ #n1/csl/q0/output@ #n1/csl/q0/.info@ #n1/csl/q0/.info@ #n1/csl/q1/up@ #n1/csl/q1/output@ #n1/csl/q1/output@ #n1/csl/q1/.info@ #n1/csl/q1/.info@ #h2/csl/q0/up@ #h2/csl/q0/output@ #h2/csl/q0/output@ #h2/csl/q0/.info@ #h2/csl/q0/.info@ #setflag garbage true .../q*;
|
Note that all components' .info@
ports are connected together (to the RUV system monitor), so we must
disconnect it before we can attach NamTrace
to the .info@ port, otherwise, the "drop"
event ports at NamTrace will be attached to
the same wire.
With the utility method, all the above can be done in
one line no matter how many nodes and links there are:
set nam [java::call drcl.inet.InetUtil setNamTraceOn [! .] "result.nam" \ [_to_string_array "red blue yellow green black orange"]]
|
| EXAMPLE 28
This example completes Example
1. In this example, the bandwidth of all links are 1Mbps
except the bottleneck link which has bandwidth 100Kbps. Three TCP
connections are set up. We start connection 0 at time 0.0, connection 1
at 100.0 and connection 2 at 200.0. The congestion window events are
collected from all three TCP components and save the results in the "ex1.plot"
file. In addition, we set up the NamTrace
component and have the results saved in the "ex1.nam"
file. The script can be obtained here.
# inet3_ex.tcl # # Topology: # h0 ---\ /--- h5 # \ / # h1 ----- n3 ----- n4 ----- h6 # / \ # h2 ---/ \--- h7
cd [mkdir drcl.comp.Component /example]
puts "create topology..." set link_ [java::new drcl.inet.Link] $link_ setPropDelay 0.3; # 300ms set adjMatrix_ [java::new {int[][]} 8 {{3} {3} {3} {0 1 2 4} {3 5 6 7} {4} {4} {4}}] java::call drcl.inet.InetUtil createTopology [! .] $adjMatrix_ $link_
puts "create builders..." # router builder: set rb [mkdir drcl.inet.NodeBuilder .routerBuilder] $rb setBandwidth 1.0e6; #1Mbps
# source builder: set hb1 [cp $rb .hostBuilder1] [mkdir drcl.inet.transport.TCP $hb1/tcp] setMSS 512; # bytes set src_ [mkdir drcl.inet.application.BulkSource $hb1/source] $src_ setDataUnit 512 connect -c $src_/down@ -and $hb1/tcp/up@
# sink builder: set hb2 [cp $rb .hostBuilder2] mkdir drcl.inet.transport.TCPSink $hb2/tcpsink set sink_ [mkdir drcl.inet.application.BulkSink $hb2/sink] connect -c $sink_/down@ -and $hb2/tcpsink/up@
puts "build..." $rb build [! n?] $hb1 build [! h0-2] $hb2 build [! h5-7]
# Configure the bottleneck bandwidth and buffer size ! n3 setBandwidth 3 1.0e5; # 100Kbps at interface 3 ! n3 setBufferSize 3 6000; # ~10 packets at interface 3
# Set up TCP connections ! h0/tcp setPeer 5 ! h1/tcp setPeer 6 ! h2/tcp setPeer 7
puts "set up static routes..." java::call drcl.inet.InetUtil setupRoutes [! h0] [! h5] "bidirection" java::call drcl.inet.InetUtil setupRoutes [! h1] [! h6] "bidirection" java::call drcl.inet.InetUtil setupRoutes [! h2] [! h7] "bidirection"
puts "set up plotter..." set plot_ [mkdir drcl.comp.tool.Plotter .plot] set file_ [mkdir drcl.comp.io.FileComponent .file] $file_ open "ex1.plot" connect -c $plot_/.output@ -to $file_/in@ setflag plot false $plot_ foreach i "0 1 2" { attach -c $plot_/$i@0 -to h$i/tcp/cwnd@ }
puts "set up nam trace..." set nam [java::call drcl.inet.InetUtil setNamTraceOn [! .] "ex1.nam" \ [_to_string_array "red blue yellow green black orange"]]
set sim [attach_simulator .] $sim stop; # stop the simulation first to complete the scenario run h0/source h5-7/sink; # start source 0 and all sinks script "run h1/source" -at 100.0 -on $sim; # schedule source 1 script "run h2/source" -at 200.0 -on $sim; # schedule source 2 script {puts [$sim getTime]} -at 100.0 -period 100.0 -on $sim; # to print simulation time $sim resumeTo |