Network Simulation in J-Sim (UP)

Creating Simulation Scenarios (PREV)

Quick Reference of INET Classes (NEXT)

Part III
Online Interactions

March 20, 2006



0 Overview

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

1 Basic Commands

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:

  1. Components are "physically" connected to one another.  No physical relation exists between files.
  2. 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.
  3. 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.

1.1 File-System-Like Commands

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.

1.2 cat

The "cat" command is used to print the "content" of a component. There are two types of data for the content of a component.

  1. the information obtained from the String drcl.comp.Component.info() method, and
  2. 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

1.3 connect/disconnect, attach/detach, pipe, watch

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.

1.4 Runtime, Simulation Engine and Simulation Control

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.

1.5 rt, run/stop/resume, reset, reboot

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.

 

2 Component Flags - Trace, Debug and Others

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.

2.1 Trace Flag

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.

2.2 Debug Flag and Debug Levels

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

 

2.3 Garbage/GarbageDisplay Flag

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

 

2.4 "Component" Flag

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.

 

3 Other Useful Commands

3.1 script - Schedule Events Manually

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

3.2 wait_until

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. 

3.3 explore - Explore/Display Network Topology

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.

EXAMPLE 22

Continued from Example 1, we exercise the explore command in this example.

TCL0> source inet3_ex1.tcl
TCL0> explore h0
/example/.link0/:
neighbor 1: example/.link0/0@ -> example/h0/0@
neighbor 2: example/.link0/1@ -> example/n3/0@
/example/.link1/:
neighbor 1: example/.link1/0@ -> example/h1/0@
neighbor 2: example/.link1/1@ -> example/n3/1@
/example/.link2/:
neighbor 1: example/.link2/0@ -> example/h2/0@
neighbor 2: example/.link2/1@ -> example/n3/2@
/example/.link3/:
neighbor 1: example/.link3/0@ -> example/n3/3@
neighbor 2: example/.link3/1@ -> example/n4/0@
/example/.link4/:
neighbor 1: example/.link4/0@ -> example/n4/1@
neighbor 2: example/.link4/1@ -> example/h5/0@
/example/.link5/:
neighbor 1: example/.link5/0@ -> example/n4/2@
neighbor 2: example/.link5/1@ -> example/h6/0@
/example/.link6/:
neighbor 1: example/.link6/0@ -> example/n4/3@
neighbor 2: example/.link6/1@ -> example/h7/0@
/example/h0/:
neighbor 1: example/h0/0@ -> example/.link0/0@
/example/h1/:
neighbor 1: example/h1/0@ -> example/.link1/0@
/example/h2/:
neighbor 1: example/h2/0@ -> example/.link2/0@
/example/h5/:
neighbor 1: example/h5/0@ -> example/.link4/1@
/example/h6/:
neighbor 1: example/h6/0@ -> example/.link5/1@
/example/h7/:
neighbor 1: example/h7/0@ -> example/.link6/1@
/example/n3/:
neighbor 1: example/n3/0@ -> example/.link0/1@
neighbor 2: example/n3/1@ -> example/.link1/1@
neighbor 3: example/n3/2@ -> example/.link2/1@
neighbor 4: example/n3/3@ -> example/.link3/0@
/example/n4/:
neighbor 1: example/n4/0@ -> example/.link3/1@
neighbor 2: example/n4/1@ -> example/.link4/0@
neighbor 3: example/n4/2@ -> example/.link5/0@
neighbor 4: example/n4/3@ -> example/.link6/0@
Figure 6: The complete topology explored from "h0".
TCL0> explore h0 -transparent .link*
/example/h0/:
neighbor 1: example/h0/0@ -> example/n3/0@
/example/h1/:
neighbor 1: example/h1/0@ -> example/n3/1@
/example/h2/:
neighbor 1: example/h2/0@ -> example/n3/2@
/example/h5/:
neighbor 1: example/h5/0@ -> example/n4/1@
/example/h6/:
neighbor 1: example/h6/0@ -> example/n4/2@
/example/h7/:
neighbor 1: example/h7/0@ -> example/n4/3@
/example/n3/:
neighbor 1: example/n3/0@ -> example/h0/0@
neighbor 2: example/n3/1@ -> example/h1/0@
neighbor 3: example/n3/2@ -> example/h2/0@
neighbor 4: example/n3/3@ -> example/n4/0@
/example/n4/:
neighbor 1: example/n4/0@ -> example/n3/3@
neighbor 2: example/n4/1@ -> example/h5/0@
neighbor 3: example/n4/2@ -> example/h6/0@
neighbor 4: example/n4/3@ -> example/h7/0@
Figure 7: The topology explored from "h0" with links being treated as transparent.
TCL0> explore h0 -transparent .link* -excluded .link3
/example/h0/:
neighbor 1: example/h0/0@ -> example/n3/0@
/example/h1/:
neighbor 1: example/h1/0@ -> example/n3/1@
/example/h2/:
neighbor 1: example/h2/0@ -> example/n3/2@
/example/n3/:
neighbor 1: example/n3/0@ -> example/h0/0@
neighbor 2: example/n3/1@ -> example/h1/0@
neighbor 3: example/n3/2@ -> example/h2/0@

TCL0> explore h5 -transparent .link* -excluded .link3
/example/h5/:
neighbor 1: example/h5/0@ -> example/n4/1@
/example/h6/:
neighbor 1: example/h6/0@ -> example/n4/2@
/example/h7/:
neighbor 1: example/h7/0@ -> example/n4/3@
/example/n4/:
neighbor 1: example/n4/1@ -> example/h5/0@
neighbor 2: example/n4/2@ -> example/h6/0@
neighbor 3: example/n4/3@ -> example/h7/0@
Figure 8: The topology explored from "h0" with links being treated as transparent and ".link3" being excluded.


Figure 9: The topology explored from "h5" with links being treated as transparent and ".link3" being excluded.

 

4 Collect Results and Display

Similar to the diagnosis procedure, collecting results in J-Sim replies on two things:

  1. components which originate interested results; and
  2. appropriate instrument components which collect the results.

This section introduces three instrument components that help to collect results for different purposes.

4.1 Save Results Directly to a File - drcl.comp.io.FileComponent

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

 

4.2 xy Plot - drcl.comp.tool.Plotter

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.

4.3 NAM Trace - drcl.inet.tool.NamTrace

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:

  1. Event type: NAM defines five types of packet events:
    1. enqueue: when a packet is enqueued to the buffer before transmitted over a link;
    2. dequeue: when a packet is removed from the buffer before transmitted over a link;
    3. drop: when a packet is dropped from the buffer due to buffer overflow;
    4. hop: when a link starts transmitting a packet;
    5. 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).
  2. 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).
  3. 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).
  4. Time of the event: Obtained from the component API (Component.getTime()).
  5. 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.
  6. Extent: Is the packet size in bytes; obtained from the probed packet.
  7. 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.
  8. 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.
  9. 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"]]

 

Appendix - A Complete Example

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