| Network Simulation in J-Sim (UP) |
January 20, 2007
With all the components available in INET, one may readily
compose a network scenario of his/her like. The basic way to compose a scenario
is to build it "by hands". That is, we create every necessary
components, from networks, nodes, links to protocols and modules inside a node.
And then we connect the components. The idea is very simple but the tasks are
repetitive and can get a bit tedious even for a small size of network.
Fortunately, we can make both tasks of creating a network topology and building
network nodes follow certain patterns and then automate the processes. The
utility class drcl.inet.InetUtil and the builder classes drcl.inet.NodeBuilder
and drcl.inet.CSLBuilder are developed for this purpose.
Building a network simulation scenario in J-Sim is outlined in the following TCL script:
# Create a container to hold the scenario cd [mkdir drcl.comp.Component scene]
# Step 1: Create topology ...
# Step 2: Build nodes ...
# Step 3: Configure nodes ...
# Attach simulator runtime to "scene" attach_simulator .
# Start all "active" components under "scene" if there is any run .
In what follows, we first describe the process of building a scenario
"by hands", and then introduce the utility functions in
drcl.inet.InetUtil for creating network topologies (step 1). Followed by that, we
introduce the builder classes and their usages (step 2). Finally, we describe other
utility functions in drcl.inet.InetUtil for building different network scenarios
(step 3).
As a review, the commands we use to build a scenario "by hands" are listed below.
| Table 1: The most useful commands to build a scenario "by hands". |
In what follows, we use an example to demonstrate how to use these commands to build a scenario.
|
EXAMPLE 1 Fig.1 and Fig.2 is an example which demonstrates how to use these commands to build a scenario. On the right of the figures are the scripts that build the scenarios. |
|
||||||||
There is a set of createTopology(...) methods in the drcl.inet.InetUtil
class for automating the process, as in Fig.1, of creating a flat topology . The
most simplest form of all is as follows:
public static void createTopology(Component network_,
int[][] adjMatrix_);
The network_ argument is where the nodes are to be created in. The most important argument
in all the createTopology() methods is the adjacency
matrix, adjMatrix_.
It is a two-dimensional array. The length of the first dimension, i.e., adjMatrix_.length,
is the number of nodes. Each element in the first dimension is a one-dimensional
array, which represents the neighbors of the node. The position of a neighbor in
this one-dimensional array is the ID of the port that the node uses to connect
to the neighbor. Nodes are indexed as 0, 1,..., (adjMatrix_.length-1). The neighbors are represented by
their indices. Each node may have a different number of neighbors. The
general form of a adjacency matrix is given below:
Port index --> (port 0@) (port 1@) node (node 0) neighbor(0,0) neighbor(0,1) ... neighbor(0, nb0) index (node 1) neighbor(1,0) neighbor(1,1) ... neighbor(1, nb1) | ... V (node (n-1)) neighbor((n-1),0) neighbor((n-1),1) ... neighbor((n-1), nbn-1)
where n is the number of nodes, nbi is the number of neighbors of node i. Fig.3 shows an example topology and its adjacency matrix representation. Two different ways of creating the topology are shown on the right.
|
EXAMPLE 2
|
||||||||||||||||
One may specify a negative number to not use a particular port to connect. For example, the adjacency matrix below is the same as that in Fig.3 except that now n1 uses 2@ to connect to n0 instead of 1@:
(0@) (1@) (2@) (n0) 1 3 2 (n1) 3 -1 0 (n2) 0 3 (n3) 0 1 2
Based on the above idea, a variety of createTopology() methods are derived:
public static void createTopology(Component network_, int[][] adjMatrix_); public static void createTopology(Component network_, int[][] adjMatrix_, boolean assignAddress_); public static void createTopology(Component network_, int[][] adjMatrix_, Link link_); public static void createTopology(Component network_, int[][] adjMatrix_, Link link_, boolean assignAddress_); public static void createTopology(Component network_, int[][] adjMatrix_, long[] ids_); public static void createTopology(Component network_, int[][] adjMatrix_, long[] ids_, Link link_); public static void createTopology(Component network_, Object[] existing_, int[][] adjMatrix_); public static void createTopology(Component network_, Object[] existing_, int[][] adjMatrix_, boolean assignAddress_); public static void createTopology(Component network_, Object[] existing_, int[][] adjMatrix_, Link link_); public static void createTopology(Component network_, Object[] existing_, int[][] adjMatrix_, Link link_, boolean assignAddress_); public static void createTopology(Component network_, Object[] existing_, int[][] adjMatrix_, long[] ids_); public static void createTopology(Component network_, Object[] existing_, int[][] adjMatrix_, long[] ids_, Link link_); public static void createTopology(Component network_, String routerIDPrefix_, String hostIDPrefix_, int[][] adjMatrix_, Link link_); public static void createTopology(Component network_, String routerIDPrefix_, String hostIDPrefix_, int[][] adjMatrix_, Link link_, boolean assignAddress_); public static void createTopology(Component network_, String routerIDPrefix_, String hostIDPrefix_, int[][] adjMatrix_, long[] ids_, Link link_); public static void createTopology(Component network_, String routerIDPrefix_, String hostIDPrefix_, Object[] existing_, int[][] adjMatrix_, Link link_); public static void createTopology(Component network_, String routerIDPrefix_, String hostIDPrefix_, Object[] existing_, int[][] adjMatrix_, Link link_, boolean assignAddress_); public static void createTopology(Component network_, String routerIDPrefix_, String hostIDPrefix_, Object[] existing_, int[][] adjMatrix_, long[] ids_, Link link_);
The most complete of all is the following:
public static void createTopology(Component network_,
String routerIDPrefix_,
String hostIDPrefix_,
Object[] existing_,
int[][] adjMatrix_,
long[] ids_,
Link link_,
boolean assignAddress_);
All the above methods invoke this one with the missing arguments given by default values. Each of the argument and its default value are described below.
network_routerIDPrefix_hostIDPrefix_existing_adjMatrix_. When creating the topology, a node is
retrieved from this array, instead of created anew, only if the index does
not excess the size of the array and the corresponding element in this array
is not null. Default is a null array, meaning that all the nodes will be
created anew.adjMatrix_ids_adjMatrix_. If the array is
not null, then its values are used, instead of the node indices, to
construct the component ID's (concatenating either routerIDPrefix_ or
hostIDPrefix_ and the value). Default is null.link_assignAddress_ids_are also used to set
the network addresses of nodes. Default is true. See the section of Address
Assignment for details regarding this address assignment action.Building a hierarchical network can be done by building levels of flat
networks. It is better illustrated by an example. Fig.4 shows an example of a
3-level hierarchical
network. For demonstration purpose, suppose net01, net02 and
net03 has the same
structure as net00.
|
Figure 4: A hierarchical network example. We can build the network either from top to bottom or the other way around. In the following script, we build the network from bottom (level-2) to top (level-0). |
|
Building level-2 networks, .LAN3 and .LAN4 are pretty straightforward.
Building level-1 and level-0 networks need to mix in constructed level-2 and
level-1 network components using the existing_ argument. Note that
in line 18 and 27, we make room for n0, n1 and n2 by putting [java::null]'s
in the existing_ array. |
After a network topology is created, the next task is to build the nodes. Note that the nodes created during the process of creating a network topology are just empty composite components. We need to put in appropriate protocols and modules to make them functional. One way to do this is, of course, to build them by hands as described in the section of Build by Hands. In this section, we explain how to use builder classes to automate the process. The rationale behind this is very simple. Suppose we have 100 nodes in a network topology. Instead of building them node by node by hands, we first categorize the nodes. Supposedly there should be far less types of nodes in the network. Then we build, by hands, a node template for each type of nodes, and then build the nodes of the same type by duplicating the structure of the template node.
The NodeBuilder class (drcl.inet.NodeBuilder)
has a set of build(...) methods to build the internal structure of nodes. But
before we can build other nodes, we need to first build the NodeBuilder itself. Building a
NodeBuilder is no difference from building a real node (i.e., adding components
and connecting them). But since the relation
between the modules in the upper protocol layer (UPL) and the core service layer
(CSL) is defined, we can further automate the process by having a set of port
naming rules for a protocol. The best way to understand this is to look at the rules
below.
Table 2: The naming rules used by NodeBuilder to connecting service and
event ports between UPL modules and CSL. |
|||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||
If a protocol follows the rules, then we can simply add the protocol to
NodeBuilder and NodeBuilder will take care of the connections between the
protocol and CSL.
In what follows, we use another example to see more closely how NodeBuilder
works.
|
To make it more complete, first build the topology using one of the
|
Nodes n0-3 are routers and h4-5 are hosts. Suppose each router runs OSPF for
unicast routing, and DVMRP and IGMP1 for multicast routing. Each host runs TCP,
IGMP and an application. Fig.5 depicts these two types of nodes.
1 For demonstration only. IGMP does not exist in the current J-Sim release. |
In the following, we first build the router builder and then the host builder:
|
||||||||||||||||
The complete set of build(...) methods of NodeBuilder
is listed below:
public void build(Object c_); public void build(Object[] cc_); public void build(Object c_, CSLBuilder cb_); public void build(Object[] cc_, CSLBuilder cb_);
The first and the third forms are to build one node or network, while the others are to
build multiple nodes/networks. In line 8 and 17 in the previous example, the arguments in calling the
build method ("[! n0-3]" and "[! h4-5]")
return Object[], that is, the second form is used.
At the end of build(...), NodeBuilder uses CSL
builder to build the internal structure of CSL. In the first two forms of
the build(...) method, the default CSL builder is used. To apply a different CSL
implementation, one may supply the corresponding CSL builder to NodeBuilder by
using the third and fourth forms of the build(...) method. The CSL
builder is covered in details in the section of CSL
Builder.
If the UPL modules in a node forms a layered protocol stack, then one may use
a node map to further ease the task of building a NodeBuilder.
A node map is a plain text which describes the layering relation between
modules. For example, the node map for a UDP application laying on top of
UDP at port 1100 is as follows:
udp 17/csl drcl.inet.transport.UDP app 1100/udp Application_Class
And then we can use the loadmap(String) method of NodeBuilder
to load a node map into a NodeBuilder. Each line in a node
map corresponds to a module and the syntax is as follows:
<module_id> <port>/<lower_layer_module_id> <module_class>
After parsing a line, NodeBuilder creates the module and
connects the down@ port of the module to the <port>@up
port of the lower layer module. If the lower layer module does not
multiplex/demultiplex, then <port> should be given by "-"
(the "minus" sign). In this case, NodeBuilder
connects the down@ port of the module to the up@ port
of the lower layer module.
The current implementation of NodeBuilder requires that the
lower layer module be defined ahead. The core service layer (csl)
is pre-defined. One may use it as lower layer module without defining it.
If the lower layer module is the core service layer (csl), then
we may omit the <port>/csl field if the protocol is known to
INET. (INET recognizes many Internet standard protocols such as TCP, UDP, IGMP,
DV, OSPF and so on).
So the following Tcl script using a node map:
set nb [mkdir drcl.inet.NodeBuilder nodeBuilder]
$nb loadmap {
udp drcl.inet.transport.UDP
app 1100/udp Application_Class
}
is equivalent to the following Tcl script which builds the nodes directly:
set nb [mkdir drcl.inet.NodeBuilder nodeBuilder] mkdir drcl.inet.transport.UDP $nb/udp mkdir Application_Class $nb/app connect -c udp/down@ -and csl/17@up connect -c app/down@ -and udp/1100@up
There are four more build(...) methods in NodeBuilder
for including a node map as an argument:
public void build(Object c_, String nodemap_); public void build(Object[] cc_, String nodemap_); public void build(Object c_, CSLBuilder cb_, String nodemap_); public void build(Object[] cc_, CSLBuilder cb_, String nodemap_);
These methods call loadmap(String) first and then calls the
corresponding build(...) methods without the node map argument.
Note that loading a node map overrides the existing structure in the NodeBuilder.
One may use the same NodeBuilder instance to build different types
of nodes with different node maps. See tutorial examples 2,
3 and 4 for using node map as an
alternative.
Some properties can be set in the NodeBuilder. When the build(...) method is
called, these properties are conveyed and set in the nodes built. It is
particularly useful when one wishes to set these properties that are common to
the nodes being built. The following table lists the properties defined in the
NodeBuilder class.
Table 3: Properties of NodeBuilder. |
|||||||||||||||
|
In addition to relying on NodeBuilder to create service
and event ports at CSL on demands (of UPL modules), one can command NodeBuilder
to create some or all of those ports, including "up"
ports. To make it happen, one simply adds the service and event ports to the NodeBuilder, and then, when building a node, the
NodeBuilder duplicates all the
service and event ports on it at the CSL created for the node.
|
EXAMPLE 5 The following script is the same as in Example 4
except that now we manually add a 100 " 1 set routerBuilder [mkdir drcl.inet.NodeBuilder .routerBuilder] 2 cd $routerBuilder 3 mkdir drcl.inet.protocol.ospf.OSPF ospf 4 mkdir drcl.inet.protocol.dvmrp.DVMRP dvmrp 5 mkdir drcl.inet.protocol.igmp IGMP igmp 6 connect igmp/.mcastHost@event -to dvmrp/.mcastHost@ 7 mkdir 100@up .rt_mcast@event 8 cd .. 9 $routerBuilder build [! n0-3] |
The CSLBuilder class (drcl.inet.CSLBuilder)
is mainly used by the NodeBuilder class to build the CSL component in a Node
component. The CSLBuilder class also has a set of build(...) methods to perform
the task. It has been shown in Example 4
that the service and event ports of CSL are created based on the needs of the
UPL modules. When building a CSL, the CSLBuilder makes sure that the resulting
CSL does provide the specified services and events while includes only a
minimal, necessary structure to reduce the memory consumption.
Since there could be different implementations of CSL, each CSL
implementation should at least provide a CSLBuilder which knows the
implementation. There is a default CSL implementation in the J-Sim package
under the drcl.inet.core sub-package. This implementation is explained in Part
I. The CSLBuilder for this implementation is discussed in the following
subsection.
The drcl.inet.core.CSLBuilder
class is the CSLBuilder for the default CSL decomposition explained in Part
I. It is also the default CSLBuilder used by NodeBuilder in the build(...)
methods that do not have the CSLBuilder argument. The main tasks of this
CSLBuilder are:
(1) creating necessary subcomponents for the specified services and events; and
(2) creating appropriate packet filter banks to form the interfaces of the node.
The first task is straightforward because each subcomponent is in charge of one
or more services and/or events and no two subcomponents are responsible for the
same service or event (one-to-one correspondence). The second task is more
complicated if one wishes to specify the structure of the packet filter bank. A
packet filter bank structure can be applied to all the interfaces or only a
specific interface. If no structure is given, then the CSLBuilder uses a default
buffer and a network interface component to form all the interfaces. Several
examples are provided below to explain these tasks and also different applications of this
CSLBuilder class.
|
EXAMPLE 6 In this example, we examine how the CSL components of the two types of nodes
from Example 4 are built by the Figure 7: The CSL component of the router from the Example
4. (a) The CSL component before the
At the end of building a node in the
A similar, but simpler, process takes place for building the CSL component of the host as shown in Fig.8 below. Figure 8: The CSL component of the host from Example
4. (a) The CSL component before the
|
NOTE: Since J-Sim v1.2, the default CSL composition combines the queue and network interface into one QueueNI component.
One can specify particular packet filter, buffer and/or network interface
components in forming particular interfaces or all interfaces of the node by
adding them to a CSLBuilder instance and calling the build(...) method of
NodeBuilder with the CSLBuilder instance as argument. CSLBuilder
recognizes those
components by the following rules (<i> is the interface
index or packet filter bank ID, <j> is the packet filter ID).
| Table 4: The naming rules of drcl.inet.core.CSLBuilder for explicitly adding components. | ||||||||||
|
The packet filter ID is used to order the packet filters in a packet filter
bank. Packet filters with smaller ID's are closer to the PktDispatcher
component in the protocol stack.
Note that the properties set in
NodeBuilder do not apply to the components (i.e., packet filter, buffer and
network interface components) that are explicitly added to the CSLBuilder.
One must set the properties explicitly for these added components.
|
EXAMPLE 7 Working on the same router in Example 4, now we wish to use RED (Random Early Detection) queue instead of the default FIFO queue. The following script achieves this: 1 set routerBuilder [mkdir drcl.inet.NodeBuilder .routerBuilder] 2 cd $routerBuilder 3 mkdir drcl.inet.protocol.ospf.OSPF ospf 4 mkdir drcl.inet.protocol.dvmrp.DVMRP dvmrp 5 mkdir drcl.inet.protocol.igmp IGMP igmp 6 connect igmp/.mcastHost@event -to dvmrp/.mcastHost@ 7 cd .. 8 set cslBuilder [mkdir drcl.inet.core.CSLBuilder .cslBuilder] 9 mkdir drcl.inet.core.queue.REDQueue $cslBuilder/q 10 $routerBuilder build [! n0-3] $cslBuilder Highlighted in boldface are the augments to the script shown in Fig.6.
Now the buffer components |
|
EXAMPLE 8 Fig.9 shows a more complicated CSL construction. For a clearer illustration, unrelated details are omitted in this example. |
|
||||
Note that the packet filter pf2_1 in Fig.9 is wired "upwards". The reason is that each packet filter is equipped with an "up"
port (up@) and a "down" port (down@). The
direction of wiring is determined by the types of these ports. The type of a
port may be
input only, output only or input/output. The following table
lists the valid combinations of the types of the "up" and
"down" ports, and the resulting wiring direction.
Table 5: The rules of drcl.inet.core.CSLBuilder for wiring a packet
filter. |
||||||||||||||
|
||||||||||||||
From the above discussion, we can infer that the type of the
"up" port of pf2_1 is output only, and the type of
the "down" port is input only. The port types of the "up"
and "down" ports of a packet filter may or may not be configurable, depending on the
implementation of the packet filter.
After the network topology is created and nodes are built, the next task is to configure the simulation scenario. Configuring a scenario may involve assigning addresses to nodes, configuring nodes and other optional tasks such as setting up virtual interfaces and so on. These tasks and the corresponding utility functions are explained in details in the following subsections.
Set Addresses by Component ID
The drcl.inet.InetUtil
class offers two types of automatic address assignment functions. The first type
is setAddressesByID(...) which sets the address of a node based on the component
ID of the node. Basically, this set of functions extracts the numerical part of
the component ID to be the network address of the node. For example, for
component ID "n11", it assigns 11 as the network address to the node;
for "host35", it assigns address 35. The following lists all different
forms of the method:
public static void setAddressByID(Node node_); public static void setAddressByID(Network network_); public static void setAddressByID(Object[] nodes_);
|
EXAMPLE 9 To set address for node " java::call drcl.inet.InetUtil setAddressByID [! n11]; To set addresses for all the nodes in network " java::call drcl.inet.InetUtil setAddressByID [! net0] To set addresses for all the nodes starting with " java::call drcl.inet.InetUtil setAddressByID [! n*] |
There are another set of methods that do the opposite of setAddressByID(...),
that is, they set component ID based on the network address of a node:
public static void setIDByAddress(Network network_); public static void setIDByAddress(Object[] networksOrNodes_);
What they do is appending the network address to the non-numerical part of
the original component ID to form the new component ID. For example, for the
component ID "node11" which has network address 35, it creates a new
component ID "node35"; for component ID "net0" of a network
component which has the network address 1100/2 (a CIDR-based address
representation), it creates a new component ID "net12_4". In
"net12_4", 12 is the base address of the network,
4 is the maximum
number of nodes in this network.
Assign Addresses to a Hierarchical Network
The second type of address assignment functions is for assigning addresses to a hierarchical network that is structured in the same fashion as described in the section of Hierarchical Network:
public static void setAddressByCIDR(Network network_); public static void setAddressByCIDR(Network network_, long baseAddress_); public static void setAddressByCIDR(Object[] networksOrNodes_); public static void setAddressByCIDR(Object[] networksOrNodes_, long baseAddress_);
These methods not only assign addresses to nodes but also networks. A network
(drcl.inet.Network)
component is associated with a base address and a mask. One can use getNetworkAddr()/setNetworkAddr(long)
and getNetworkMask()/setNetworkMask(long) to access
these fields, or use the "cat"
command on a network component at
run-time to observe these fields.
The address assignment in these methods is based on the principle of CIDR. The advantage of CIDR, compared to traditional class-based address assignment, is that one can use variable length subnet masks to assign addresses in unbalanced hierarchical networks, where by an unbalanced network, we mean a network that contains at least two networks with unequal number of nodes. Since it allows variable length subnet masks, one can assign addresses in a more efficient manner, meaning that the number of un-used addresses can be reduced.
Network Representation in CIDR
In CIDR, a network is represented by an address with a network mask in the format of <address>/<mask>, where a network mask is an address that, in the binary form, starts with contiguous 1's and then all 0's thereafter. For example, the network address 10xy2/11002 with x, y in [ 0,1] is equivalent to 10002/11002, and contains only the nodes with addresses in the format of 10xy2 with x, y in [ 0,1]. A network address can also be represented in the format of <address>/<number of 1's>. For example, the above network address can also be represented as 10002/2.
|
EXAMPLE 10 Fig.10(a)
depicts a network system of 3 levels and totally 10 nodes. The
system is unbalanced because |
|
||||||
EXAMPLE 11 To set addresses for all the nodes in the root network " java::call drcl.inet.InetUtil setAddressByID [! net0] Or equivalently with the base address set to zero: java::call drcl.inet.InetUtil setAddressByID [! net0] 0 This function is often used with java::call drcl.inet.InetUtil setIDByAddress [! net0] If the resulting address assignment is as in Fig.10(b), then the network address and component ID of each network and node become:
|
One may configure a node after it is built. Several general properties of a
node is exposed at drcl.inet.Node
to facilitate configuring a node. These properties and the access methods are
listed below.
| Property | Access Methods |
|---|---|
| Identity/address |
long getDefaultAddress() void addAddress(long addr_) void removeAddress(long addr_) |
| Routing table |
boolean hasRoutingCapability() void addRTEntry(RTKey key_, RTEntry entry_, double timeout_) void removeRTEntry(RTKey key_) Object retrieveRTEntry(RTKey key_, String matchMethod_) |
| Interface bandwidth |
void setBandwidth(int ifindex_, double bw_) void setBandwidth(double bw_) double getBandwidth(int ifIndex_) |
| Interface buffer size |
void setBufferSize(int ifindex_, int bs_) void setBuffer(int bs_, String mode_) void setBuffer(int ifindex_, int bs_, String mode_) int getBufferSize(int ifIndex_) |
| Interface buffer mode |
void setBufferMode(String mode_) void setBufferMode(int ifIndex_, String mode_) String getBufferMode(int ifIndex_) |
| Interface maximum transmission unit (MTU) |
void setMTU(int ifindex_, int mtu_) void setMTUs(int mtu_) int getMTU(int ifIndex_) |
| General interface information |
void setInterfaceInfo(int ifindex_, InterfaceInfoif_) InterfaceInfo getInterfaceInfo(int ifIndex_) InterfaceInfo[] getInterfaceInfos() void setInterfaceInfos(InterfaceInfo[] aa_) int getNumOfInterfaces() int getNumOfPhysicalInterfaces() |
Most of the functions are straightforward. The hasRoutingCapability()
method returns true if an appropriate routing table component is installed in
the node, false otherwise.
For bandwidth, buffer size, buffer
mode and MTU, there are two set(...) methods. One with the interface index
argument is to set the property at the specified interface. The other one
without the interface index argument is to set the property at all interfaces.
There are two buffer modes: "byte" or "packet". In the
"byte" mode, the buffer size and the queue length are accounted in
bytes, while in the "packet" mode, they are accounted in numbers of
packets.
The drcl.inet.data.InterfaceInfo
class encapsulates general interface information, including the local
address (drcl.inet.data.NetAddress),
the addresses (drcl.inet.data.NetAddress)
of the neighbors that can be reached at the interface, the size of the
outgoing buffer, the bandwidth, the maximum transmission unit (MTU) and so on.
The getNumOfInterfaces() method returns the number of interfaces of
the node, including virtual interfaces, if there is any.
Instead of using the node properties to manually set up static route entries
along a path,
drcl.inet.InetUtil
includes a set of setupRoutes(...) methods to
automate the task. Given source and destination nodes, the methods compute the
unicast or multicast routes with minimum hop count, and then install appropriate
route entries in the nodes along the routes. The following lists different forms
of the methods:
public static void setupRoutes(Node src_, Node dest_); public static void setupRoutes(Node src_, Node dest_, String bidirect_); public static void setupRoutes(Component src_, Component dest_, long destAddr_, long destAddrMask_); public static void setupRoutes(Component src_, Object[] dests_, long destAddr_); public static void setupRoutes(Component src_, Object[] dests_, long destAddr_, long destAddrMask_); public static void setupRoutes(Component src_, Object[] dests_, long srcAddr_, long srcAddrMask_, long destAddr_, long destAddrMask_);
The methods do not distinguish unicast and multicast addresses. It sets up
routes between the source node (src_) and the destination node(s) (dest_/dests_)
and uses srcAddr_, srcAddrMask_, destAddr_
and destAddrMask_ to create route entries (drcl.inet.data.RTKey).
If srcAddr_is not present, then address 0 with mask 0 are
used instead. If destAddr_ is not present, then it uses the default
address of the node instead. If the destination address mask is not present, the
default mask of all 1's is used.
The examples of using these methods can be found in the subsequent sections.
In addition to the above methods, one may want to set up the unicast routes for all the nodes in the network in one shot using one of the following methods:public static void setupRoutes(Component network_, int[][] adjMatrix_); public static void setupRoutes(Component network_, int[][] adjMatrix_, long[] addr_); public static void setupRoutes(Node[] nodes_, int[][] adjMatrix_, LinkCost linkcost_); public static void setupRoutes(Component network_, int[][] adjMatrix_, long[] addr_, LinkCost linkcost_);For details, refer to the class document at
drcl.inet.InetUtil.
The following methods in
drcl.inet.InetUtil
are useful in setting up a
traffic source using the specified traffic model:
public static Component createTrafficSource(TrafficModel trafficModel_, Node dest_); public static Component createTrafficSource(TrafficModel trafficModel_, long dest_); public static Component createTrafficSource(TrafficModel trafficModel_, long src_, long dest_, long tos_);
The method returns a component which, when started, spontaneously sends out
packets, the pattern of which conforms to the traffic model specified and all
packets are destined to the destination node specified. The component sends out
packets at its down@ port and acts as the packet
sending service initiator with default forwarding, router alert turned off,
TTL=255 and ToS = drcl.inet.InetPacket.DATA
(if the first two are used).
As a result, it is ready to be hooked up, as a UPL module, with the core service
layer.
For most cases, it is convenient to use the following method instead:
public static Component createTrafficSource(TrafficModel trafficModel_, String id_, Node src_, Node dest_, long tos_, int protocol_)
This method not only creates a traffic source component as the above three
methods do, but also installs the component in the source node right above the
core service layer at the <protocol_>@up port.
For available traffic models, refer to the drcl.net.traffic
package and the drcl.net document.
EXAMPLE 12 In this example, the topology from Example 4 is used. For convenience, the topology is shown below.
In the following (complete) script, we build the topology and the
nodes, and add a traffic source at host |
1 cd [mkdir drcl.comp.Component scene] 2 # Create topology:
3 set adjMatrix_ [java::new {int[][]} 6 {{1 3 2} {3 0 4} {0 3 5} {0 1 2} 1 2}]
4 java::call drcl.inet.InetUtil createTopology [! .] $adjMatrix_
5 # Build nodes: 6 set routerBuilder_ [java::new drcl.inet.NodeBuilder .routerBuilder] 7 set hostBuilder_ [cp $routerBuilder_ .hostBuilder] 8 mkdir $hostBuilder_/20@up 9 $routerBuilder_ build [! n*] 10 $hostBuilder_ build [! h*] 11 # Set up traffic source: 12 set packetSize_ 512 13 set period_ .1; # send a packet of size 512 bytes every .1 second 14 set trafficModel_ [java::new drcl.net.traffic.traffic_PacketTrain $packetSize_ $period_] 15 java::call drcl.inet.InetUtil createTrafficSource $trafficModel_ "source" [! h4] [! h5] 0 20] 16 # Set up sink: 17 set sink_ [mkdir drcl.comp.tool.DataCounter h5/sink] 18 connect -c h5/csl/20@up -to $sink_/down@ 19 # Set up static routes from h4 to h5 20 java::call drcl.inet.InetUtil setupRoutes [! h4] [! h5] 21 attach_simulator .; # attach simulation runtime 22 # start "active" component: the traffic source 23 run . |
|
Line 8 creates a 20 "up" port on the host builder, which
makes the host builder create a 20 "up" port at the CSL when
it builds a host node. The up port is used in line 15 and 18 to connect
with the traffic source and the sink components in After the simulation starts (at line 23), one can observe the number
of packets that have arrived at the sink component by using the command
" |
One can set up a tunnel between two nodes using one of the following methods
in drcl.inet.InetUtil:
public static void setupVIF(Node n1_, int vifindex1_, Node n2_, int vifindex2_); public static void setupVIF(Node n1_, int vifindex1_, Node n2_, int vifindex2_, int mtu_); public static void setupVIF(Node n1_, int vifindex1_, int mtu1_, Node n2_, int vifindex2_, int mtu2_);
As can be seen from the arguments, a tunnel is determined by two end points. Each is described by the node component and the index of the interface that terminates the tunnel at one end. One may also specify the maximum transmission unit (MTU) to limit the size of packets that come out at the interface.
EXAMPLE 13 Fig.11(a) shows the physical topology of a network. The following script constructs a virtual topology (shown as in Fig.11(b)) on this network using tunnels.
...(omitted)... # create topology ...(omitted)... # build nodes java::call drcl.inet.InetUtil setupVIF [! n0] 2 [! n8] 2 java::call drcl.inet.InetUtil setupVIF [! n0] 3 [! n16] 2 java::call drcl.inet.InetUtil setupVIF [! n0] 4 [! n24] 2 java::call drcl.inet.InetUtil setupVIF [! n8] 3 [! n24] 3 java::call drcl.inet.InetUtil setupVIF [! n16] 3 [! n24] 4 |
||||||
The drcl.inet.InetUtil class
provides a configure(...) method which can be used to set up a LAN or a CIDR-based
hierarchical network. The method has the following form:
public static void configure(Network network_); public static void configure(Object[] networksOrNodes_);
Specifically, it goes through all the nodes in the specified network
component and categorizes nodes into hosts and routers by Node.hasRoutingCapability().
When a host is identified, it adds an appropriate route entry to the routing
table of the immediate router that the host is connected to. When a router is
identified, it installs appropriate local addresses (drcl.inet.data.NetAddress)
to the general information (drcl.inet.data.InterfaceInfo)
of the interfaces of the router if the router is at the boundary of the network
where it resides.
This method replies on the network addresses being properly set for network
components. It is usually used with the setAddressByCIDR(...)
method.
| EXAMPLE 14
This example is continued from Example 3. Here we build the nodes, assign addresses, set component ID's and then configure the hierarchical network and LANs. |
...(script from Example 3)... set nb [mkdir drcl.inet.NodeBuilder .nodeBuilder] mkdir $nb/.if@event $nb build [!! net?? n?] java::call drcl.inet.InetUtil setAddressByCIDR [!! net* n?] java::call drcl.inet.InetUtil setIDByAddress [!! net* n?] java::call drcl.inet.InetUtil configure [! net*] Let's inspect node " 1 Node: 12
2 Interface index ----- interface info
3 4 ----- local:<12,-8>, peers:<null>, timeouts:<null double array>, MTU=2147483647, BW=8000.0, buffer=2147483647
4 Number of identities: 1
5 12 timeout NaN
6 Routing Table:
7 (0,8,0)(0,-1,0) 8-{0} -toHostSubnet- timeout:NaN
8 (0,9,0)(0,-1,0) 9-{1} -toHostSubnet- timeout:NaN
9 (0,10,0)(0,-1,0) 10-{2} -toHostSubnet- timeout:NaN
10 (0,11,0)(0,-1,0) 11-{3} -toHostSubnet- timeout:NaN
|
||||||
|
In line 3, we can see that the local address of interface 4 is set to
be <RTKey> <next_hop>-<outgoing interfaces> <extension> timeout:<timeout> See |
| Network Simulation in J-Sim |