J-Sim INET Tutorial

A SimpleTwo-node, Raw IP Example

December 04, 2002

Figure 1: The scenario to be constructed in this example.


Working with RUV System Commands

In this example, we first show how to construct the scenario depicted in Figure 1 using only RUV commands.

Step 1. Create the network topology.

Step 1.1. We create a component directory to hold the components created in this example:

	mkdir drcl.comp.Component /example1
cd /example1

Setp 1.2.  We create the two nodes and the link, and connect them as depicted in Figure 1:

	mkdir drcl.inet.Node node0 node1
mkdir drcl.inet.Link link0
connect -c node0/0@ -and link0/0@
connect -c node1/0@ -and link0/1@
! link0 setPropDelay .01; # 10ms

The RUV commands, mkdir, connect, and ! can be found in the RUV command summary page. Specifically,

  1. mkdir is a RUV command that creates one or more components at the path(s) specified. The syntax is
    mkdir ?-q? ?<class name>? <path>....

In the first two lines of the scripts, we create two node components,  node0 and node1, of the drcl.inet.Node class, and one link component, link0, of the drcl.inet.Node class.

  1. connect is a Tcl command which connects two components at specified ports, and has the following syntax:
    connect ?-c? <port path> -and|-to <port path>

where the option "-c" indicates that ports are created if necessary, "-and" sets up a bi-direction connection, and "-to" sets up an uni-directional connection. 

  1. "!" converts the path to the reference to the Java object.  Hence, "! link0" references to the Java object, link0, and "! link0 setPropDelay .01" invokes the method  specified in the argument list (i.e., setPropDelay) to set the propagation delay to 10 ms.

Step 2. Configure the internal structure of both node 0 and node 1.

Step 2.1. The two nodes are composite components which contain several subcomponents. Their internal structures are shown in Figure 2.  Specifically, 

The ports, except pd/100@up and stdout/in@, shown in Figure 2 are all default ports defined in the corresponding components. The item highlighted in red (at ni) is what to be configured for the component.

Figure 2: The node constructed using the basic technique.

 

The commands to configure the internal structure of node0 and node1 are as follows:

mkdir drcl.inet.core.PktDispatcher node0/pd node1/pd
mkdir drcl.inet.core.Identity node0/id node1/id
mkdir drcl.inet.core.queue.DropTail node0/q node1/q
mkdir drcl.inet.core.ni.PointopointNI node0/ni node1/ni
cd node0
connect -c pd/0@down -to q/up@
connect -c q/output@ -and ni/pull@
connect -c ni/down@ -to ./0@
connect -c ./0@ -to pd/0@down
! pd bind [! id]
cd ../node1
connect -c pd/.service_id@ -and id/.service_id@
connect -c pd/0@down -to q/up@
connect -c q/output@ -and ni/pull@
connect -c ni/down@ -to ./0@
connect -c ./0@ -to pd/0@down
! pd bind [! id]
cd ..
! .../ni setBandwidth 1.0e6; # 1Mbps

Again the above RUV commands can be found in  the RUV command summary page. Note that the path expression ".../ni" matches all "ni" components under the current component directory. "! .../ni setBandwidth 1.0e6" configures the bandwidth of both the NI components to be 1Mbps.

Step 2.2. We assign the node addresses at the Identity component:

! node0/id add 0
! node1/id add 1

In the above script, we invoke the "add" method of the node0/id (node1/id) component to assign an ID of 0 (1) to node0 (node1).

Step 2.3. We open a raw IP port at both nodes and connects the one in node1 to a standard output component:

mkdir node0/pd/100@up node1/pd/100@up
mkdir drcl.comp.io.Stdout node1/stdout
connect -c node1/pd/100@up -to node1/stdout/in@

Step 3. Composing a packet. 

Step 3.1. We prepare a TCL procedure, send, to compose and inject data packets to port 100 at node0:

proc send data_ {
set source_ 0
set destination_ 1
set routerAlert_ false
set TTL_ 1
set ToS_ 0
set size_ 100
set packet_ [java::call drcl.inet.contract.PktSending getForwardPack $data_ $size_ $source_ $destination_ $routerAlert_ $TTL_ $ToS_]
inject $packet_ node0/pd/100@up
}

Several points are in order:

  1. The procedure has one argument data_. It sets source_ to be 0, destination_ to be 1, routeAlert_ to be false, TTL_ to be 1, ToS_ to be 0, and size_ to be 100. These are the items needed in composing an INET packet. 
  2. The procedure then composes the packet by invoking the "getForwardPack" method in the drcl.inet.contract.PktSending class.
  3. The procedure injects the packet at the 100@up port of node0/pd (by invoking another RUV command, "inject").

Step 4. Starting the simulation.

Step 4.1. We attach the simulation runtime to the example directory (the current directory "."):

set sim [attach_simulator .]

Step 4.2. We start the simulation by injecting a message:

tcl0> send "Test!"

When the message arrives at node1, it is delivered to the standard output:

tcl0> sz120(INET)sz20--src:#0--dest:#1--prot:0--TTL:1/1--ToS:#0__<Test!>__

We just conduct our first simulation. The source of the example is available here .


Making Use of Utility Classes

We have implemented several utility classes to simplify the process of constructing the network scenario.  In particular, these utility classes automate several repetitive steps. In what follows, we use the same example to illustrate these utility classes.

Step 1. Creating the network topology.

Step 1.1.  We first create a component directory to hold the components created in this example:

mkdir drcl.comp.Component /example1_2
cd /example1_2

Step 1.2. We use the adjacency matrix and drcl.inet.InetUtil.createTopology() to create the topology shown in Figure 1:

set link_ [java::new drcl.inet.Link]
$link_ setPropDelay .01; # 10ms
set adjMatrix_ [java::new {int[][]} 2 {{1} {0}}]
java::call drcl.inet.InetUtil createTopology [! .] "node" "node" $adjMatrix_ $link_

In the above script, we 

java::new <array_type> <sizes_of_dimensions> <array_content>

The size of the last dimension is usually omitted. The adjacency matrix is expressed as  a recursive Tcl list, and has the following form,  where n is the number of nodes, and nbk is the number of neighbors of node k:

Index of neighbor 1, ..., Index of neighbor nb0
Index of neighbor 1, ..., Index of neighbor nb1
...
Index of neighbor 1, ..., Index of neighbor nbn

In this example, node0 has only one neighbor node1 and vice versa, and hence the adjacency matrix is {{1} {0}}.

void createTopology(Component network_, int[][] adjMatrix_)
void createTopology(Component network_, int[][] adjMatrix_, Link link_)
void createTopology(Component network_, String routerIDPrefix_, String hostIDPrefix_, int[][] adjMatrix_, Link link_)

The last format has the most complete argument list.  The default values for missing arguments in the other formats are routerIDPrefix_ = "n", hostIDPrefix_ = "h" and link_ = null. The link argument, link_, specifies the link component that connects the nodes. A null link implies that the nodes are connected directly without links.  (In such a case, link emulation should be turned on at each node component to emulate the link propagation delay).  Finally, note that [! .] returns the reference to the current component directory, example1_2

After executing the above script, we create node0, node1 and link0

Step 2. Construct the internal structure of both node0 and node1.

Step 2.1. We use drcl.inet.NodeBuilder to construct the internal structure of nodes:

# NodeBuilder
set nodeBuilder_ [mkdir drcl.inet.NodeBuilder .nodeBuilder]
$nodeBuilder_ setBufferSize 10240; # 10KB
$nodeBuilder_ setBandwidth 1.0e6; # 1Mbps
mkdir $nodeBuilder_/100@up
# Build:
$nodeBuilder_ build [! node*]
mkdir drcl.comp.io.Stdout node1/stdout
connect -c node1/csl/100@up -to node1/stdout/in@

Several points are in order:

The nodes built by the above script are shown in Figure 3. The nodal structure is similar to that shown in Figure 2 except that the pd, id, q, and  ni components are encapsulated in the csl component.  

NOTE: Since J-Sim v1.2, the default CSL composition combines the queue and network interface into one QueueNI component.

Figure 3: The node structure built by the node builder.

 

Step 3. Composing a packet.

Step 3.1. We prepare a Tcl procedure, send, to compose and inject data packets to port 100 at node0:

# Proceduer to inject a packet to port 100 at node0
proc send data_ {
set source_ 0
set destination_ 1
set routerAlert_ false
set TTL_ 1
set ToS_ 0
set size_ 100
set packet_ [java::call drcl.inet.contract.PktSending getForwardPack $data_ $size_ $source_ $destination_ $routerAlert_ $TTL_ $ToS_]
inject $packet_ node0/csl/100@up }

Step 4. Starting the simulation.

Step 4.1. We attach the simulation runtime to the example directory:

# Attach the simulator runtime
set sim [attach_simulator .]

Step 4.2. We start the simulation by injecting a packet:

tcl0> send "Test 2!"

When the message arrives at node1, it is delivered to the standard output: 

tcl0> sz120(INET)sz20--src:#0--dest:#1--prot:0--TTL:1/1--ToS:#0__<Test 2!>__

The source of the example is available here.


Summary of what we have done

  1. We have introduced how to use several RUV commands to configure the scenario for network simulation.
  2. We have introduced several utility classes to facilitate the task of configurating the network simulation:
    1. Use an adjacency matrix and drcl.inet.InetUtil.createTopology() to create a topology.
    2. Use drcl.inet.NodeBuilder to build nodes.
  3. How to attach a simulator runtime for running simulations.

Where we go next

Example 2: two-host, one-router and one-TCP-connection.