Professional Documents
Culture Documents
Lab Exercices Modeler
Lab Exercices Modeler
1
Service capacity, C =
Mean service rate, = C
Mean Delay, =
=
C
W
1
Does the analytic value agree with the simulated result?
Master thesis MEE 03:24
Tommy Svensson 56
Alex Popescu
Another statistic of interest is the time-averaged queue size.
106) In the View results dialog box, remove the check next to the queuing delay.
107) Place a check next to the queue size (packets) statistic.
108) Select time-average from the pull-down list.
109) Click Show.
Figure 54 - View Results dialog
Figure 55 - Queue Size graph
Master thesis MEE 03:24
Tommy Svensson 57
Alex Popescu
From this graph we can draw the conclusion that the system is stable. It reaches steady
state after about 2 hours.
Validate the result.
Calculate the following:
Ratio of Load to Capacity = =
C
Average Queue Size =
1
Does the analytic value agree with the simulated results?
We will produce a queue size versus time averaged queue size graph.
110) Set focus on the time averaged queue size window.
111) Right-click on the graph and choose Add statistics.
112) Place a check next to File Statistics => <initials>_mm1net-mm1 => Object
Statistics => m1 => queue => subqueue [0] => queue => queue size (packets).
113) Left-click on the Add box.
114) Save the analysis configuration as <initials>_mm1net-mm1.
Master thesis MEE 03:24
Tommy Svensson 58
Alex Popescu
Figure 56 - Queue Size, As Is and Average overlapped graph
Its important to know the confidence intervals of the simulation results. We will now
graph the confidence interval.
115) Load the Scalar file. File => Load output scalar file
116) Select <initials>_mm1scalar.
117) Click the Create graph of two scalars button.
118) Select top.queue.service_rate on the Horizontal roll-down menu.
119) Select top.queue.subqueue[0].queue.queue size (packets).mean on the
Vertical roll-down menu.
120) Right click on the graph and select Edit Graph Properties.
Master thesis MEE 03:24
Tommy Svensson 59
Alex Popescu
121) Check the Show Confidence Interval check box.
Figure 57 - Graph Plot properties
122) Click OK to close the dialog.
Master thesis MEE 03:24
Tommy Svensson 60
Alex Popescu
The graph should resemble the one below.
Figure 58 - Queue Size Confidence Intervall graph
Master thesis MEE 03:24
Tommy Svensson 61
Alex Popescu
In order to get better confidence intervals you need to run more scenarios. The graph
below shows the confidence interval of 40 scenarios. The service rate is between 1024
and 1300 with step size 10.
Figure 59 - Queue Size Confidence Interval graph
Congratulations!
You have finished the lab.
Master thesis MEE 03:24
Tommy Svensson 62
Alex Popescu
Laboratory 3
Ethernet simulation
Objective
Networks can be generally divided into two broad categories, which are based on using
point-to-point connections and on using broadcast channels. In the broadcast channel
case, there could be competition for the use of the channel between two or more stations.
In the common literature, broadcast channels are referred to as multi-access channels, or
random-access channels. The problem of media access is therefore the most important
one for this case.
Multiple access protocols are implemented primarily in Local Area Networks (LANs).
Todays personal computers and workstations are connected by Local Area Networks
(LANs), which use a multi-access channel as the basis of their communication.
An example of a popular LAN is the Ethernet which uses a random-access scheme for
media access. The random-access technique was first used by the ALOHA protocol
developed at the University of Hawaii in the 1970s. Another popular random-access
protocol is the Carrier Sensing Multiple Access (CSMA) scheme which was developed
by XEROX Parc. Further the Ethernet, which is using the Carrier Sensing Multiple
Access with Collision Detection (CSMA-CD) scheme, was developed by Dr. Robert M.
Metcalfe in 1978. [4]
Overview
In this laboratory we will study Multiple Access Protocols. We will look at the ALOHA,
CSMA and Ethernet (CSMA-CD) protocols. The ALOHA is the simplest Multiple
Access Protocol and implements therefore only the most basic functionality, which is to
send packets. ALOHA has no built mechanism to check if the channel is free before it
continues transmitting packets, neither the possibility to detect any collisions on the
channel. These flaws limit the use of the bus.
By adding carrier sense capability to the Aloha random access protocol the performance
is improved. The carrier sense capability is employed in the CSMA (Carrier Sense
Multiple Access) protocol. The process waits until the channel is free before transmitting
a packet. Because of finite signal propagation times, it is possible for a node to be
transmitting before it detects an existing transmission signal. This results in some
collisions. [4]
Finally the Ethernet protocol implements the capability of both transmitting and
monitoring a connected bus link at the same time. It has fullduplex capability. By
monitoring the bus link it can determine whether a collision condition exists. If that is the
Master thesis MEE 03:24
Tommy Svensson 63
Alex Popescu
case a retransmission sequence will commence. This operational mode is commonly
referred to as Carrier-Sense Multiple Access with Collision Detection (or CSMA/CD).
The objectives of our study are:
To take a look at the performance, whichs main objective is the throughput.
To study various parameters that characterizes the multi-access protocols.
To assess via simulation the performance of ALOHA, CSMA and CSMA-CD
protocols and to study the throughput of each of them.
Procedure
OPNET uses the Finite State Machine (FSM) to implement the behavior of a module.
FSMs determine a modules behavior when an event occurs, detailing the actions taken
in response to every possible event.
A process model is a Finite State Machine (FSM). It represents a modules logic and
behavior. An FSM consists of any number of states that a module may be in and the
necessary criteria for changing states.
A state is the condition of a module. For example the module may be waiting for a link to
recover.
A transition is a change of state in response of an event.
Designing the Aloha Transmitter Process Model
The Aloha transmitter process must only receive packets from the generator and send
them further onto the transmitter. This process model has only two states, idle and
tx_pkt.
The idle state is an unforced state. That means it returns control to the simulation kernel
after executing its executives. The simulation begins in the idle state where it waits for
packets to arrive. In this model the FSM (Finite State Machine) begins in an unforced
state. Because of that the process needs to be activated with a begin simulation interrupt.
When the simulation starts the FSM will execute the idle state and will then be ready to
transition with the first arriving packet.
The tx_pkt state is a forced state. That means it does not return control to the simulation
kernel, but instead immediately executes the exit executives and transitions to another
state. The only interrupt expected is the packet arrival interrupt (the arrival of generated
packets). It is therefore safe to omit the unforced state a default transition. When a packet
interrupt is delivered the FSM should perform executives to acquire and transmit the
packet in the tx_pkt state, then transition back to the idle state.
1) Start Opnet.
2) Select File New then Process model.
3) Click on the Create State button and place two states in the workspace.
Master thesis MEE 03:24
Tommy Svensson 64
Alex Popescu
The first state created is automatically the initial state and indicated by a heavy black
arrow pointed towards it (figure 60). Any state can be changed to initial state by right
clicking on the state and choose Make Initial state in the pop-up menu.
Figure 60 - A initial state
4) Right click on the initial state and choose Edit attributes.
5) Change the name to idle.
6) Make sure the status is unforced.
Figure 61 - State Attributes
7) Click OK to accept the changes.
8) Right click on the other state and choose Edit attributes.
9) Change the name to tx_pkt and the status to forced.
It is now time to specify the code for the process model starting with the header block.
In the header block one usually specify macros to replace more complicated expressions
in transition conditions and executives. The use of macros saves place but the key
advantage is that it simplifies the task of interpreting an FSM diagram. The header block
may also contain #include statements, struct and typedef definitions, extern and global
variable declarations, function declarations and C-style comments.
10) Click on the Header Block button.
11) Type in the definitions shown below.
Master thesis MEE 03:24
Tommy Svensson 65
Alex Popescu
12) Close the header block editor to save the definitions.
IN_STRM and OUT_STRM will be used later to specify which stream to get packets
from and to which to send the packets to. In this process model only stream number 0
will be used. It is possible to select any stream number between 0-8. To achieve the
desired functionality these stream indices must be consistent with those defined in the
node model later.
PKT_ARVL is used to determine when a packet interrupt occurred by comparing the
value returned by the Simulation Kernel Procedure op_intrpt_type() with the OPNET
constant of OPC_INTRPT_STRM. If the comparison evaluates to true, this indicates
that the interrupt is due to a packet arriving on an input stream. In this model there is no
need to determine which input stream received the packet. A packet in only expected on
input stream 0.
The global variable subm_pkts will be used to keep track of the number of submitted
packets.
13) Create two transitions, one from idle state to tx_pkt state and the second one from
tx_pkt state to idle state. Use the create transition button.
14) Right click on the idle tx_pkt transition and select edit attributes.
15) Change the condition attribute to PKT_ARVL.
The finished configuration should look like in figure 62.
/* Input stream from generator module */
#define IN_STRM 0
/* Output stream to bus transmitter module */
#define OUT_STRM 0
/* Conditional macros */
#define PKT_ARVL (op_intrpt_type () == OPC_INTRPT_STRM)
/* Global variable */
extern int subm_pkts;
Master thesis MEE 03:24
Tommy Svensson 66
Alex Popescu
Figure 62 - Process Model
The condition PKT_ARVL is the macro that just has been defined in the header block.
The next step is to create state executives needed in the FSM. OPNET allows one to
attach code to each part of an FSM. This code is called Proto-C. There are three primary
places to use Proto-C, namely:
Enter Executives: Code executed when the module moves into a state.
Exit Executives: Code executed when the module leaves a state.
Transition Executives: Code executed in response to a given event.
Although the enter executives and exit executives of forced states are executed without
interruption, standard practice is to place all forced state executives in the enter
executives block.
To bring up the enter executives editor one double clicks on the upper half of the state.
Double clicking on the lower half of the state will bring up the exit executives editor.
(figure 63)
Figure 63 - executives editor click zones
Master thesis MEE 03:24
Tommy Svensson 67
Alex Popescu
Next step is to define the actions for the idle state.
16) Double-click on the top of the idle state to open the enter executives block
17) Enter the code shown below.
18) Save your changes to close the text edit pad.
op_ima_sim_attr_get (attr_type, attr_name, value_pointer) function takes three
arguments.
attr_type argument specifies the type of the attribute-of-interest. The acceptable values
of this argument are OPC_IMA_INTEGER, OPC_IMA_DOUBLE,
OPC_IMA_TOGGLE, or OPC_IMA_STRING.
attr_name argument specifies the name of the attribute-of-interest. This value must
specify an attribute defined in the simulation environment, or a prompt will be issued for
the attributes value.
value_pointer argument specifies a pointer to a variable to be filled with the specified
attributes value. It can accept a pointer to an integer, a double, or a character string. In
the last case, the array of characters must be large enough to contain the attributes value.
The data type of the argument pointer must match the data type of the specified attribute,
or an error will occur.
The max_packet_count variable is not yet defined. The variable will hold the maximum
number of packets to be processed in the simulation before it terminates. Variables can be
declared in two places. Variables declared in the temporary variables block do not
retain their values between invocations of the FSM. Variables declared in the state
variables block retain their values from invocation to invocation. The
max_packet_count variable value should be retained between invocations and therefore
declared in the state variable block.
19) Click the state variable block button.
20) Add the max_packet_count variable. The default type, int, is acceptable. When
you are finished click OK to close the dialog box.
/* Get the maximum packet count, */
/* set at simulation run-time. */
op_ima_sim_attr_get (OPC_IMA_INTEGER,"max packet \
count", &max_packet_count);
Master thesis MEE 03:24
Tommy Svensson 68
Alex Popescu
Figure 64 - State variable block
This value is set later in the simulation attributes. To be able to set the value at simulation
run-time it needs to be defined.
21) Select Interface Simulation Attributes and enter an attribute into the dialog
box table.
Figure 65 - Simulation Attributes dialog box
22) To save your changes click on the OK button.
Specify the actions for the tx_pkt state.
23) Double-click on the upper half of the tx_pkt state to open the enter executives
block.
24) Enter the code shown below.
/* A packet has arrived for transmission. Acquire */
/* the packet from the input stream, send the packet*/
/* and update the global submitted packet counter.*/
out_pkt = op_pk_get (IN_STRM);
op_pk_send (out_pkt, OUT_STRM);
++subm_pkts;
/*Compare the total number of packets submitted with*/
/*the maximum set for this simulation run.If equal*/
/* end the simulation run. */
if (subm_pkts == max_packet_count)
{
op_sim_end ("Simulation ended when max packet count \
reached.", "", "", "");
}
Master thesis MEE 03:24
Tommy Svensson 69
Alex Popescu
23) Save your changes to close the text edit pad.
op_pk_get(instream_index) function returns a pointer to the packet taken from the input
stream, instream_index. If the specified input stream does not contain any packets, the
value OPC_NIL will be returned by this KP. This situation can be avoided by first calling
op_strm_empty() to determine if a stream contains any packets.
op_pk_send(packet_pointer, outstream_index ) function takes two arguments.
packet_pointer argument specifies a pointer to the packet-of-interest.
outstream_index argument specifies the index of an output packet stream.
op_sim_end (line0, line1, line2, line3) function takes four arguments. These arguments
are message lines. This function terminates the simulation.
subm_pkts variable is declared in the header block. It is increased every time a packet is
sent.
The out_pkt variable is a packet pointer. This variable has not been declared yet. Since
the process model acquires packets from the generator stream and immediately transmits
them, it is not necessary to retain the packet pointer between process invocations. This
variable will be declared in the temporary variable block.
Enter the temporary variable block and state variables.
25) Click the temporary variable block button.
26) Enter the following declarations.
/* Outgoing packet */
Packet* out_pkt;
27) Save your changes to close the text edit pad.
The out_pkt entry in the temporary variable block creates a temporary packet pointer.
This is used to extract packets from one stream and insert them into another. The packet
pointers existence is only temporary. Since the packet is sent directly there is no need for
the pointer to be retained between process invocations.
The model is now complete, except for the model interface attribute.
To control the attributes visible at the node level, edit the Process Interfaces. You can
set initial attribute values or hide attributes.
28) Select Interface Process Interfaces.
29) Change the Initial Value for the begsim intrpt attribute to enabled.
Master thesis MEE 03:24
Tommy Svensson 70
Alex Popescu
30) Verify that the Initial Value for each of the following attributes is set to disabled.
endsim intrpt
failure intrpts
intrpt interval
recovery intrpts
super priority
31) Verify that the Initial value of the priority attribute is 0.
32) Change the status attribute to hidden for all attributes
Figure 66 - Process Interfaces attributes
33) Click OK to close the dialog box.
All process models must be compiled before they can be used in a simulation. Compiling
a model makes its object code available to a processor modules process model attribute.
34) Compile the model by clicking on the compile process model action
button.
35) Save the model as <initials>_aloha_tx.
36) Close the Process Model Editor when the compilation of the process model has
finished.
Creating the Aloha Transmitter Node Model
37) Select File New then Node Model from the pull down menu. To accept click
OK.
38) Using the create processor action button create two processor modules.
39) Create one bus transmitter by using the bus transmitter action button .
Master thesis MEE 03:24
Tommy Svensson 71
Alex Popescu
40) Connect the modules with packet streams using the packet stream action button.
Figure 67 - Node model overview
41) Right click on the first processor module and select Edit attribites.
42) Set the name to gen and process model to simple_source.
The value for the generators interarrival time needs to be promoted to make it possible to
assign different values at simulation time.
43) Click on Packet Interarrival Time in the left column to highlight the Attribute
name, then right-click and select Promote Attribute to Higher Level from the
pop-up menu.
44) Click OK.
Figure 68 - Generator process attributes
45) Right click on the second processor module and select Edit attributes
46) Set the name to tx_proc and process model to <initials>_aloha_tx.
47) Click OK.
48) Change the bus transmitters name to bus_tx.
Master thesis MEE 03:24
Tommy Svensson 72
Alex Popescu
Figure 69 - Alhoa transmitter node model
Double check the module connectivity to make sure all objects in the model has been
connected in the correct order.
49) Right click on the tx_proc module and choose Show Connectivity from the
Object pop-up menu. The objects should be connected as shown in figure 70.
Figure 70 Connectivity
The node interfaces needs to be defined.
50) Select Interfaces Node interfaces.
51) In the Node Types table, change the Supported value to no for the mobile and
satellite types.
52) Change the Status of all the attributes to hidden, except for the one with
promoted status, gen.Packet Interarrival Time.
53) Click OK to save the changes.
54) Save the node model as <initials>_cct_tx.
Aloha node model is completed.
55) Close the editor.
Master thesis MEE 03:24
Tommy Svensson 73
Alex Popescu
Creating the Generic Receiver Node Process Model
The generic receiver node process model is responsible for handling received packets for
statistics gathering purposes. The goal is to count packets and record statistics. It can be
used to monitor network performance whether the packets are transmitted in accordance
with the Aloha or the CSMA channel access methods.
To process received packets for statistics collection, the cct_rx process needs one
unforced state where it waits to receive collision-free packets. Collisions are detected
later in the link model.
The process records the channel throughput and channel traffic values for analysis at the
end of the simulation. It also handles the statistics gathering variables, which should be
initiated at the simulation start.
56) Select File New then choose process model.
57) Click on the Create State button and place two states in the workspace.
58) Right click on the initial state and choose Edit attributes.
59) Change the name to init and the status to forced. Click OK.
60) Right click on the second state and choose Edit attributes.
61) Change the name to idle and leave the status as unforced. Click OK.
62) Draw the transitions as shown below.
Figure 71 - Transitions overview
Master thesis MEE 03:24
Tommy Svensson 74
Alex Popescu
Enter the code for the header block.
63) Click the header block action button.
64) Type in the definitions shown below.
65) Save the header block definitions.
IN_STRM is the input stream definition.
The macro PKT_RCVD is used to detect received packets.
The END_SIM macro determines if the interrupt received by the process is associated
with an end-of simulation interrupt delivered by the Simulation Kernel.
The global variable subm_pkts is established so that all transmitting nodes can
contribute their individual transmission attempts to this accumulator. Declaring a variable
in a process model header block causes it to behave as a global variable within the
executable simulation.
Define the following state variable:
66) Click the state variable action button.
67) Set the name to rcvd_pkts.
68) Set the type to int.
69) Click OK.
The rcvd_pkts variable is used to keep track of the number of valid received packets. It
needs to be initiated at simulation start.
70) Double-click on the top of the init state to open the enter executives block, and
enter the following code:
71) Save the changes to close the dialog.
Two functions are needed. One that receives packets and one to write statistics to a scalar
file.
/* Input stream from bus receiver */
#define IN_STRM 0
/* Conditional macros */
#define PKT_RCVD (op_intrpt_type () == OPC_INTRPT_STRM)
#define END_SIM (op_intrpt_type () == OPC_INTRPT_ENDSIM)
/* Global variable */
int subm_pkts = 0;
/* Initialize accumulator */
rcvd_pkts = 0;
Master thesis MEE 03:24
Tommy Svensson 75
Alex Popescu
72) Open the function block and enter the following code.
The proc_pkt() function acquires each received packet as it arrives, destroys it, and
increments the count of received packets.
The record_stats() function is called when the simulation terminates.
The op_stat_scalar_write function sends the channel throughput and traffic data to a
scalar file that is specified in the simulation attributes.
The macro definitions and the functions have been defined. There is now a good idea to
change the transition conditions.
73) For the first transition between the states, change the condition attribute to
PKT_RCVD and the executive attribute to proc_pkt().
74) For the second transition between the states, change the condition attribute to
END_SIM and the executive attribute to record_stats().
75) For the first transition from idle back to itself, change the condition attribute to
PKT_RCVD and the executive attribute to proc_pkt().
76) For the second transition from idle back to itself, change the condition attribute to
default.
/* This function gets the received packet, destroys it, */
/* and then logs the incremented received packet total. */
void proc_pkt ()
{
Packet* in_pkt;
/* Get packet from bus receiver input stream */
in_pkt = op_pk_get (IN_STRM);
/* Destroy the received packet */
op_pk_destroy (in_pkt);
/* Increment the count of received packets */
++rcvd_pkts;
}
/* This function writes the end-of-simulation channel */
/* traffic and channel throughput statistics to a */
/* scalar file */
void record_stats ()
{
/* Record final statistics */
op_stat_scalar_write ("Channel Traffic G",
(double) subm_pkts / op_sim_time ());
op_stat_scalar_write ("Channel Throughput S",
(double) rcvd_pkts / op_sim_time ());
}
Master thesis MEE 03:24
Tommy Svensson 76
Alex Popescu
77) For the third transition from idle back to itself, change the condition attribute to
END_SIM and the executive attribute to record_stats().
Define the process interfaces.
78) Select Interfaces Process Interfaces
79) Change the Initial value of the endsim intrpt attribute to enabled.
80) Change the status of all the attributes to hidden.
Figure 72 - Generic Receiver process interfaces attributes
81) Click OK.
82) Click on the Compile Process Model action button.
83) Supply the filename <initials>_cct_rx and click OK.
84) Close the process model editor.
Master thesis MEE 03:24
Tommy Svensson 77
Alex Popescu
Creating the Generic Receiver Node Model
The next step is to create a generic receiver node model.
85) Begin by selecting File New then Node Model from the pull down menu.
Click OK to accept.
86) Click on the create processor action button and place one processor in the
workspace.
87) Create also a bus receiver module in the workspace to the right of the processor
by clicking on its action button .
88) Connect the two modules from the bus receiver to the processor by using a packet
stream.
89) Change the name of the processor to rx_proc and the name of the bus receiver to
bus_rx.
The finished configuration should look like the picture below:
Figure 73 - Generic reciever model overview
90) Open the processors attribute dialog box and set the process model attribute to
<initials>_cct_rx. Close the dialog box when finished.
The interface attributes remains to be set before the node model is completed.
91) Select Interfaces Node Interfaces.
92) The supported value should be changed to no for the mobile and satellite types
in the Node types table.
Figure 74 - Supported node types
Master thesis MEE 03:24
Tommy Svensson 78
Alex Popescu
93) Further, in the Attributes table change the status to hidden for all the attributes.
Figure 75 - Node interfaces attibutes
94) Close the node model editor after saving the node model as <initials>_cct_rx.
Master thesis MEE 03:24
Tommy Svensson 79
Alex Popescu
Creating a new link model
The behavior of a bus link is defined by its Transceiver Pipeline stages. The pipeline is a
series of C or C++ procedures which can be modified to customize the link model.
This bus link model will use the default pipeline stages. Default pipeline stages are
denoted by the dbu_ prefix. The table below lists pipeline stages by function.
Bus Transceiver Pipeline Model Stages
Model Function
txdel Computes the transmission delay associated with the transmission of a
packet over a bus link (transmission delay is the time required to transmit
the packet at the bit rate defined in the relevant bus transmitter module).
closure Determines the connectivity between any two stations on the bus.
propdel Calculates the propagation delay between a given transmitter and a
receiver.
coll Determines whether a packet has collided on the bus.
error Calculates the number of bit errors in a packet.
ecc Rejects packets exceeding the error correction threshold as well as any
collided packets.
95) Select File New then choose Link model. Click OK.
This link model supports only the bus and bus tap types.
96) In the Link Types table, change the Supported value to no for the ptsimp and
ptdup types.
Figure 76 - Supported Link Types
97) Save the file as <initials>_cct_link and close the Link Model Editor.
Master thesis MEE 03:24
Tommy Svensson 80
Alex Popescu
Creating the network model
The network model will be built so that it can be used when analyzing both the Aloha and
CSMA protocols. This will be done by defining the nodes so that they reference the
generic node models, and later changing the referenced process models at the node level.
The analytical Aloha model assumes that packets are always introduced into the network
at exponentially distributed interarrival times. This network model will contain a finite
number of nodes. To closely follow the analytical models assumptions, a relatively large
number of transmitter nodes must exist on the bus.
The network model will be constructed within a subnet so that a small scale coordinate
system can be used.
98) Select File New then choose Project and click OK.
99) Name the project <initials>_cct_network and the scenario aloha, then click
OK.
100) In the Startup Wizard, use the following settings:
Dialog Box Name Value
Initial Topology Default value: Create Empty Scenario
Choose Network Scale Office (Use Metric Units enabled)
Specify Size 700 m x 700 m
Select Technologies None
Review Check values, then click OK
In order to easily build your network, one needs a custom palette that contains the
necessary objects for your network.
101) Open the Object palette if its not already opened.
102) Click on the Configure Palette button.
103) Click on the Clear button in the Configure Palette dialog.
104) Click on the Node Models button and add <initials>_cct_tx and
<initials>_cct_rx from the list of available node models.
105) Click OK.
106) Click on the Link Models button and add <initials>_cct_link from the list of
available link models.
Master thesis MEE 03:24
Tommy Svensson 81
Alex Popescu
107) Click OK.
108) Click on the Save button in the Configure Palette dialog and save the palette as
<initials>_cct.
109) Click OK to close the Configure Palette dialog box.
The next step is to create bus network. Instead of creating the entire bus network by hand,
you can use rapid configuration to build it quickly.
110) Select Topology Rapid Configuration.
111) Choose Bus and click OK.
In the Model area.
112) Select <initials>_cct_tx in the Node model pull-down list.
113) Select <initials>_cct_link in the Link model pull-down list.
114) Enter the value 20 in the Number field.
115) Select <initials>_cct_link in the Tap model pull-down list.
In the Placement area.
116) Select Horizontal radio button.
117) Check the Top of bus and Bottom of bus check boxes.
118) Enter X: 100 and Y: 200 for Head of bus.
119) Enter the value 500 for the Bus Size.
120) Enter the value 100 for Tap Size.
Master thesis MEE 03:24
Tommy Svensson 82
Alex Popescu
Figure 77 - Rapid Configuration dialog
All the transmitter nodes have been created. The network needs a receiver node.
121) Click and drag the receiver node <initials>_cct_rx from the palette into the left
side of the tool area.
122) Click on the <initials>_cct_link tap link in the palette and draw a tap
from the bus to the receiver node. Drawing a tap from the node to the bus may
produce different results.
Master thesis MEE 03:24
Tommy Svensson 83
Alex Popescu
The completed bus model should resemble the one below.
Figure 78 - Bus model overview
124) Save the project as <initials>_cct_network.
Executing the Aloha Simulation
The goal is to observe how the performance of the protocol varies as a function of
channel traffic. The interarrival time input parameter will be varied in a series of
simulations to produce different levels of traffic so that one can observe different levels
of throughput.
123) Select Simulation Configure Discrete Event Simulation (Advanced)
124) Right-click and choose Edit attributes
125) Change the values in the common tab: Duration to 20000 sec and seed to an
arbitrary integer.
126) Click on the Global Attributes tab and set max packet count value to 1000.
127) Click on the Object Attributes tab and click on the Add button.
128) Add Office Network. *.gen.Packet Interarrival Time and click OK.
129) Click the on the Values button.
130) Click in the value column and choose exponential (mean) in the pop-up list.
Master thesis MEE 03:24
Tommy Svensson 84
Alex Popescu
131) Set the value 1000 by replacing mean with the value. (see figure 79)
Figure 79 - Setting exponential value
132) Repeate the last 2 steps to enter the following values: 200, 150, 100, 80, 50, 35,
30, 25, 20, 18,15
Figure 80 - Interarrival time values
133) Click OK.
134) Click on the Advanced tab.
135) Set Network to <initials>_cct_network-aloha.
136) Set Probe file to NONE.
137) Set Scalar file to <initials>_cct_a.
138) Click OK.
Master thesis MEE 03:24
Tommy Svensson 85
Alex Popescu
If the output scalar file <initials>_cct_a does not exist when the simulation sequence
begins, it will be created so that scalar results may be recorded. If the file already exists,
the simulation executables will append their scalar results to this file. To avoid
viewing obsolete results which may already exist in a similarly named file, the output
scalar file <initials>_cct_a must be deleted if it exists.
139) Select File Model Files Delete Model Files....
A list of delete able file types appears.
140) Select the Output Scalars item.
A list of available scalar files appears.
141) If the list contains the output scalar file <initials>_cct_a, select the entry to
delete the file.
142) Close the open dialog boxes.
The simulation is now ready for execution.
143) Click on the Execute Simulation Sequence action button.
144) Click OK to confirm execution.
145) When the simulations are complete, close the Simulation Sequence dialog box
and the Simulation Sequence editor.
Aloha channel performance can be measured according to the number of successfully
received packets as a function of the number of packets submitted. In this network,
channel throughput is a typical measurement of network performance.
The results of each simulation are stored as two scalar values in the output scalar file.
That allows us to view the networks performance as a function of an input parameter
rather than a function of time. The channel throughput as a function of the channel traffic
across all simulations can be viewed in the Analysis Configuration Editor.
146) Select File New and then choose Analysis Configuration. Click OK.
147) Select File Load Output Scalar File.
148) Select <initials>_cct_a.
149) Click on the Create graph of two scalars file action button.
Master thesis MEE 03:24
Tommy Svensson 86
Alex Popescu
150) Select Channel Traffic G from the Horizontal pull-down menu.
151) Select Channel Throughput S from the Vertical pull-down menu.
152) Click OK.
Figure 81- Create graph of two scalars dialog
The graph should resemble the one below.
Figure 82 - Aloha channel throughput as a function of Channel traffic
The Aloha bus simulation is now completed.
Master thesis MEE 03:24
Tommy Svensson 87
Alex Popescu
Creating the CSMA transmitter process model
By adding carrier sense capability to the Aloha random access protocol the performance
is improved. The process waits until the channel is free before transmitting a packet.
Because of finite signal propagation times, there is a risk for a node to transmit before it
detects an existing transmission signal. This results in some collisions. The carrier sense
capability is employed in the CSMA (Carrier Sense Multiple Access) protocol.
153) Select File Open then Process Model from the pull down menu in the
Project Editor.
154) Select the <initials>_aloha_tx model then click OK.
Modifications have to be made for adjusting the process model to CSMA.
155) Click on the Header Block button.
156) Add the following lines to the end of the existing code.
The Macro FREE makes the process verify that the channel is free before transmitting.
The Macro PKTS_QUEUED checks if the queue is empty.
The Macro CH_GOES_FREE keeps track of when the channel becomes empty and
ready for a new transmission.
157) Select File Save to save and exit the Header Block.
158) Now create a new state in the Process Model and name it wt_free.
159) Create a transition from wt_free to tx_pkt, and change the condition to
CH_GOES_FREE.
160) Create a transition from the wt_free state back to itself and set the condition to
default.
161) Create a transition from the idle state to wt_free and change the condition to
PKT_ARVL && !FREE.
/* Input statistic indices */
#define CH_BUSY_STAT 0
/* Conditional macros */
#define FREE (op_stat_local_read (CH_BUSY_STAT) == 0.0)
#define PKTS_QUEUED (!op_strm_empty (IN_STRM))
#define CH_GOES_FREE (op_intrpt_type () == OPC_INTRPT_STAT)
Master thesis MEE 03:24
Tommy Svensson 88
Alex Popescu
162) Add a transition from the idle state back to itself with a condition of default.
163) Change the condition on the transition from idle state to the tx_pkt state to
PKT_ARVL && FREE.
164) Change the unconditional transition from tx_pkt to idle to conditional by
setting the condition attribute to default.
165) Create a transition from tx_pkt back to itself, and set the condition to
PKTS_QUEUED && FREE.
166) Finally, create a transition from tx_pkt to wt_free and set the condition to
PKTS_QUEUED && !FREE.
The finished configuration should look like in the picture below.
Figure 83 - CSMA process model overview
167) Select File Save As and rename the model <initials>_csma_tx.
168) Compile the model then close the Process Editor.
Master thesis MEE 03:24
Tommy Svensson 89
Alex Popescu
Creating the CSMA transmitter node model
The Aloha transmitter node model will now be enhanced so that it supports CSMA. A
bus receiver module and a sink processor will be added to the existing Aloha model. The
bus receiver module delivers a falling edge statistic interrupt to the processor module
when the receiver busy statistic changes from busy to free. The sink processor
accepts and destroys the packets received by the receiver module.
The enhancements also include an inactive statistic wire which will both inform the
process (contained in the tx_proc module) of the busy status of the channel as well as
provide interrupts to the process when the channel condition changes.
169) Select File Open and choose Node Model in the roll-down list.
170) Select the <initials>_cct_tx model in the list and click OK.
171) Click on the create processor action button.
172) Place a processor on the workspace above the existing model.
173) Click on the create bus receiver action button.
174) Place a bus receiver next to the new processor.
175) Change the name of the new processor module to sink and the name of the
bus receiver to bus_rx.
176) Click on the create packet stream button
177) Make a connection form the bus_rx receiver to the sink processor.
Figure 84 -New modules in the CSMA node model
178) Click on the create static wire action button.
Master thesis MEE 03:24
Tommy Svensson 90
Alex Popescu
179) Connect bus_rx module with tx_proc module.
180) Right click on the static wire and choose Edit Attributes
181) Set the falling edge trigger attribute to enabled and rising edge trigger
attribute to disabled. Click OK.
Figure 85 - Static wire attributes
182) Right click on the tx_proc module and choose Edit attributes...
183) Change the process model attribute to <initials>_csma_tx. Click OK.
The processor now uses the CSMA process model created previously.
184) Select File Save As... and rename the model <initials>_cct_csma_tx.
185) Close the Node Editor.
Master thesis MEE 03:24
Tommy Svensson 91
Alex Popescu
Redefining the network model
The appropriate models needed to support CSMA are now created. The existing network
model needs to be modified to use the new models.
Instead of creating an entirely new model, one can duplicate the existing scenario
(including the network model) and make the appropriate changes.
186) Select Scenarios Duplicate Scenario in the project editor.
187) Name the new scenario CSMA.
The only change to the network model is to use the new CSMA transmitter node model.
It needs to be added to the object palette.
188) Open the Object palette if its not already opened and click on the configure
palette action button.
189) Click on the Node models action button.
190) Include <initials>_cct_csma_tx node model and click OK.
191) Click on the save button and save the palette with the default name.
All transmitter nodes in the network model need to be changed to use the new transmitter
model.
192) Right-click on one of the transmitter nodes and choose Select Similar Nodes
from the Object pop-up menu.
All 20 transmitter nodes are selected.
193) Right-click on any of the selected nodes and choose Edit Attributes from the
pop-up menu.
194) Change the model attribute to <initials>_cct_csma_tx.
195) Check Apply Changes to Selected Objects check box in the bottom left, then
click OK.
The nodes are now modified to use the new node model.
Master thesis MEE 03:24
Tommy Svensson 92
Alex Popescu
Configuring CSMA Simulations
Configure a series of simulations for the CSMA model.
196) Save the project. File Save.
197) Select Simulation Configure Discrete Event Simulation (Advanced).
198) Right-click on the simulation set and select Edit Attributes from the pop-up
menu.
199) Change the seed to any arbitrary integer.
200) Click on the Advanced tab.
201) Change the Scalar file to <initials>_cct_c.
202) Set Probe file to NONE.
203) Click OK.
204) Save the simulation sequence, File Save.
205) Delete any existing output scalar files with the name <initials>_cct_c.
206) Execute the simulation.
207) Close the simulation sequence editor when the simulation is finished.
Master thesis MEE 03:24
Tommy Svensson 93
Alex Popescu
Analyzing the CSMA results
The simulation is now complete and the results can be viewed.
208) Open the Analysis Configuration Editor, File New then Analysis
Configuration. Click OK.
209) Choose File Load Output Scalar File.
210) Select <initials>_cct_c from the list of available files.
211) Click on the Create a graph of two scalars action button.
212) Select Channel Traffic G from the Horizontal pull-down menu.
213) Select Channel Throughput S from the Vertical pull-down menu.
Your graph should resemble the one below:
Figure 86 - CSMA channel throughput as a function of Channel traffic
The goal is to compare the Aloha and CSMA protocols. The easiest way to do so is to
display both traces on the same graph.
Master thesis MEE 03:24
Tommy Svensson 94
Alex Popescu
Viewing Both Results on the Same Graph
To view both results on a single graph panel, we need to first create a scalar graph for the
Aloha results and then create a vector graph that displays both results.
Create a scalar graph for the Aloha results.
214) Select File Load Output Scalar File.
215) Select <initials>_cct_a from the menu.
216) Click on the Create a graph of two scalars action button.
217) Select Channel Traffic G from the Horizontal pull-down menu.
218) Select Channel Throughput S from the Vertical pull-down menu.
219) Click OK.
Create a vector graph that displays both results.
220) Select Panels Create Vector Panel.
221) Open the Displayed Statistics menu, and select both displayed statistics.
222) Change the display mode to Statistics Overlaid.
Figure 87 - Create Vector Panel dialog
223) Click Show.
Master thesis MEE 03:24
Tommy Svensson 95
Alex Popescu
The graph should resemble the one below.
Figure 88 - Aloha and CSMA traffic overlaid
224) Right-click on the multiple vector graph and select Edit Graph Properties.
Notice the pop-up menu of active traces in the top section of the dialog box.
Click and hold this menu to see the list of active traces. Both are named Channel
Throughput S. Which is the CSMA trace and which the Aloha trace?
Figure 89 - Active traces pop-up menu
In this pop-up menu, traces are listed in the order in which they were added to the multi-
trace graph. The first trace listed in the pop-up menu is the CSMA trace.
Change the labels for the CSMA trace.
225) Change the Custom Title to CSMA Channel Throughput.
Master thesis MEE 03:24
Tommy Svensson 96
Alex Popescu
226) Click on the Apply button.
Change the labels for the Aloha trace.
227) Select the second active trace in the pop-up menu.
228) Change the Custom Title to Aloha Channel Throughput.
229) Click OK.
Figure 90 - Aloha and CSMA renamed traces overlaid
The CSMA protocol is shown to be superior to the Aloha protocol at all channel traffic
loads.
230) Close the graphs and the Analysis Configuration Editor.
Master thesis MEE 03:24
Tommy Svensson 97
Alex Popescu
Ethernet network model
The Ethernet protocol implements the capability of both transmitting and monitoring a
connected bus link at the same time. It has fullduplex capability. By monitoring the bus
link it can determined whether a collision occurs. This operational mode is commonly
referred to as Carrier-Sense Multiple Access with Collision Detection (CSMA/CD). This
is accurately modeled by an OPNET-supplied example model.
The Ethernet model is to complex too be modeled in this lab. Instead we will use the
OPNET-supplied example model.
Our Ethernet network consists of a multi-tap bus network populated by eight nodes. The
nodes employ the node model ethcoax_station_adv.
The ethcoax_station_adv node model is significantly more complex than the Aloha or
CSMA node models. It has four processor modules, a queue module which performs the
bulk of the channel access processing, and a pair of bus receiver and transmitter modules.
(Figure 91)
Figure 91 - Ethcoax_station_adv node model
The bus_tx and bus_rx modules serve as the bus link interface. These modules are set to
transmit and receive at a data rate of 10 Mbits/second by default.
Figure 92 - bus_tx attributes
Master thesis MEE 03:24
Tommy Svensson 98
Alex Popescu
The sink processor represents higher layers and simply accepts
incoming packets that have been processed through the mac (medium access control)
process.
The defer processor independently monitors the links condition and maintains a
deference flag that the mac process reads over a statistic wire to decide whether
transmission is allowed.
The bursty_gen module represents higher layer users who submit data for transmission.
It uses an ON-OFF pattern for traffic generation.
The mac process handles both incoming and outgoing packets. Incoming packets are
decapsulated from their Ethernet frames and delivered to a higher level process. Outgoing
packets are encapsulated within Ethernet frames and when the deference flag goes low, a
frame is sent to the transmitter. This process also monitors for collisions, and if one
occurs, the transmission is appropriately terminated and rescheduled for a later attempt.
231) Open a new project. File New and choose project.
232) Name the project <initials>_ethernet and the scenario bus.
233) Create an empty scenario. Click next.
234) Choose Office. Click next.
235) Choose X span 100 and Y span 100. Click next.
236) Include ethcoax. Click next.
237) Review the settings then click OK.
Proceed by constructing the network.
238) Use the rapid configuration tool. Topology Rapid configuration.
239) Choose bus. Click OK.
Master thesis MEE 03:24
Tommy Svensson 99
Alex Popescu
240) Make the following configuration:
Node model: ethcoax_station
Link model: eth_coax
Tap model: eth_tap
Number: 8
Placement: Horizontal, Top of bus and Bottom of bus.
Head of bus: X=10 and Y=50
Bus: 80
Tap: 20
Figure 93 - Rapid Configuration dialog
241) Click OK.
242) Right click on one node and choose select similar nodes from the pop-up menu.
243) Right click on a node and select edit attributes.
Master thesis MEE 03:24
Tommy Svensson 100
Alex Popescu
244) Make the following configuration:
Traffic Generation Parameters
Start Time: constant (5.0)
ON State Time: Exponential (100)
OFF State Time: Exponential (0)
Packet Generation Arguments
Interarrival time: Exponential (0.01333)
Packet Size: Constant (1250)
Segmentation size: No segmentation
Stop time: Never
Figure 94 - Node attributes
245) Check the Apply Changes to Selected Objects check box. (figure 95)
Figure 95 Apply Changes to Selected Objects check box
246) Save the project with the default name. File Save.
The network model is completed. To gather the statistics of interest a probe model is
needed.
247) Select File New and choose probe model from the menu. Click OK.
The statistic of interest is the bus utilization.
248) Add a link statistic probe. Click on the add link statistic probe action button.
249) Choose network model to probe. Select Object Set Network Model.
250) Click on <initials>_ethernet-bus in the list.
Master thesis MEE 03:24
Tommy Svensson 101
Alex Popescu
251) Right click on the link probe and select choose probed link.
252) Expand the tree and then select top.Office Network.bus 0. Click OK.
Figure 96 - Link object tree
253) Right click on the link probe and choose edit attributes.
254) Set the name attribute to Bus Utilization.
255) Set the statistic attribute to bus.utilization.
256) Save the probe as <initials>_ethernet-probe.
The probe model is now completed. Proceed by executing the simulation.
257) In the project window, select Simulation Configure Discrete Event
Simulation (Advanced).
258) Right click on the scenario and select edit attributes.
259) In the common tab set:
Duration: 60 seconds
Seed: Any arbitrary integer.
260) In the advanced tab set:
Network: <initials>_ethernet-bus
Probe file: <initials>_ethernet-probe
Vector file: <initials>_ethernet-vector
261) Click on the Run action button to execute the simulation.
262) Close the simulation sequence window when the simulation is completed.
263) Open the Analysis Configuration tool. File New and then Analysis
Configuration.
264) Click on the create graph of a statistic action button.
265) Expand File statistic.<initials>_ethernet-vector.object statistics.Office
Network.bus_0 [0].bus.
266) Check the utilization statistic.
Master thesis MEE 03:24
Tommy Svensson 102
Alex Popescu
267) Choose Average from the menu and click Show.
Figure 97 - View results dialog
Master thesis MEE 03:24
Tommy Svensson 103
Alex Popescu
The graph should resemble the one below.
As you can see, the throughput after 30 seconds of simulation stabilizes near
5.5 Mbps/sec. This demonstrates the superiority of the carrier-sensing, collision-
detection, and backoff strategies used by Ethernet over the less sophisticated methods
used by the pure Aloha and CSMA protocols.
The lab is now completed.
Master thesis MEE 03:24
Tommy Svensson 104
Alex Popescu
Laboratory 4
TCP simulation
Objective
The purpose of this lab is to demonstrate the functioning of TCP, and particularly the four
algorithms used for congestion control: slow start, congestion avoidance, fast retransmit
and fast recovery. The lab provides a number of scenarios to simulate and compare these
algorithms.
Overview
In this lab we will study TCPs four intertwined congestion control algorithms, namely:
slow start, congestion avoidance, fast retransmit and fast recovery.
The objectives are:
To study the behavior and implementation of slow start and congestion avoidance
algorithms.
To study modifications to the congestion avoidance algorithm, namely fast
retransmit and fast recovery.
Procedure
Slow start and congestion avoidance
Previous versions of TCP start a connection with the sender injecting multiple segments
into the network, up to the windows size advertised by the receiver. This is ok when the
hosts are placed on the same LAN. But if there are routers and slower links between the
sender and the receiver different problems can arise. Some intermediate router must
queue the packets and it is possible for the router to run out of space in the queue. The
algorithm to avoid this is called slow start.
Beginning transmission into a network with unknown conditions requires TCP to slowly
probe the network to determine the available capacity, in order to avoid congesting the
network with an inappropriate large burst of data.
Slow start adds another window to the senders TCP: the congestion window, called
cwnd. When a new connection is established with a host on another network, the
congestion window is initialized to one segment (typically 536 bytes or 512 bytes). The
sender starts by transmitting one segment and waiting for its ACK. When that ACK is
received, the congestion window is increased from one to two, and two segments can be
sent. When each of those two segments is acknowledged, the congestion window is
increased to four. This provides an exponential growth, although it is not exactly
exponential because the receiver may delay its ACKs, typically sending one ACK every
two segments that it receives. The sender can transmit up to the minimum of the
congestion window and the advertised window. The congestion window is flow control
Master thesis MEE 03:24
Tommy Svensson 105
Alex Popescu
imposed by the sender, while the advertised window is flow control imposed by the
receiver.
At some point the capacity of the internet can be reached and an intermediate router will
start discarding packets. This tells the sender that its congestion window has gotten too
large.
Congestion avoidance is a way to deal with lost packets. Congestion can occur when data
arrives on a big pipe (a fast LAN) and outputs on a smaller pipe (a slower WAN).
Congestion can also occur when multiple input streams arrive at a router whose output
capacity is less than the sum of the inputs. There are two indications of packet loss at a
sender: a timeout occurring and the receipt of duplicate ACKs. However, the overall
assumption of the algorithm is that packet loss caused by damage is very small (much
less than 1%), therefore the loss of a packet signals congestion somewhere in the network
between the source and destination.
Although congestion avoidance and slow start are independent algorithms with different
objectives, in practice they are implemented together. When congestion occurs TCP must
slow down its transmission rate of packets into the network, and then invokes slow start
to get things going again. [3]
The combined congestion avoidance and slow start algorithms require that two variables
are maintained for each connection:
A congestion window (cwnd).
A slow start threshold size (ssthresh).
The combined algorithm operates as follows:
a) Initialization for a given connection sets cwnd to one segment and sstresh to 65535
bytes.
The initial value of cwnd must be less than or equal to 2*SMSS bytes and must not be
more than 2 segments. SMSS, Sender Maximum Segment Size, is the size of the largest
segment that the sender can transmit.
The initial value of cwnd may be arbitrarily high (some implementations use the size of
the advertised window), but it may be reduced in response to congestion.
b) The TCP output routine never sends more than the minimum of cwnd and receivers
advertised window.
c) When congestion occurs one-half of the current window size is saved in ssthresh.
Additionally, if the congestion is indicated by a timeout, cwnd is set to one segment.
Congestion is indicated by a timeout or the reception of duplicate ACKs.
d) When new data is acknowledged by the other end, increase cwnd. The way in which
cwnd is increased depends on whether TCP is performing slow start or congestion
avoidance. If cwnd is less than or equal to ssthresh, TCP is in slow start, otherwise TCP
is performing congestion avoidance. Slow start continues until TCP is halfway to where it
Master thesis MEE 03:24
Tommy Svensson 106
Alex Popescu
was when congestion occurred, and then congestion avoidance takes over. This is done
due to the recorded half of the window size that caused the problem.
As mentioned earlier slow start increases congestion window (cwnd) exponentially.
Congestion avoidance on the other hand dictates that congestion window (cwnd) be
incremented by segsize * segsize / cwnd each time an ACK is received, where segsize is
the segment size and cwnd is maintained in bytes. This results in a linear growth of
cwnd, compared to slow starts exponential growth. The increase in cwnd should be at
most one segment each round-trip time (regardless how many ACKs are received in
that RTT) whereas slow start increments cwnd by the number of ACKs received in a
round-trip time. [2]
Slow start and congestion avoidance simulation
This network setup utilizes TCP as its End-to-End transmission protocol. One server is
placed in Paris and one client is placed in Stockholm. The Congestion window size will
be analyzed with different mechanism. This network is assumed to be perfect with no
packet loss.
Master thesis MEE 03:24
Tommy Svensson 107
Alex Popescu
Create the network
1) Start OPNET and create a new project. File New and choose project
in the pop-up window.
2) Name the project <initials>_TCP and the scenario NoDrop. Click OK.
3) Select Create Empty Scenario and click next.
4) Select Choose From Maps and click next.
5) Choose Europe from the maps and click next.
6) Do not include any technologies and click next.
7) Review the values and click OK.
8) Open the Object palette if its not already open and make sure that the
opened palette is internet_toolbox.
Figure 98 - Internet toolbox selected in the object palette
9) Add an Application Config object to the workspace and rename it to
Applications.
10) Right click on the Applications node and choose Edit Attributes.
11) Click in the value column on the Application Definitions row. Choose
Edit
Figure 99 - Applications attributes
12) Set the Rows attribute value to 1.
13) Set the Application name to FTP_Application. Click OK.
14) Go to Application definitions Row 0 Description FTP and
choose Edit
15) Set the following values:
Master thesis MEE 03:24
Tommy Svensson 108
Alex Popescu
Attribute Value
Command Mix (Get/Total) 100%
Inter-Request Time (seconds) constant (3600)
File Size (bytes) constant (9000000)
Symbolic Server Name FTP Server
Type of service Best Effort (0)
RSVP Parameters None
Back-End Custom Application Not Used
16) Click OK.
17) Click OK to close Application Attributes.
18) Add a Profile Config object to the workspace and rename it to Profiles.
19) Right click on the Profile node and choose Edit attributes
20) Click in the value column on the Profile Configuration row. Choose
Edit
Figure 100 - Profiles attribute
21) Set the Rows attribute to 1.
22) Set Profile Name to FTP_Profile.
23) Set Operation Mode to Serial (Ordered).
24) Set Start Time to constant (100) and Duration to End of Simulation.
25) Set Repeatability to Once at Start Time.
26) Click in the Applications column and choose Edit
27) Set the Rows attribute to 1.
28) Set Name to FTP_Application.
29) Set Start Time Offset to constant (5) and Duration to End of Profile.
30) Set Repeatability to Once at Start Time.
31) Click OK to close the Applications Table.
Master thesis MEE 03:24
Tommy Svensson 109
Alex Popescu
32) Click OK to close the Profile Configuration Table.
The Profiles Attributes should look like the picture below:
Figure 101 - Profiles Attributes
33) Click OK to close the Profiles Attributes dialog.
Master thesis MEE 03:24
Tommy Svensson 110
Alex Popescu
Create the Paris subnet
34) Place a subnet in Paris.
35) Set the name to Paris.
36) Double click on the Paris subnet node.
37) Place an ethernet_server in the workspace. Rename it to Server_Paris.
38) Place an ethernet4_slip8_gtwy router in the workspace next to the server.
39) Rename it to Router_Paris.
40) Connect the server and the router with a 100BaseT cable.
41) Right click on Server_Paris and choose Edit Attibutes
42) Go to the Application: Supported Services attribute and choose Edit
Figure 102 - Server Paris attributes
43) Set the Rows attribute to 1.
44) Choose the name FTP_Application and click OK.
45) Edit the Server Address attribute and set value to Server_Paris.
46) Expand TCP Parameters.
47) Disable both Fast Retransmit and Fast Recovery.
48) Click OK.
49) Save the project. File Save.
Master thesis MEE 03:24
Tommy Svensson 111
Alex Popescu
Figure 103 - Paris Subnet nodes
50) Click the Go to next higher level action button.
The Paris subnet is now configured.
Master thesis MEE 03:24
Tommy Svensson 112
Alex Popescu
Create the Stockholm subnet
51) Place a subnet in Stockholm.
52) Set the name to Sthlm.
53) Double click on the Sthlm subnet node.
54) Place an ethernet_wkstn in the workspace. Rename it to Client_Sthlm.
55) Place an ethernet4_slip8_gtwy router in the workspace next to the client.
56) Rename it to Router_Sthlm.
57) Connect the client and the router with a 100BaseT cable.
58) Right click on the Client_Sthlm node and choose Edit Attributes
59) Go to the Application: Supported Profiles and choose Edit
Figure 104 - Edit Application: Supported Profiles
60) Set the Rows attribute to 1.
61) Change the Profile Name attribute to FTP_Profile.
62) Click OK.
63) Set the Client Address attribute value to Client_Sthlm.
64) Go to the Application: Destination Preferences and choose Edit
65) Set the Rows attribute to 1.
66) Set the Symbolic Name attribute to FTP Server.
67) Click in the Actual name column.
68) Set the Name attribute to Server_Paris. Click OK to close Actual name
table dialog.
69) Click OK to close Application: Destination Preferences dialog.
Master thesis MEE 03:24
Tommy Svensson 113
Alex Popescu
70) Click OK to close Client_Sthlm Attributes dialog.
71) Save the project. File Save.
The Stockholm subnet is now configured.
Figure 105 - Subnet Sthlm nodes
72) Click the Go to next higher level action button.
Master thesis MEE 03:24
Tommy Svensson 114
Alex Popescu
Create the IP Cloud
73) Place an ip32_cloud on the workspace between Stockholm and Paris.
74) Set the name to Europa_Internet.
75) Connect the Paris subnet to the Europa_Internet IP Cloud with a
PPP_DS3 cable.
76) Select Paris.Router_Paris in the pop-up menu.
77) Connect the Sthlm subnet to the Europa_Internet IP Cloud with a
PPP_DS3 cable.
78) Select Sthlm.Router_Sthlm in the pop-up menu.
The IP Cloud is now configured.
Figure 106 - Network overview
Master thesis MEE 03:24
Tommy Svensson 115
Alex Popescu
Choose Statistics
79) Enter the Paris Subnet.
80) Right click on Server_Paris and select Choose Indivitual Statistics from
the pop-up menu.
81) Expand Node Statistics TCP Connection and select Congestion
Windows Size (bytes)
Figure 107 Choose Results dialogue
82) Right click on the Congestion Window Size (bytes) and select Change
Collection mode.
83) Check the Advanced checkbox in the pop-up dialog.
84) Change Capture mode to all values.
85) Click OK to close the dialog.
Master thesis MEE 03:24
Tommy Svensson 116
Alex Popescu
86) Click OK to close the Choose results dialog.
87) Save the project. File Save.
Master thesis MEE 03:24
Tommy Svensson 117
Alex Popescu
Slow start and Congestion avoidance simulation
88) Select Simulation Configure Discrete Event Simulation in the menu.
89) Set Duration to 10 minutes.
90) Click Run.
91) Click Close when the simulation has finished.
View the results
92) Right click on the workspace and choose View Results.
93) Expand Object statistics Choose From Maps Network Paris
Server Paris TCP Connection and select Congestion Window Size.
94) Click Show.
The graph should resemble the one below.
Figure 108 - Slow start and Congestion Avoidance
Master thesis MEE 03:24
Tommy Svensson 118
Alex Popescu
Fast retransmit
Fast retransmit is a modification to the congestion avoidance algorithm.
The TCP sender should use fast retransmit algorithm to detect and repair loss, based on
incoming duplicate ACKs. The fast retransmit algorithm uses the arrival of 3 duplicate
ACKs (4 identical ACKs without the arrival of any other intervening packets) as an
indication that a segment has been lost. After receiving 3 duplicate ACKs, TCP
performs a retransmission of what appears to be the missing segment, without waiting for
the retransmission timer to expire. The fast retransmit algorithm first appeared in the
4.3BSD Tahoe release.
Fast recovery
Congestion avoidance without slow start is performed after fast retransmit sends what
appears to be the missing segment. It is an improvement that allows high throughput
under moderate congestion, especially for large windows.
In this case the reason for not performing slow start is that the receipt of duplicate
ACKs tells TCP that more than just one packet has been lost. Since the receiver can
only generate the duplicate ACK when another segment is received, that segment has left
the network and is in the receivers buffer. In other words there is still data flowing
between the two ends, and TCP does not want to reduce the flow abruptly by going into
slow start. The fast recovery algorithm appeared in the 4.3BSD Reno release.
The fast retransmit and fast recovery algorithms are usually implemented together as
follows:
a) When the third duplicate ACK is received, set ssthresh to no more than one-half the
current congestion window, cwnd, but no less than two segments. Retransmit the missing
segment, and then set cwnd to ssthresh plus 3 times the segment size. This increases the
congestion window by the number of segments that have left the network and which the
other end has cached.
b) Each time another duplicate ACK arrives, increment cwnd by the segment size. This
inflates the congestion window for the additional segment that has left the network.
c) Transmit a segment (packet) if allowed by the new value of cwnd and the receivers
advertised window.
d) When the next ACK arrives that acknowledges new data, set cwnd to ssthresh. This
ACK should be the acknowledgment of the retransmission from step a, one round-trip
time after the retransmission. Additionally, this ACK should acknowledge all the
intermediate segments sent between the lost packet and the receipt of the first duplicate
ACK. This step is congestion avoidance, since TCP is down to one-half the rate it was at
when the packet was lost.
Master thesis MEE 03:24
Tommy Svensson 119
Alex Popescu
Fast Retransmit and Fast Recovery simulation
Two additional scenarios will be created to study the behavior of fast retransmit and
fast recovery algorithms. The network just created was assumed to be perfect with no
packet loss. In the following scenarios packet loss will be introduced.
Create the Tahoe scenario
95) Select Scenarios Duplicate Scenario.
96) Name the scenario Tahoe.
97) Right click on the IP Cloud, Europa Internet, and choose Edit Attributes.
98) Set the Packet Discard Ratio attribute to 0.5%.
Figure 109 - Europa internet attributes
99) Click OK.
100) Enter the Paris subnet.
101) Right click on Server_Paris and choose Edit Attributes
102) Expand TCP Parameters.
103) Change the Fast Retransmit attribute to Enabled.
Figure 110 - Server Paris TCP attributes
104) Click OK.
105) Save the project. File Save.
Create the Reno scenario
106) Select Scenarios Duplicate Scenario.
107) Name the scenario Reno.
108) Right click on the Server_Paris and choose Edit Attributes
Master thesis MEE 03:24
Tommy Svensson 120
Alex Popescu
109) Expand TCP Parameters.
110) Change the Fast Recovery attribute to Reno.
Figure 111 - Server Paris TCP attributes
111) Click OK.
112) Save the project. File Save.
Simulate the scenarios
113) Select Scenarios Manage scenarios.
114) Change the Results attribute to collect or recollect.
Figure 112 - Manage Scenarios dialog
115) Click OK.
116) Click Close when the simulations has finished.
View results
117) Right click on the workspace and choose Compare Results.
118) Expand Object statistics Choose From Maps Network Paris
Server Paris TCP Connection.
119) Check Congestion Window size (bytes).
120) Select Statistics Stacked in the bottom left roll-down menu.
Master thesis MEE 03:24
Tommy Svensson 121
Alex Popescu
Figure 113 - Compare results dialog
121) Click Show.
The graph should resemble the one below.
Figure 114 - Resluts Graphs
The first graph illustrates the NoDrop scenario which has no packet loss.
Master thesis MEE 03:24
Tommy Svensson 122
Alex Popescu
The second graph illustrates the Tahoe scenario which has 0.5% packet loss. When
congestion is indicated by a timeout, cwnd is set to one segment. In other words, slow
start is performed.
The third graph illustrates the Reno scenario which also has 0.5% packet loss. The
congestion window size does not drop to zero as in the Tahoe graph. Fast recovery is
performed instead of slow start.
The lab is completed.
Master thesis MEE 03:24
Tommy Svensson 123
Alex Popescu
Laboratory 5
OSPF simulation
Objective
The purpose of this lab is to demonstrate the behavior of OSPF routing protocol.
Overview
In this lab we will study the OSPF routing protocol. The objective is to construct a
network and configure it with all the necessary parameters for OSPF routing. Using this
network we will analyze the behavior of the OSPF routing protocol.
Procedure
The Open Shortest Path First (OSPF) protocol is an interior gateway protocol (IGP) used
for routing in Internet Protocol (IP) networks. As a link state routing protocol, OSPF is
more robust against network topology changes than distance vector protocols such as
RIP, IGRP, and EIGRP. OSPF can be used to build large scale networks consisting of
hundreds or thousands of routers.
Open Shortest Path First (OSPF) uses the Dijkstras algorithm to compute the shortest
path to a destination. The algorithm calculates the shortest path to each destination based
on the cumulative cost required to reach that destination. The cumulative cost is a
function of the cost of the various interfaces needed to be traversed in order to reach that
destination.
The cost (or the metric) of an interface in OSPF is an indication of the overhead required
to send packets across that interface. The cost of an interface is calculated based on the
bandwidth -- it is inversely proportional to the bandwidth of that specific interface (i.e., a
higher bandwidth indicates a lower cost). For example, the cost of a T1 interface is much
higher than the cost of a 100Mbit Ethernet interface because there is more overhead (e.g.,
time delays) involved in crossing a T1 interface.[5]
Characteristic features of OSPF
Link State Based
Runs directly over IP
Interior or border gateway protocol
Multiple paths to each destination. Load balancing.
Link-attribute based costing. Costing is statically assigned.
[6]
Master thesis MEE 03:24
Tommy Svensson 124
Alex Popescu
Create the network
1. Start OPNET and create a new project. File New and choose
Project.
2. Name the project <initials>_OSPF and the scenario NoAreas. Click OK.
3. Select Create empty scenario and click next.
4. Select Office and click next.
5. Set X Span to 200 and Y Span to 200. Click next.
6. Do not include any technologies and click next.
7. Review the values and click OK.
8. Open the Object palette and change the palette to routers.
Figure 115 Object palette dialog
9. Click OK.
10. Place ten slip8_gtwys in the workspace as in figure 117.
11. Change the object palette to internet_toolbox.
Figure 116 - Object palette
12. Connect all the routers using PPP_DS3 link as in figure 117.
Master thesis MEE 03:24
Tommy Svensson 125
Alex Popescu
13. Rename all the routers as in figure 117. Right click on each router and
select Set Name from the pop up menu.
Figure 117 - Network overview
Master thesis MEE 03:24
Tommy Svensson 126
Alex Popescu
Configure router interfaces
We need to designate the interfaces of all routers that use the OSPF protocol. By default,
RIP is used on every router interface.
There are three ways to configure router interfaces to use a particular set of routing
protocols:
Method Characteristics When to Use
Protocols IP
Routing Configure
Routing Protocols menu
operation
Any number of interfaces
can be configured at the
same time
Overwrites the
IP Routing Parameters
Interface Information
Routing Parameters
attribute
Multiple routing protocols
can be specified.
In most cases.
IP Routing Parameters
Interface Information
Routing Protocols
Only one interface can be
configured at a time.
When one wants to add a
protocol to those already
designated on a particular
interface.
IP Dynamic Routing
Protocol simulation
attribute
Does not modify router
attributes
Overrides the routing
protocols configured on the
router interfaces for the
duration of the simulation
One routing protocol used
on all interfaces
When this attribute is set
to Default, the protocols
specified on the router
interfaces are used.
You have configured the
routing protocols in your
network but want to see the
effects of running a single
protocol throughout the
network.
The easiest way to designate routing protocols is the Configure Routing Protocols
operation from the Protocols IP Routing menu. This operation has the same effect
as manually setting the interface routing protocol attributes, but with the added advantage
of being able to configure multiple interfaces at the same time. The previous setting on
the interface is overwritten each time this operation is used.
1. Open the Protocols IP Routing Configure Routing Protocols
menu.
Master thesis MEE 03:24
Tommy Svensson 127
Alex Popescu
2. Check the OSPF check box. Figure 118.
3. Select the All interfaces radio button. Figure 118.
Figure 118 - Configure routing protocols dialog
4. Save the project.
Master thesis MEE 03:24
Tommy Svensson 128
Alex Popescu
A Routing Domain Legend appears in the bottom left corner on the workspace. All links
should have a green O attached to it. This indicates that OSPF routing protocol is used
over that link. Figure 119.
Figure 119 - Routing Domain Legend and Link indication
Assign addresses to the router interfaces.
The Protocols IP Addressing Auto-Assign IP Addresses operation assigns a
unique IP address to the connected IP interfaces whose IP address is currently set to auto-
assigned. This operation does not change the value of manually set IP addresses.
1. Use the Protocols IP Addressing Auto-Assign IP Addresses.
The message Assignes 40 IP addresses appear in the status bar. Figure 120.
Figure 120 - Status bar
Master thesis MEE 03:24
Tommy Svensson 129
Alex Popescu
Configure routing cost
Cost is specified on a per interface basis and is used as the basis for the shortest path
route calculation.
There are two ways of setting this Cost attribute for each interface.
A. Per-interface: The interface information table is located by right clicking on a
router and selecting the Edit attributes option. Figure 121. One can manually
specify the cost of an interface by editing the value with the desired cost setting.
For example, the default value of Auto Calculate can be over-written by any
positive integer cost value: When set to Auto Calculate, the formula used to
calculate the cost is based on the interface speed and another configurable
attribute called Reference Bandwidth:
Bandwith Interface
Bandwith ference
t Interface
_
_ Re
cos _ =
Note: The default value for Reference Bandwidth is 1000 Mbps; therefore, it will
cost 1,000,000,000/100,000,000 = 10 to traverse a 100Mbps Ethernet interface
and it will cost 1,000,000,000/1,544,000 = 647 to cross a T1 serial line interface.
The default for Interface Bandwidth is computed dynamically using the data rate
of the connected interface. It can be over-written by using the Bandwidth setting
in the Protocols IP Routing Configure Interface Metric Information
table.
Figure 121 - Router attributes
Master thesis MEE 03:24
Tommy Svensson 130
Alex Popescu
B. Globally for all interfaces: If wanted to change the interface cost across all
interfaces, then, rather than individually setting them on each interface, one can
use the model-wide cost configuration option using the following menu option:
Protocols OSPF Configure Interface Cost. This operation will allow for
choosing one of the following two cost configuration options:
B1) The Reference Bandwidth will be set for all routers. All interfaces will be
set with a cost value of Auto Calculate.
B2) All interfaces will be set with the specified cost value. The
interface/bandwidth settings will be ignored.
Figure 122 - OSPF Interface Cost Configuration dialog
In this lab we use different bandwidths on the links to set different costs.
1. Select the links between:
Router A Router B
Router B Router D
Router D Router C
Router C Router A
Router B Router C
by shift clicking on them.
2. Open the Configure Interface Metric Information dialog. Protocols IP
Routing Configure Interface Metric Information.
3. Set the Bandwidth value to 5000 kbps.
4. Select Interfaces across selected links radio button. Click OK.
5. Select the links between:
Router B Router E
Router E Router G
Router I Router F
Router F Router D
Router E Router F
by shift clicking on them.
Master thesis MEE 03:24
Tommy Svensson 131
Alex Popescu
6. Open the Configure Interface Metric Information dialog. Protocols IP
Routing Configure Interface Metric Information.
7. Set the Bandwidth value to 20000 kbps.
8. Select Interfaces across selected links radio button. Click OK.
9. Select the links between:
Router G Router H
Router H Router J
Router J Router I
Router I Router G
Router G Router J
by shift clicking on them.
10. Open the Configure Interface Metric Information dialog. Protocols IP
Routing Configure Interface Metric Information.
11. Set the Bandwidth value to 10000 kbps.
12. Select Interfaces across selected links radio button. Click OK.
13. Save the project.
The cost configuration looks as in figure 123:
Figure 123 - Cost overview
Master thesis MEE 03:24
Tommy Svensson 132
Alex Popescu
Configure the traffic demands
1. Select both Router B and Router D by shift clicking on them.
2. Open the Create traffic demands menu. Protocols IP Demands
Create Traffic Demands
3. Select From Router B radio button.
4. Click Create.
5. Select both Router C and Router J by shift clicking on them.
6. Open the Create traffic demands menu. Protocols IP Demands
Create Traffic Demands
7. Select From Router C radio button.
8. Click Create.
The paths of the traffic demands are now visible. To hide them select View Demand
Objects Hide All.
Configure Simulation
1. Open the Configure Discrete Event Simulation dialog.
2. Set duration to 10 minutes.
3. Click OK.
4. Save the project.
Duplicate the scenario
In the scenario just created all routers belong to the same level of hierarchy, i.e., one
area. No load balancing where enforced for any routers. Two new scenarios will be
created to implement areas and load balancing.
Areas scenario
The major addition in OSPF configuration, relative to other protocols, is that the OSPF
routing domain can be divided into smaller segments called areas. This reduces memory
and computational load on the routers. Each area is numbered and there must always be
an area zero, which is the backbone. All other areas attach to the backbone either
directly or via virtual links. An area should contain no more than about 50-100 routers
for optimum performance. A router that connects to more than one area is called an Area
Border Router (ABR).
1. Duplicate the scenario. Scenarios Duplicate scenario
2. Name the scenario Areas.
Partition the network into areas. This is a physical partitioning in the sense that an
interface can belong to only one area. The distinct interfaces of the same router may still
belong to separate areas.
Master thesis MEE 03:24
Tommy Svensson 133
Alex Popescu
3. Select the links between:
Router A Router B
Router B Router D
Router D Router C
Router C Router A
Router B Router C
by shift clicking on them.
4. Open the OSPF Area Configuration dialog. Protocols OSPF Configure
Areas.
5. Set the value 1 to Area Identifier.
6. Click OK.
7. Select the links between:
Router B Router E
Router E Router G
Router I Router F
Router F Router D
Router E Router F
by shift clicking on them.
8. Open the OSPF Area Configuration dialog. Protocols OSPF Configure
Areas.
9. Set the value 0 to Area Identifier.
10. Click OK.
11. Select the links between:
Router G Router H
Router H Router J
Router J Router I
Router I Router G
Router G Router J
by shift clicking on them.
12. Open the OSPF Area Configuration dialog. Protocols OSPF Configure
Areas.
13. Set the value 2 to Area Identifier.
14. Click OK.
15. Visualize the areas. Protocols OSPF Visualize Areas
16. Click OK in the pop-up dialog.
17. Save the project.
The areas are visualized in different colors.
Balanced Scenario
Load balancing is a concept that allows a router to take advantage of multiple best paths
(routes) to a given destination. If two routes to the same destination have the same cost,
the traffic will be distributed half to each.
Master thesis MEE 03:24
Tommy Svensson 134
Alex Popescu
1. Go back to the NoAreas scenario. Scenarios Switch To Scenario
NoAreas.
2. Duplicate the scenario. Scenarios Duplicate scenario
3. Name the scenario Balanced.
4. Select both Router C and Router J by shit clicking on them.
5. Open the Configure Load Balancing Option dialog. Protocols IP
Routing Configure Load Balancing Option.
6. Select Packet based in the roll-down menu.
7. Select the Selected Routers radio button.
8. Click OK.
9. Save the project.
Figure 124 - Configure Load Balancing Option dialog
Run the simulation
1. Open the Manage Scenarios dialog. Scenarios Manage Scenarios
2. Click in the Results column on the NoAreas row and click the collect button.
3. Set the scenarios Area and Balanced to collect results. Repeat the previous step.
Figure 125 - Manage Results dialog
4. Click OK to run the simulation.
5. Click Close when the simulation has finished.
Master thesis MEE 03:24
Tommy Svensson 135
Alex Popescu
View the results
NoAreas scenario
1. Switch to the NoAreas scenario. Scenarios Switch to Scenario NoAreas.
2. Open the Route Report for IP Traffic Flows dialog. Protocols IP
Demands Display Routes for Configured Demands
3. Expand Sources Router B Router D.
4. Select Router B Router D.
5. Change the Display attribute to Yes. Figure 126.
Figure 126 - Route Report for IP Traffic Flows dialog
The traffic flow should look like figure 127.
Figure 127 NoAres scenario. Router B Router D traffic flow
Master thesis MEE 03:24
Tommy Svensson 136
Alex Popescu
6. Change the Display attribute for Router B Router D to No.
7. Expand Sources Router C Router J.
8. Select Router C Router J.
9. Change the Display attribute to Yes. Figure 128.
Figure 128 - - Route Report for IP Traffic Flows dialog
The traffic flow should look like figure 129.
Figure 129 NoAres scenario. Router C Router J traffic flow
Master thesis MEE 03:24
Tommy Svensson 137
Alex Popescu
Areas scenario
1. Switch to the Areas scenario. Scenarios Switch to Scenario Areas.
2. Open the Route Report for IP Traffic Flows dialog. Protocols IP
Demands Display Routes for Configured Demands
3. Expand Sources Router B Router D.
4. Select Router B Router D.
5. Change the Display attribute to Yes.
The traffic flow should look like figure 130.
Figure 130 - Ares scenario. Router B Router D traffic flow
Master thesis MEE 03:24
Tommy Svensson 138
Alex Popescu
Balanced scenario
1. Switch to the Balanced scenario. Scenarios Switch to Scenario Balanced.
2. Open the Route Report for IP Traffic Flows dialog. Protocols IP Demands
Display Routes for Configured Demands
3. Expand Sources Router C Router J.
4. Select Router C Router J.
5. Change the Display attribute to Yes.
The traffic flow should look like figure 131.
Figure 131 - Balanced scenario. Router C Router J traffic flow
The lab is completed.
Master thesis MEE 03:24
Tommy Svensson 139
Alex Popescu
Laboratory 6
Queuing policies
Objective
The purpose of this lab is to demonstrate the behavior of different queuing disciplines.
Overview
In this lab we will look at one aspect of the DS (Differentiated Services) architecture
which is queue management and traffic shaping. The simulation package OPNET has
been used in this study. Based on the DS value, packets may be put in separate queues,
and various forwarding policies can be used to favor high priority packets in different
ways. The policies that are studied here are: FIFO (First In First Out), PQ (Priority
Queuing), WFQ (Weighted Fair Queuing).
Procedure
Originally, the Internet was designed for data processing applications where delays were
relatively unimportant. In most cases a best effort delivery service was adequate, and in
case of loss or corruption of data, the TCP protocol would take care of the necessary
retransmission and recovery. Nowadays these requirements have been changed due to the
growth of multimedia application which are bandwidth hungry and require megabits per
second rather than the kilobits per second required for traditional data processing
applications. Todays application are more or less sensitive for the delays experienced
when transmitting over Internet. It is therefore important to keep track of the delay and
delay variation or jitter and insure that they dont grow to big. There is thus a need to
support a variety of traffic with different quality of service (QoS). The central issue is
how to share available resources in times of congestion. For doing this, diverse
mechanisms are needed to differentiate between different types of traffic (priority).
Master thesis MEE 03:24
Tommy Svensson 140
Alex Popescu
Copy files
1. Copy the model files from the CD-ROM and place them on the hard drive.
2. Edit the Opnet environment file, env_db9.0. On Windows XP it is located in
C:\Documents and Settings\<profile>\op_admin
3. Add the path where the files are placed to mod_dirs.
Figure 132 - Opnet enviroment file
Master thesis MEE 03:24
Tommy Svensson 141
Alex Popescu
FIFO queuing
First-in-first-out (FIFO) is the simplest type of queuing. The incoming packets are placed
in a single queue and are served in the order as they where received. This queuing policy
requires very little computation and its behavior is very predicable, i.e. packet delay is a
direct function of the queue size.
There are many undesirable properties related to this queuing policy, due to the simplistic
nature.
It is impossible to offer different services for different packet classes since all
packets are inserted into the same queue.
If an incoming flow suddenly becomes bursty, then it is possible for the entire
buffer space to be filled by this single flow and other flows will not be serviced
until the buffer is emptied.
Figure 133 - FIFO queue
Master thesis MEE 03:24
Tommy Svensson 142
Alex Popescu
Create the FIFO network
1. Start OPNET and create a new project. File New and choose Project.
2. Name the project <initials>_queue_ disciplines and the scenario Fifo. Click OK.
3. Click Quit.
4. Open the Object palette.
5. Click the Configure palette button.
6. Clear the palette. Click the Clear button.
7. Choose which node models to include. Click the Node models button.
8. Include ta_fifo node model. Click OK.
Figure 134 - Include node models dialog
9. Click SAVE in the Configure Palette dialog. Use the default filename.
10. Click OK to close the Configure Palette dialog.
11. Click and drag ta_fifo node model from the Object palette to the workspace.
12. Right click on node model in the workspace and choose set name. Set the name
to fifo_infinite_buffer.
13. Double click on the fifo node model.
The node model that appears should resemble the one in figure 135.
The model has three packet sources which generates packets to the fifo_queue. The
packets in the queue are served by fifo (First In First Out) queue discipline and sent to the
sink, where they are destroyed.
Master thesis MEE 03:24
Tommy Svensson 143
Alex Popescu
Figure 135 - Fifo queue node model overview
14. Right click on source_1 and choose Edit attributes
15. Verify the values with figure 136.
16. Click OK to close the attribute dialog.
Figure 136 - Source_1 attributes
17. Repeat the same procedure with source_2 and source_3.
Master thesis MEE 03:24
Tommy Svensson 144
Alex Popescu
18. Right click on fifo_queue and choose Edit attributes
19. Right click on subqueue attribute and choose Promote to higher level.
20. Click OK to close the attribute dialog.
Figure 137 - fifo_queue attributes
21. Close the node model window. Save the changes.
22. Right click on the fifo node and choose Edit attributes
23. Expand fifo_queue.subqueue row 0.
24. Set both bit capacity and pk capacity to infinity.
Figure 138 - fifo node subqueue attributes (infinite buffer)
25. Click OK.
Master thesis MEE 03:24
Tommy Svensson 145
Alex Popescu
Duplicate scenario
26. Duplicate the scenario. Choose scenarios duplicate Scenario (Figure 139)
or use shortcut key Ctrl + Shift + D.
Figure 139 - Duplicate scenario menu item
27. Enter the name fifo_finite_buffer.
28. Right click on the fifo node and choose Edit attributes
29. Expand fifo_queue.subqueue row 0.
30. Set bit capacity to infinity and pk capacity to 20.
Figure 140 - Fifo node subqueue attributes (finite buffer)
31. Click OK.
Master thesis MEE 03:24
Tommy Svensson 146
Alex Popescu
Collect statistics
32. Right click on the fifo node.
33. Select Choose individual statistics.
34. Expand Module statistics fifo_queue queue.
35. Check overflow, queue size and queue delay statistics.
Figure 141 - Choose individual statistic dialog
36. Right click on the overflow statistic and choose Change collection mode.
Figure 142 - Change Collection mode
37. Check the Advanced checkbox.
38. Change Collection mode to all values.
Figure 143 - Statistics capture mode
Master thesis MEE 03:24
Tommy Svensson 147
Alex Popescu
39. Click OK.
40. Repeat the same procedure for Queue size (packet) and Queue delay statistics.
41. Click OK to close the dialog.
42. Switch to scenario fifo_infinite_buffer. Scenarios Switch to scenario
fifo_infinite_buffer.
43. Choose the same statistics and capture mode as in fifo_finite_buffer scenario.
Run the simulation
44. From the main menu, select Scenarios Manage scenarios.
45. Choose collect or recollect in the results column.
46. Set Sim duration to 1 hour.
Figure 144 - Manage scenarios dialog
47. Click OK and wait for the simulation to finish.
48. Close the simulation sequence dialog.
Master thesis MEE 03:24
Tommy Svensson 148
Alex Popescu
View the results
49. Right click in the workspace and choose Compare results.
50. Expand Object statistics fifo fifo_queue queue.
51. Check queue size (packets).
52. Choose statistics stacked in the pull down menu. Figure 145.
53. Click Show.
Figure 145 - Compare results dialog
54. Repeat the same procedure for queue delay statistics.
55. Check overflow statistic.
56. Choose differentiator in the middle pull down menu. Figure 146.
57. Choose select scenarios in the right pull down menu. Figure 146.
58. Click Show.
59. Uncheck fifo_infinite_buffer and check fifo_finite_buffer and click OK.
Figure 146 - Compare results dialog
Master thesis MEE 03:24
Tommy Svensson 149
Alex Popescu
The results should resemble the graphs below.
Figure 147 - Fifo Queue size (packet) for infinite and finite buffers
Master thesis MEE 03:24
Tommy Svensson 150
Alex Popescu
Figure 148 - Fifo queue delay for infinite and finite buffers
Master thesis MEE 03:24
Tommy Svensson 151
Alex Popescu
Figure 149 - Packet overflows for finite buffer
Master thesis MEE 03:24
Tommy Svensson 152
Alex Popescu
Priority queuing
A simple way of offering different services to different classes of packets is Priority
Queuing. Its operation involves classifying each incoming packet into different priorities
and placing them into separate queues accordingly. The packets that have the highest
priority are transmitted on the output port before the packets with lower priority. Even
though this queuing policy is a good way of providing differentiated service, it also has
some shortcomings, like large continuous flow of high priority traffic into the queue,
equals excessive delay, and perhaps even service starvation for lower priority packets.
Further, in our case we make use of both a non-preemptive priority network and a
preemptive priority network. The difference between a so-called non-preemptive priority
queuing discipline and a preemptive priority queuing discipline is that the transmission of
a packet in a non-preemptive queuing discipline is not interrupted once it has begun.
Figure 150 - Priority queuing
Create the Non-preemptive priority network, infinite buffer
1. Open a new project. File New
2. Name the project <initials>_priority_queue and the scenario non_preemptive.
3. Click OK.
4. Click Quit button to close the wizard.
5. Open the Object palette.
6. Click the Configure palette button.
7. Clear the palette. Click the Clear button.
8. Choose which node models to include. Click the Node models button.
9. Include jsd_prio and jsd_prmpt_res node model and click OK. Figure 151.
Master thesis MEE 03:24
Tommy Svensson 153
Alex Popescu
Figure 151 - Include node models dialog
10. Click Save and use the default filename.
11. Click OK to close the dialog.
12. Click and drag jsd_prio node model from the Object palette to the workspace.
13. Change the name on the node to nonpreemptive. Right click set name.
14. Double click on the node.
15. Right click on source_1 and choose Edit attributes
16. Set:
ia_time to 1
instruction_range to 9600
priority_range to 0
17. Click OK.
18. Right click on source_2 and choose Edit attributes
19. Set:
ia_time to 1
instruction_range to 9600
priority_range to 1
20. Click OK.
21. Right click on source_3 and choose Edit attributes
22. Set:
ia_time to 1
instruction_range to 9600
priority_range to 2
23. Click OK.
24. Right click on nonpreemptive_priority_queue and choose Edit attributes
Master thesis MEE 03:24
Tommy Svensson 154
Alex Popescu
25. Set:
Processing_rate to 30000
Subqueue rows to 3
Subqueue row 0 bit capacity to infinity
Subqueue row 0 pk capacity to infinity
Subqueue row 1 bit capacity to infinity
Subqueue row 1 pk capacity to infinity
Subqueue row 2 bit capacity to infinity
Subqueue row 2 pk capacity to infinity
26. Click OK.
27. Close the node model and save the changes.
Master thesis MEE 03:24
Tommy Svensson 155
Alex Popescu
28. Right click on the node and
select Choose Individual
Statistics.
29. Check the statistics as in
figure 152.
30. Change Statistic collection
mode to All values. Right
click on the statistic and
choose Change collection
mode.
31. Click OK to close the
Choose Result dialog.
Figure 152 - Choose individual statistics for nonpreemtive priority
queue model
Master thesis MEE 03:24
Tommy Svensson 156
Alex Popescu
Create the Preemptive priority network, infinite buffer
32. Duplicate the scenario and name it preemptive. Scenarios Duplicate scenario.
33. Select the node on the workspace and delete it.
34. Click and drag jsd_prmpt_res node model from the Object palette to the
workspace.
35. Change the name on the node to preemptive. Right click set name.
36. Double click on the node.
37. Right click on source_1 and choose Edit attributes
38. Set:
ia_time to 1
instruction_range to 9600
priority_range to 0
39. Click OK.
40. Right click on source_2 and choose Edit attributes
41. Set:
ia_time to 1
instruction_range to 9600
priority_range to 1
42. Click OK.
43. Right click on source_3 and choose Edit attributes
44. Set:
ia_time to 1
instruction_range to 9600
priority_range to 2
45. Click OK.
46. Right click on preemptive_priority_queue and choose Edit attributes
47. Set:
Processing_rate to 30000
Subqueue rows to 3
Subqueue row 0 bit capacity to infinity
Subqueue row 0 pk capacity to infinity
Subqueue row 1 bit capacity to infinity
Subqueue row 1 pk capacity to infinity
Subqueue row 2 bit capacity to infinity
Subqueue row 2 pk capacity to infinity
48. Click OK.
49. Close the node model and save the changes.
50. Right click and select Choose individual statistics.
51. Choose the same statistics as in nonpreemptive scenario. Dont forget to change
statistic collection mode to all values.
Master thesis MEE 03:24
Tommy Svensson 157
Alex Popescu
Run the infinite buffer simulation
52. Choose Scenarios Manage scenarios from the main menu.
53. Change the value in results column to collect.
54. Change Sim Duration to 1 hour.
55. Click OK and wait for the simulation to finish.
56. Close the simulation dialog.
Master thesis MEE 03:24
Tommy Svensson 158
Alex Popescu
View the infinite buffer simulation results
57. Open Analysis Configuration tool. File New Analysis Configuration.
Figure 153.
Figure 153 - Open a new Analysis configuration tool window
58. Click Create a graph of a statistic button.
59. Expand File statistics <initials>_priority_queue-non_preemptive
Object Statistics nonpreemptive nonpreemptive_priority_queue.
Figure 154.
Figure 154 - Choose File Statistics in Analysis Configuration tool
60. Choose the statistics as in Figure 155.
Master thesis MEE 03:24
Tommy Svensson 159
Alex Popescu
Figure 155 Chosen statistics for nonpreemptive priority queue
61. Choose Statistics Overlaid and time_average in the pull down menus at the
bottom.
Figure 156 - Graph layout setting
62. Click Show.
Master thesis MEE 03:24
Tommy Svensson 160
Alex Popescu
The Graph should resemble Figure 157.
Figure 157 -Queue sizes for Nonpreemptive priority queues
Master thesis MEE 03:24
Tommy Svensson 161
Alex Popescu
63. Expand File statistics <initials>_priority_queue-preemptive Object
Statistics preemptive preemptive_priority_queue. Figure 158.
Figure 158 - Choose File Statistics in Analysis Configuration tool
64. Choose the statistics as in Figure 159.
Figure 159 - Chosen statistics for preemptive priority queue
65. Choose Statistics Overlaid and time_average in the pull down menus at the
bottom.
Figure 160 - Graph layout setting
66. Click Show.
Master thesis MEE 03:24
Tommy Svensson 162
Alex Popescu
The Graph should resemble Figure 161.
Figure 161 - Queue sizes for preemptive priority queues
Master thesis MEE 03:24
Tommy Svensson 163
Alex Popescu
Create the Preemptive priority network, Finite buffer
67. Enter the preemptive node. Double click on the node.
68. Right click on the preemptive_priority_queue and choose Edit attributes
69. Change the subqueues packet capacity to 3. Figure 162.
Figure 162 - Finite buffer queue, packet capacity setting
70. Click OK.
71. Close the node model and save the changes.
72. Right click on the preemptive node and select Choose Individual Statistics.
73. Expand Module Statistics preemptive_priority_queue.subqueue[0]
queue.
74. Check overflows statistic.
75. Right click on the overflows statistics and choose Change Collection Mode.
76. Set Capture mode to All values.
77. Repeat the same procedure on subqueue[1] and subqueue[2].
Create the Preemptive priority network, Finite buffer
78. Change the scenario to non_preemptive. Scenarios Switch To Scenario
non_preemptive.
79. Enter the nonpreemptive node. Double click on the node.
80. Right click on the nonpreemptive_priority_queue and choose Edit attributes
81. Change the subqueues packet capacity to 3.
82. Click OK.
83. Close the node model and save the changes.
84. Right click on the preemptive node and select Choose Individual Statistics.
85. Expand Module Statistics nonpreemptive_priority_queue.subqueue[0]
queue.
86. Check overflows statistic.
87. Right click on the overflows statistics and choose Change Collection Mode.
88. Set Capture mode to All values.
89. Repeat the same procedure on subqueue[1] and subqueue[2].
Master thesis MEE 03:24
Tommy Svensson 164
Alex Popescu
Run the finite buffer simulation
90. Choose Scenarios Manage scenarios from the main menu.
91. Change the value in results column to collect.
92. Change Sim Duration to 1 hour.
93. Click OK and wait for the simulation to finish.
94. Close the simulation dialog
View the finite buffer simulation results
95. Open Analysis Configuration tool. File New Analysis Configuration.
Figure 163
Figure 163 - Open a new Analysis configuration tool window
96. Click Create a graph of a statistic button.
97. Expand File statistics <initials>_priority_queue-non_preemptive
Object Statistics nonpreemptive nonpreemptive_priority_queue.
Figure 64.
Figure 164 - Choose File Statistics in Analysis Configuration tool
Master thesis MEE 03:24
Tommy Svensson 165
Alex Popescu
98. Choose the statistics as in Figure 165.
Figure 165 - Selected statistics for nonpreemptive priority queue
99. Choose Statistics Overlaid and differentiator in the pull down menus at the
bottom.
Figure 166 - Graph layout setting
100. Click Show.
Master thesis MEE 03:24
Tommy Svensson 166
Alex Popescu
The graphs should resemble Figure 167.
Figure 167 - Packet loss rate for nonpreemptive priority queue
Master thesis MEE 03:24
Tommy Svensson 167
Alex Popescu
101. Expand File statistics <initials>_priority_queue-preemptive Object
Statistics preemptive preemptive_priority_queue. Figure 168.
Figure 168 - Choose File Statistics in Analysis Configuration tool
102. Choose the statistics as in Figure 169.
Figure 169 - Selected statistics for preemptive priority queue
103. Choose Statistics Overlaid and differentiator in the pull down menus at the
bottom.
Figure 170 - Graph layout setting
104. Click Show.
Master thesis MEE 03:24
Tommy Svensson 168
Alex Popescu
The graph should resemble Figure 171.
Figure 171 - Packet loss rate for preemptive priority queue
Master thesis MEE 03:24
Tommy Svensson 169
Alex Popescu
Weighted Fair Queuing
Processor Sharing (PS) is a class of queueing mechanism with the purpose of allowing
fair access for each incoming flow and to prevent a bursty flow from consuming all of the
output bandwidth. PS contains a queue for each distinct flow and packets from each flow
are inserted into its respective queue. The system then services each queue one packet at
a time in a roundrobin fashion.
Weighted Fair Queuing (WFQ) is a variation of Processor Sharing (PS) in that it supports
flows with different bandwidth requirements. It does this by assigning each queue with
different weights that corresponds to the proportion of the allocated output bandwidth. In
WFQ, each incoming packet is time stamped with a finish time in addition to being
placed into its corresponding flow queue. Unlike Processor Sharing, selection of which
packet to be serviced is now based on this time stamp on each packet. Further packets are
serviced by examining their finish times. The ones with earlier finish times are
transmitted before the ones with later finish times. It is possible for a later packet to have
a finish time stamp that is smaller than an earlier packet.
Figure 172 - WFQ scheduling
Create the Weighted Fair Queuing infinite buffer network
1. Start OPNET and create a new project. File New and choose Project.
2. Name the project <initials>_WFQ_discipline and the scenario infinite. Click
OK.
3. Click Quit.
4. Open the Object palette.
5. Click the Configure palette button.
6. Clear the palette. Click the Clear button.
7. Choose which node models to include. Click the Node models button.
8. Include ta_wfq_node_model. Figure 173.
Master thesis MEE 03:24
Tommy Svensson 170
Alex Popescu
Figure 173 - Include WFQ node model
9. Click OK.
10. Click Save and use the default filename.
11. Click OK.
12. Click on ta_wfq_node_model in the object palette and drag it into the workspace.
13. Right click on the node and choose Set name.
14. Set the name wfq and click OK.
15. Enter the wfq node. Double click on it.
16. Right click on source_1 and choose Edit Attributes
17. Set ia_time to 1
instruction_range to 1
priority_range to 0
18. Click OK.
19. Right click on source_2 and choose Edit Attributes
20. Set ia_time to 1
instruction_range to 1
priority_range to 1
21. Click OK.
22. Right click on source_3 and choose Edit Attributes
23. Set ia_time to 1
instruction_range to 9600
priority_range to 2
24. Click OK.
25. Right click on wfq_queue and choose Edit Attributes
26. Set processing_rate to 30000
queue_weight0 to 50
queue_weight1 to 30
queue_weight2 to 20
27. Set the rows attribute value to 3
28. Set Row 0 Bit capacity to infinity.
Master thesis MEE 03:24
Tommy Svensson 171
Alex Popescu
Row 0 Pk capacity to infinity.
Row 1 Bit capacity to infinity.
Row 1 Pk capacity to infinity.
Row 2 Bit capacity to infinity.
Row 2 Pk capacity to infinity.
Figure 174 - wfq processor settings
29. Close the node model and save the changes.
Master thesis MEE 03:24
Tommy Svensson 172
Alex Popescu
Figure 175 - wfq statistics settings
30. Right click the wfq node and select
Choose Individual Statistics.
31. Choose the statistics as in Figure 175.
32. Right click subqueue[0] queue
queue size (packets) and choose
Change collection mode.
33. Change Capture mode to all values.
34. Click OK to close capture mode
dialog.
35. Click OK to close Choose Results
dialog.
Master thesis MEE 03:24
Tommy Svensson 173
Alex Popescu
Run the Weighted Fair Queuing infinite buffer simulation
36. Open Configure simulation dialog. Click the Run simulation button.
37. Set duration to 1 day
Seed to any arbitrary integer (i.e. 5416)
38. Click Run and wait for the simulation to finish.
View the Weighted Fair Queuing infinite buffer results.
39. Right click on the workspace and choose View Results.
40. Expand Object statistics wfq wfq_queue.
41. Choose the statistics as in Figure 176.
42. Set Statistics overlaid and time_average in the pull down menus at the bottom.
Figure 176.
Figure 176 - WFQ graph results setting
43. Click Show.
Master thesis MEE 03:24
Tommy Svensson 174
Alex Popescu
The Graph should resemble Figure 177.
Figure 177 WFQ queue length, infinite buffer
Master thesis MEE 03:24
Tommy Svensson 175
Alex Popescu
Create the Weighted Fair Queuing finite buffer network
44. Close the View result dialog.
45. Enter the wfq node. Double click on it.
46. Right click on wfq_queue and choose Edit Attributes
47. Change
subqueue row 0 pk capacity (pks) to 3
subqueue row 1 pk capacity (pks) to 3
subqueue row 2 pk capacity (pks) to 3
(figure 178)
Figure 178 - wfq finite queue settings
48. Click OK.
49. Close the node model and save the changes.
50. Right click the wfq node and select Choose Individual Statistics.
51. Include Module statistics wfq_queue wfq_queue.subqueue[0]
overflows and change the colletion mode to all values.
52. Include Module statistics wfq_queue wfq_queue.subqueue[1]
overflows and change the colletion mode to all values.
53. Include Module statistics wfq_queue wfq_queue.subqueue[2]
overflows and change the colletion mode to all values.
54. Click OK.
Master thesis MEE 03:24
Tommy Svensson 176
Alex Popescu
Run the Weighted Fair Queuing finite buffer simulation
55. Open Configure simulation dialog. Click the Run simulation button.
56. Set duration to 1 day
Seed to any arbitrary integer (i.e. 2569)
57. Click Run and wait for the simulation to finish.
View the Weighted Fair Queuing finite buffer results.
58. Right click on the workspace and choose View Results.
59. Expand Object statistics wfq wfq_queue.
60. Choose the statistics as in Figure 179.
61. Set Statistics overlaid and differentiator in the pull down menus at the bottom.
Figure 179.
Figure 179 - WFQ packet loss graph results setting
62. Click Show.
Master thesis MEE 03:24
Tommy Svensson 177
Alex Popescu
The Graph should resemble Figure 180.
Figure 180 Packet loss for WFQ finite buffer
Master thesis MEE 03:24
Tommy Svensson 178
Alex Popescu
Laboratory 7
Self-Similar
Objective
The purpose of this lab is to understand self-similarity on physical grounds in a realistic
network environment. This understanding is important when developing efficient and
integrated network frameworks within which end-to-end QoS guarantees are fully
supported.
Overview
Self-similar traffic has been shown to exist in networks and it seems to be a ubiquitous
phenomenon that is independent of technology, protocol and environment.
In this laboratory moment we will study and compare the performance of an Ethernet
segment run with heavy-tail traffic and with exponential traffic. The performance
parameters considered here are link utilization and e2e delay. The laboratory moments
are as follows:
Creation of the network model
Running the simulation with different ON-OFF models
Plotting and comparing the results
Master thesis MEE 03:24
Tommy Svensson 179
Alex Popescu
Procedure
A self-similar phenomenon represents a process displaying structural similarities across a
wide range of scales of a specific dimension. In other words, the reference structure is
repeating itself over a wide range of scales and the (main) statistics of the process do not
change. However, these properties do not hold indefinitely for real phenomena and at
some point, this structure breaks down. Self-similarity can therefore be associated with
fractals which are objects with unchanged appearances over different scales.
A stochastic process is called fractal when a number of relevant statistics exhibit scaling
with related scaling exponents. Since scaling leads mathematically to power-law
relationships in the scaled quantities the conclusion is therefore that the traffic shows
fractal properties when several estimated statistics exhibit power-law behaviour over a
wide range of time scales [8].
A continuous-time stochastic process X(t) is considered to be statistical self-similar with
parameter H(0.5 H 1.0) if, for any real positive a, the process a
-H
x(at) has the same
statistical properties as x(t). This relationship may be expressed by the following three
conditions:
E[x(t)] = E[x(at)] / a
H
mean
Var[x(t)] = Var[x(at)] / a
2H
variance
R
x
(t,s) = R
x
(at,as) /a
2H
autocorrelation
The parameter H is known as the Hurst parameter, or the self-similarity meter, and it is a
key measure of self-similarity. More precisely H is a measure of the persistence of a
statistical phenomenon and it is the measure of the length of the long-range dependence
of a stochastic process. A value of H=0.5 indicates the absence of long-range
dependence. The closer H is to 1 the greater the degree of persistence or long-range
dependence.
Master thesis MEE 03:24
Tommy Svensson 180
Alex Popescu
Create the self similar network model
1. Start OPNET and create a new project. File New and choose Project.
2. Name the project <initials>_selfsimilar and the scenario
self_similar_vs_exponential. Click OK.
3. Choose Create Empty Scenario. Click Next.
4. Choose Office. Click Next.
5. Set: Size to Meters
X Span to 100
Y Span to 100
Click Next.
6. Include RPG. Click Next.
Figure 181 - Include technologies dialog
7. Review the chosen values. Click OK.
8. Open the Object palette if its not already open.
9. Place two Ethernet_rpg_station nodes in the workspace. Figure 182.
Figure 182 - ethernet_rpg_station icon
10. Name the first node model PowOn-PowOff source and the second one PowOn-
PowOff receiver. Right click and choose Set Name.
11. Change the Object palette to ethernet_advanced. Figure 183.
Figure 183 - Choused Object palette
Master thesis MEE 03:24
Tommy Svensson 181
Alex Popescu
12. Place two ethernet_stn_advanced nodes in the workspace. Figure 184.
Figure 184 - ethernet_stn_advanced icon
13. Name the first node model Exponential source and the second one
Exponential_receiver. Right click and choose Set Name.
14. Place two ethernet16_hub_adv in the workspace.
Figure 185 - ethernet16_hub_adv icon
15. Name the first hub PowON-PowOFF Hub and the second hub Exponential
Hub. Right click and choose Set Name.
16. Use 10BaseT_int link model to the following connections.
PowOn-PowOff_source PowON-PowOFF Hub
PowON-PowOFF Hub PowOn-PowOff receiver
Exponential source Exponential Hub
Exponential Hub Exponential_receiver
Figure 186 - 10BaseT_int icon
Master thesis MEE 03:24
Tommy Svensson 182
Alex Popescu
The network model should resemble figure 187.
Figure 187 Network model overview
17. Right click on PowOn-PowOff source and choose Edit Attributes...
18. Set the attributes as in Figure 188.
Master thesis MEE 03:24
Tommy Svensson 183
Alex Popescu
Figure 188 - PowOn-PowOff Source node attributes
19. Click OK to close the attributes dialog.
20. Select the PowOn-PowOff network and press <CTRL>+C
21. Paste two copies on the workspace. Press <CTRL>+V to place a copy next to the
original.
22. Rename the nodes.
PowOn-PowOff source_0 to ExpOn-PowOff source
PowOn-PowOff Hub_0 to ExpOn-PowOff Hub
PowOn-PowOff Receiver_1 to ExpOn-PowOff Receiver
PowOn-PowOff source_1 to PowOn-ExpOff source
PowOn-PowOff Hub_1 to PowOn-ExpOff Hub
PowOn-PowOff Receiver_1 to PowOn-ExpOff Receiver
Master thesis MEE 03:24
Tommy Svensson 184
Alex Popescu
23. Right click on ExpOn-PowOff source and choose Edit Attributes...
24. Set the attributes as in Figure 189.
Figure 189 - ExpOn-PowOff source node attributes
25. Click OK to close the dialog.
Master thesis MEE 03:24
Tommy Svensson 185
Alex Popescu
26. Right click on PowOn-ExpOff source and choose Edit Attributes...
27. Set the attributes as in Figure 190.
Figure 190 - PowOn-ExpOff source node attributes
28. Click OK to close the dialog.
Master thesis MEE 03:24
Tommy Svensson 186
Alex Popescu
29. Right click on PowOn-ExpOff source and choose Edit Attributes...
30. Set the attributes as in Figure 191.
Figure 191 - ExpOn-PowOff receiver node attributes
31. Click OK to close the dialog.
32. Right click on PowOn-ExpOff source and choose Edit Attributes...
33. Set the attributes as in Figure 192.
Figure 192 - PowOn-ExpOff receiver node attributes
34. Click OK to close the dialog.
Master thesis MEE 03:24
Tommy Svensson 187
Alex Popescu
35. Right click on PowOn-PowOff source and choose Edit Attributes...
36. Set the attributes as in Figure 193.
Figure 193 - PowOn-PowOff receiver node attributes
37. Click OK to close the dialog.
38. Right click on Exponential source and choose Edit attributes
39. Set the attributes as in Figure 194.
Figure 194 - Exponential source node attributes
40. Click OK to close the dialog.
Master thesis MEE 03:24
Tommy Svensson 188
Alex Popescu
41. Right click on Exponential receiver and choose Edit attributes
42. Set the attributes as in Figure 195.
Figure 195 - Exponential reveiver node attributes
43. Click OK to close the dialog.
The final network should resemble figure 196.
Figure 196 - Network overview
Master thesis MEE 03:24
Tommy Svensson 189
Alex Popescu
44. Right click on the workspace and choose Select Individual Statistics.
45. Expand Node statistics Ethernet.
46. Choose Delay (sec) and Utilization statistics.
Figure 197 - Choused statistics
47. Click OK.
Master thesis MEE 03:24
Tommy Svensson 190
Alex Popescu
Run the simulation
63. Open Configure simulation dialog. Click the Run simulation button.
64. In the Common tab, Set
duration to 100 seconds
Seed to any arbitrary integer (i.e. 5416)
65. In the Global Attributes tab, Set
Eth Hub Optimization to Enabled
RPG Flow Info File to Not Used
RPG Start Time to 0
66. In the Environment Files, Set
Optimize_simulation status to included
67. Click Run and wait for the simulation to finish.
68. Close the simulation dialog.
Master thesis MEE 03:24
Tommy Svensson 191
Alex Popescu
View the results
48. Right click on the workspace and choose View results.
49. Choose the delay statistics as in figure 198.
Figure 198 - Choose delay statistics
Master thesis MEE 03:24
Tommy Svensson 192
Alex Popescu
The results should resemble figure 199.
Figure 199 - Delay results
Master thesis MEE 03:24
Tommy Svensson 193
Alex Popescu
50. Choose the throughput statistics as in figure 200.
Figure 200 Choose throughput statistic
Master thesis MEE 03:24
Tommy Svensson 194
Alex Popescu
The results should resemble figure 201.
Figure 201 - Throughput graph
Master thesis MEE 03:24
Tommy Svensson 195
Alex Popescu
Conclusions throughput
ExpON-PowOff
Fluctuations are much higher at traffic with heavytail than at traffic with exponential
only.
Exponential
Average throughput is more variable at ExpOn-PowOff. It is seen that OFF is heavytail.
PowON-ExpOff and PowON-PowOff
The difference is not so big (regarding average variations) between PowON-ExpOff and
PowON-PowOff.
Conclusions delay
ExpON-PowOff
It is clear that we have PowOff, long periods with very small delays
Exponential
It is clear that it is exponential only, small variations.
PowON-ExpOff and PowON-PowOff
Somehow similar.
Master thesis MEE 03:24
Tommy Svensson 196
Alex Popescu
Concluding Remarks
This thesis consists of five laboratory exercises that cover a range of important topics in
networking and telecommunications. The students are provided an opportunity to
experience the behavior of different networks and protocols but also a chance to learn the
basic procedures of network simulation by using the OPNET Modeler simulation
environment.
This is today the most cost effective solution for universities to demonstrate the behavior
of different networks and protocols.
Acknowledgments
We would like to take this opportunity and thank the Department of
Telecommunications and Signal Processing at the Blekinge Institute of Technology.
We would also especially like to thank Prof: Arne Nilsson and Docent: Adrian Popescu
for giving us the opportunity to work with such interesting and challenging topics.
Finally we would like to give special thanks to the Ph.D. students: Doro Constantinescu,
Dragos Ilie, David Erman and Lennart Isaksson for their help and support.
Master thesis MEE 03:24
Tommy Svensson 197
Alex Popescu
Glossary
ACK - Acknowledge
ATM Asynchronous Transfer Mode
CSMA - Carrier Sensing Multiple Access
CSMA-CD - Carrier Sensing Multiple Access with Collision Detection
cwnd - congestion window
EIGRP Enhanced Interior Gateway Routing Protocol
E-mail Electronic mail
FIFO First in First Out
FSM - Finite State Machines
FTP File Transfer Protocol
IGP Interior Gateway Protocol
IGRP Interior Gateway Routing Protocol
IP Internet Protocol
LAN Local Area Network
M/M/1 Markov/Markov/1 queue
MAC - Medium Access Control
MPLS Multiprotocol Label Switching
OPNET - Optimized Network Engineering Tools
OSPF Open Shortest Path First
RIP Routing Internet Protocol
RTT Round Trip Time
Segsize Segment Size
SMSS - Sender Maximum Segment Size
ssthresh - slow start threshold
TCP Transmission control protocol
WAN Wide Area Network
Master thesis MEE 03:24
Tommy Svensson 198
Alex Popescu
References
[1] URL: http://www.opnet.com/products/modeler/home.html (2003-05-31)
[2] URL: http://www.ietf.org/rfc/rfc2001.txt?number=2001 (2003-05-31)
[3] URL: http://www.ietf.org/rfc/rfc2581.txt?number=2581 (2003-05-31)
[4] Modeling and Simulating Communication Networks
Irene Katzela
Published: Prentice Hall, Inc. 1999
ISBN: 0-13-915737-9
[5] Advanced IP Routing In Cisco Networks
Terry Slattery and Bill Burton
Published: The McGraw-Hill Companies, Inc. 2000
ISBN: 0-07-212591-8
[6] OPNET Online Documentation
IP Model Description
[7] Kteori och tillfrlitlighetsteori
Ulf Krner
Published: Ulf Krner and Studentlitteratur 1992, 1997
ISBN: 91-44-00480-X
[8] Traffic Self-Similarity technical report
Adrian Popescu
BTH 2000
Master thesis MEE 03:24
Tommy Svensson 199
Alex Popescu
Appendix 1
/* Process model C form file: jsd_prio.pr.c */
/* This variable carries the header into the object file */
static const char jsd_prio_pr_c [] = "MIL_3_Tfile_Hdr_ 90A 30A modeler 7
3F55FAD2 3F55FAD2 1 its-2503-5 exjobb 0 0 none none 0 0 none 0 0 0 0 0 0
";
#include <string.h>
/* OPNET system definitions */
#include <opnet.h>
#if defined (__cplusplus)
extern "C" {
#endif
FSM_EXT_DECS
#if defined (__cplusplus)
} /* end of 'extern "C"' */
#endif
/* Header Block */
#include <stdlib.h> /* atoi(), atof() */
typedef struct {
int job_type;
double job_size;
} JsdT_Job_Desc;
#define QUEUE_EMPTY op_q_empty ()
#define ARRIVAL op_intrpt_type () == OPC_INTRPT_STRM
#define SVC_COMPLETION op_intrpt_type () == OPC_INTRPT_SELF
#define GET_INST_SUCCESS 0 /* Success codes for
get_instructions () function */
#define GET_INST_NO_JOB_TYPE -1
#define GET_INST_NO_JOB_TABLE -2
#define GET_INST_NO_ENTRY -3
#include "jsd_win_avg.ex.h"
int jsd_prio_get_instructions ();
void jsd_prio_error ();
/* End of Header Block */
#if !defined (VOSD_NO_FIN)
#undef BIN
Master thesis MEE 03:24
Tommy Svensson 200
Alex Popescu
#undef BOUT
#define BIN FIN_LOCAL_FIELD(last_line_passed) = __LINE__ -
_block_origin;
#define BOUT BIN
#define BINIT FIN_LOCAL_FIELD(last_line_passed) = 0; _block_origin =
__LINE__;
#else
#define BINIT
#endif /* #if !defined (VOSD_NO_FIN) */
/* State variable definitions */
typedef struct
{
/* Internal state tracking for FSM */
FSM_SYS_STATE
/* State Variables */
int server_busy;
int table_exists;
int num_lines;
double processing_rate;
double last_update_time;
double total_busy_time;
double work_left_last;
double total_work;
double total_delay;
double num_pks_serviced;
double win_size;
JsdT_Win_Stat_Hndl* Util_Stat_Hndl;
JsdT_Win_Stat_Hndl* Work_Left_Stat_Hndl;
Objid own_id;
Evhandle svc_complete;
JsdT_Job_Desc* Job_Desc_Table;
Stathandle busy_signal_shandle;
Stathandle inst_delay_shandle;
Stathandle inst_wk_left_shandle;
Stathandle normalized_delay_shandle;
Stathandle mean_util_shandle;
Stathandle avg_thruput_shandle;
Stathandle mean_delay_shandle;
} jsd_prio_state;
#define pr_state_ptr ((jsd_prio_state*)
SimI_Mod_State_Ptr)
#define server_busy pr_state_ptr->server_busy
#define table_exists pr_state_ptr->table_exists
#define num_lines pr_state_ptr->num_lines
#define processing_rate pr_state_ptr->processing_rate
#define last_update_time pr_state_ptr->last_update_time
#define total_busy_time pr_state_ptr->total_busy_time
#define work_left_last pr_state_ptr->work_left_last
#define total_work pr_state_ptr->total_work
#define total_delay pr_state_ptr->total_delay
#define num_pks_serviced pr_state_ptr->num_pks_serviced
#define win_size pr_state_ptr->win_size
#define Util_Stat_Hndl pr_state_ptr->Util_Stat_Hndl
Master thesis MEE 03:24
Tommy Svensson 201
Alex Popescu
#define Work_Left_Stat_Hndl pr_state_ptr-
>Work_Left_Stat_Hndl
#define own_id pr_state_ptr->own_id
#define svc_complete pr_state_ptr->svc_complete
#define Job_Desc_Table pr_state_ptr->Job_Desc_Table
#define busy_signal_shandle pr_state_ptr-
>busy_signal_shandle
#define inst_delay_shandle pr_state_ptr-
>inst_delay_shandle
#define inst_wk_left_shandle pr_state_ptr-
>inst_wk_left_shandle
#define normalized_delay_shandle pr_state_ptr-
>normalized_delay_shandle
#define mean_util_shandle pr_state_ptr-
>mean_util_shandle
#define avg_thruput_shandle pr_state_ptr-
>avg_thruput_shandle
#define mean_delay_shandle pr_state_ptr-
>mean_delay_shandle
/* This macro definition will define a local variable called */
/* "op_sv_ptr" in each function containing a FIN statement. */
/* This variable points to the state variable data structure, */
/* and can be used from a C debugger to display their values. */
#undef FIN_PREAMBLE
#define FIN_PREAMBLE jsd_prio_state *op_sv_ptr = pr_state_ptr;
/* Function Block */
enum { _block_origin = __LINE__ };
int
jsd_prio_get_instructions (pkptr, pk_inst_ptr)
Packet* pkptr;
double* pk_inst_ptr;
{
int job_type, i;
/** This function takes as input a pointer to a packet, and
returns **/
/** a double corresponding to the number of instructions in the
**/
/** packet. If the instructions field in the packet is not set,
the **/
/** function determines the number of instructions by getting the
**/
/** type of the job from the job_type field of the packet, and
**/
/** looking up the number of instructions for that type of job in
**/
/** the Job_Desc_Table, which has been read in from an external
file **/
/** in the init state.
**/
FIN (jsd_prio_get_instructions (pkptr, pk_inst_ptr));
Master thesis MEE 03:24
Tommy Svensson 202
Alex Popescu
/* Get the number of instructions directly */
/* from the named field in the packet. */
if (op_pk_nfd_get (pkptr, "instructions", pk_inst_ptr) ==
OPC_COMPCODE_FAILURE)
jsd_prio_error ("Unable to get instructions field from
packet.");
FRET (GET_INST_SUCCESS);
}
void
jsd_prio_error (msg)
char* msg;
{
/** Print an error message and exit the simulation. **/
FIN (jsd_prio_error (msg));
op_sim_end ("Error in JSD priority process (jsd_prio):",
msg, OPC_NIL, OPC_NIL);
FOUT;
}
/* End of Function Block */
/* Undefine optional tracing in FIN/FOUT/FRET */
/* The FSM has its own tracing code and the other */
/* functions should not have any tracing. */
#undef FIN_TRACING
#define FIN_TRACING
#undef FOUTRET_TRACING
#define FOUTRET_TRACING
#if defined (__cplusplus)
extern "C" {
#endif
void jsd_prio (void);
Compcode jsd_prio_init (void **);
void jsd_prio_diag (void);
void jsd_prio_terminate (void);
void jsd_prio_svar (void *, const char *, char **);
#if defined (__cplusplus)
} /* end of 'extern "C"' */
#endif
/* Process model interrupt handling procedure */
void
jsd_prio (void)
Master thesis MEE 03:24
Tommy Svensson 203
Alex Popescu
{
int _block_origin = 0;
FIN (jsd_prio ());
if (1)
{
Packet* pkptr;
Packet* low_pkptr;
Objid orig_id;
int orig_port;
int insert_ok;
int svc_time_determined;
int success_code;
int i;
int pkid;
int num_pkts;
int position;
int sub_q_no;
double pk_instructions;
double pk_svc_time;
double low_pk_svc_time;
double time_in_processor;
double svc_start;
double original_svc_time;
double processing_delay;
double mean_util;
double avg_throughput;
double mean_proc_delay;
Objid job_type_table_id;
Objid line_id;
char err_str [256];
char* line;
int dval;
int job_type;
double instructions;
double pk_prio;
FSM_ENTER (jsd_prio)
FSM_BLOCK_SWITCH
{
/*----------------------------------------------------
-----*/
/** state (init) enter executives **/
FSM_STATE_ENTER_FORCED_NOLABEL (0, "init", "jsd_prio
[init enter execs]")
FSM_PROFILE_SECTION_IN ("jsd_prio [init enter
execs]", state0_enter_exec)
{
/** These executives are encountered only once,
at the beginning of the simulation. **/
/** Their purpose is to initialize the process
model. The attributes of this particular **/
/** module are determined and state variables
are initialized. If a job_type_filename **/
Master thesis MEE 03:24
Tommy Svensson 204
Alex Popescu
/** was set, the file is read and parsed into a
job description table. **/
/* Initially the server is idle. */
server_busy = 0;
/* Get queue module's own object id. */
own_id = op_id_self ();
/* Get assigned value of server processing rate.
*/
if (op_ima_obj_attr_get (own_id,
"processing_rate", &processing_rate) == OPC_COMPCODE_FAILURE)
jsd_prio_error ("Unable to get processing
rate from attribute.");
/* Get assigned value of the window size for
windowed stats. */
if (op_ima_obj_attr_get (own_id, "win_size",
&win_size) == OPC_COMPCODE_FAILURE)
jsd_prio_error ("Unable to get window size
from attribute.");
/* Initialize some state variables dealing with
statistics. */
last_update_time = op_sim_time ();
total_busy_time = 0.0;
work_left_last = op_sim_time ();
total_work = 0.0;
/* Initialize the structures for the windowed
stats. */
Util_Stat_Hndl = jsd_win_avg_create ("Jsd
Windowed Utilization", win_size, OPC_STAT_LOCAL);
Work_Left_Stat_Hndl = jsd_win_avg_create ("Jsd
Windowed Work Left (sec)", win_size, OPC_STAT_LOCAL);
/* Set the table exists flag. */
table_exists = 1;
/* Register Statistics. */
busy_signal_shandle = op_stat_reg ("Jsd Busy
Signal", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
inst_delay_shandle = op_stat_reg ("Jsd
Instantaneous Delay (sec)", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
inst_wk_left_shandle = op_stat_reg ("Jsd
Instantaneous Work Left (sec)", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
normalized_delay_shandle = op_stat_reg ("Jsd
Normalized Delay", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
mean_util_shandle = op_stat_reg ("Jsd Total Busy
Time", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
avg_thruput_shandle = op_stat_reg ("Jsd Total
Work", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
mean_delay_shandle = op_stat_reg ("Jsd Mean
Delay (sec)", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
}
Master thesis MEE 03:24
Tommy Svensson 205
Alex Popescu
FSM_PROFILE_SECTION_OUT ("jsd_prio [init enter
execs]", state0_enter_exec)
/** state (init) exit executives **/
FSM_STATE_EXIT_FORCED (0, "init", "jsd_prio [init exit
execs]")
FSM_PROFILE_SECTION_IN ("jsd_prio [init exit
execs]", state0_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("jsd_prio [init exit
execs]", state0_exit_exec)
/** state (init) transition processing **/
FSM_TRANSIT_FORCE (1, state1_enter_exec, ;, "default",
"", "init", "idle")
/*----------------------------------------------
-----------*/
/** state (idle) enter executives **/
FSM_STATE_ENTER_UNFORCED (1, state1_enter_exec,
"idle", "jsd_prio [idle enter execs]")
FSM_PROFILE_SECTION_IN ("jsd_prio [idle enter
execs]", state1_enter_exec)
{
}
FSM_PROFILE_SECTION_OUT ("jsd_prio [idle enter
execs]", state1_enter_exec)
/** blocking after enter executives of unforced state.
**/
FSM_EXIT (3,jsd_prio)
/** state (idle) exit executives **/
FSM_STATE_EXIT_UNFORCED (1, "idle", "jsd_prio [idle
exit execs]")
FSM_PROFILE_SECTION_IN ("jsd_prio [idle exit
execs]", state1_exit_exec)
{
/** These executives are encountered whenever
there is a stream interrupt (arrival), or a **/
/** self interrupt (service completion). In
either case, we want to record some statistics. **/
/** If the server is busy at this point, we will
want to record a 1.0 for each statistic from **/
/** the last update time until the current
update time. If the server is free, we will want **/
/** to record a 0.0. Thus we will use the value
of server_busy as the value to record. **/
Master thesis MEE 03:24
Tommy Svensson 206
Alex Popescu
/* Update the busy signal. */
op_stat_write_t (busy_signal_shandle,
server_busy, last_update_time);
/* Update the windowed utilization statistic. */
jsd_win_avg_update (Util_Stat_Hndl, (double)
server_busy);
/* Prevent rounding off errors, if any. */
if (work_left_last < 0)
work_left_last = 0;
/* Update the statistic for the instantaneous
total amount of unfinished work in the queue. */
op_stat_write_t (inst_wk_left_shandle,
work_left_last, last_update_time);
/* Update the statistic for the windowed
unfinished work in the queue. */
jsd_win_avg_update (Work_Left_Stat_Hndl,
work_left_last);
work_left_last -= (server_busy * (op_sim_time ()
- last_update_time));
/* Add to the total_busy_time for use by the
mean_utilization stat. */
total_busy_time += (server_busy * (op_sim_time
() - last_update_time));
/* Update the statistic. */
op_stat_write (mean_util_shandle,
total_busy_time/ op_sim_time ());
/* Set the last_update_time for use by the next
event. */
last_update_time = op_sim_time ();
}
FSM_PROFILE_SECTION_OUT ("jsd_prio [idle exit
execs]", state1_exit_exec)
/** state (idle) transition processing **/
FSM_PROFILE_SECTION_IN ("jsd_prio [idle trans
conditions]", state1_trans_conds)
FSM_INIT_COND (SVC_COMPLETION)
FSM_TEST_COND (ARRIVAL)
FSM_TEST_LOGIC ("idle")
FSM_PROFILE_SECTION_OUT ("jsd_prio [idle trans
conditions]", state1_trans_conds)
FSM_TRANSIT_SWITCH
{
FSM_CASE_TRANSIT (0, 4, state4_enter_exec, ;,
"SVC_COMPLETION", "", "idle", "svc_comp")
Master thesis MEE 03:24
Tommy Svensson 207
Alex Popescu
FSM_CASE_TRANSIT (1, 2, state2_enter_exec, ;,
"ARRIVAL", "", "idle", "arrival")
}
/*----------------------------------------------
-----------*/
/** state (arrival) enter executives **/
FSM_STATE_ENTER_FORCED (2, state2_enter_exec,
"arrival", "jsd_prio [arrival enter execs]")
FSM_PROFILE_SECTION_IN ("jsd_prio [arrival enter
execs]", state2_enter_exec)
{
/** These executives are encountered when a
packet arrives on an input **/
/** stream. The incoming packet is enqueued in
priority order in a subqueue. **/
/** If there is a packet already in service, it
will not be preempted. **/
/* Acquire the arriving packet.
*/
/* Multiple arriving streams are supported.
*/
pkptr = op_pk_get (op_intrpt_strm());
if (pkptr == OPC_NIL)
jsd_prio_error ("Unable to get packet from
input stream.");
/** Determine the remaining service time of the
incoming packet. **/
/* If the svc_time field of the packet is set,
we can */
/* read the remaining service time directly from
it. */
if (op_pk_nfd_is_set (pkptr, "svc_time"))
{
if (op_pk_nfd_get (pkptr, "svc_time",
&pk_svc_time) == OPC_COMPCODE_FAILURE)
jsd_prio_error ("Unable to get
remaining service time from packet.");
/* Set a success flag to be used later. */
svc_time_determined = 1;
}
/* Otherwise we need to determine the number of
instructions */
/* in the packet. */
else
{
/* Determine the number of instructions in
the packet. */
Master thesis MEE 03:24
Tommy Svensson 208
Alex Popescu
success_code = jsd_prio_get_instructions
(pkptr, &pk_instructions);
/* If the number of instructions was
successfully determined, */
/* compute the service time of the packet.
*/
if (success_code == GET_INST_SUCCESS)
{
pk_svc_time = pk_instructions /
processing_rate;
/* Since the svc_time field was not
previously set, */
/* set it now for later statistical
reference. */
if (op_pk_nfd_set (pkptr,
"svc_time", pk_svc_time) == OPC_COMPCODE_FAILURE)
jsd_prio_error ("Unable to set
service time in packet.");
/* Set a success flag to be used
later. */
svc_time_determined = 1;
}
else
{
/* It was not possible to get the
number of instructions from the packet. */
svc_time_determined = 0;
sprintf (err_str, "Error: Unable to
determine mumber of instructions.");
/* Print error messages and
deallocate the packet. */
op_sim_message (err_str, "Dropping
the packet and continuing.");
op_pk_destroy (pkptr);
/* Set flag to ensure that
transition to svc_start does not occur. */
insert_ok = 0;
}
}
/* Check whether the svc_time was determined
successfully. */
if (svc_time_determined == 1)
{
/* Write the remaining service time into
the packet. */
if (op_pk_nfd_set (pkptr,
"svc_time_remain", pk_svc_time) == OPC_COMPCODE_FAILURE)
jsd_prio_error ("Unable to set
remaining service time in packet.");
Master thesis MEE 03:24
Tommy Svensson 209
Alex Popescu
/* Set the svc_start field to the current
time, to keep track of */
/* when the packet first entered the
processor. */
if (op_pk_nfd_set (pkptr, "svc_start",
op_sim_time ()) == OPC_COMPCODE_FAILURE)
jsd_prio_error ("Unable to set
service start time in packet.");
/* Get the packets priority, return
type is double! */
pk_prio=op_pk_priority_get (pkptr);
/* Attempt to enqueue the packet in
priority order in subqueue pk_prio. Typecasting pk_prio to int!! */
if (op_subq_pk_insert ((int)pk_prio,
pkptr, OPC_QPOS_TAIL) != OPC_QINS_OK)
{
/* The insertion failed (due to a
full queue). Determine the */
/* packet with the lowest priority
and remove it from the queue. */
low_pkptr = op_subq_pk_remove
((int)pk_prio, OPC_QPOS_TAIL);
if (low_pkptr == OPC_NIL)
jsd_prio_error ("Unable to get
lowest priority packet from subqueue.");
/* Determine the remaining service
time of the low priority packet. */
if (op_pk_nfd_get (low_pkptr,
"svc_time_remain", &low_pk_svc_time) == OPC_COMPCODE_FAILURE)
jsd_prio_error ("Unable to get
remaining service time from packet.");
/* Subtract this amount of time from
the work left in the queue. */
work_left_last -= low_pk_svc_time;
/* Deallocate the packet with the
lowest priority. */
op_pk_destroy (low_pkptr);
/* Attempt to re-enqueue the new
packet in priority order in subqueue pk_prio. */
if (op_subq_pk_insert ((int)pk_prio,
pkptr, OPC_QPOS_TAIL) != OPC_QINS_OK)
{
/* The insertion failed again.
Deallocate the new packet. */
op_pk_destroy (pkptr);
/* Set flag indicating
insertion fail. This flag is used to */
/* determine transition out of
this state. */
Master thesis MEE 03:24
Tommy Svensson 210
Alex Popescu
insert_ok = 0;
}
else
{
/* Insertion was successful */
insert_ok = 1;
/* Add the service time of the
inserted packet to */
/* the work left in the queue,
for statistical use. */
work_left_last += pk_svc_time;
}
}
else
{
/* Insertion was successful */
insert_ok = 1;
/* Add the service time of the
inserted packet to */
/* the work left in the queue, for
statistical use. */
work_left_last += pk_svc_time;
}
}
}
FSM_PROFILE_SECTION_OUT ("jsd_prio [arrival
enter execs]", state2_enter_exec)
/** state (arrival) exit executives **/
FSM_STATE_EXIT_FORCED (2, "arrival", "jsd_prio
[arrival exit execs]")
FSM_PROFILE_SECTION_IN ("jsd_prio [arrival exit
execs]", state2_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("jsd_prio [arrival exit
execs]", state2_exit_exec)
/** state (arrival) transition processing **/
FSM_PROFILE_SECTION_IN ("jsd_prio [arrival trans
conditions]", state2_trans_conds)
FSM_INIT_COND (!server_busy && insert_ok)
FSM_DFLT_COND
FSM_TEST_LOGIC ("arrival")
FSM_PROFILE_SECTION_OUT ("jsd_prio [arrival trans
conditions]", state2_trans_conds)
FSM_TRANSIT_SWITCH
{
FSM_CASE_TRANSIT (0, 3, state3_enter_exec, ;,
"!server_busy && insert_ok", "", "arrival", "svc_start")
FSM_CASE_TRANSIT (1, 1, state1_enter_exec, ;,
"default", "", "arrival", "idle")
Master thesis MEE 03:24
Tommy Svensson 211
Alex Popescu
}
/*----------------------------------------------
-----------*/
/** state (svc_start) enter executives **/
FSM_STATE_ENTER_FORCED (3, state3_enter_exec,
"svc_start", "jsd_prio [svc_start enter execs]")
FSM_PROFILE_SECTION_IN ("jsd_prio [svc_start
enter execs]", state3_enter_exec)
{
/** When entering these executives, there will
be a packet at the **/
/** head of subqueue 0 that requires service.
This state begins **/
/** service for the packet and schedules an
interrupt for the **/
/** time of completion of service.
**/
sub_q_no=0;
for (i=2; i>=0; i--)
{
if (!op_subq_empty(i))
{
sub_q_no=i;
}
}
/* Get a handle on the packet at the head of
subqueue sub_q_no. */
/* This does not remove the packet.
*/
pkptr = op_subq_pk_access (sub_q_no,
OPC_QPOS_HEAD);
if (pkptr == OPC_NIL)
jsd_prio_error ("Unable to access packet
at head of subqueue.");
/* Extract the remaining service time of the
packet. */
if (op_pk_nfd_get (pkptr, "svc_time_remain",
&pk_svc_time) == OPC_COMPCODE_FAILURE)
jsd_prio_error ("Unable to get remaining
service time from packet.");
/* Schedule an interrupt for this process at the
time where service ends. */
/* The packet id is used as the interrupt code,
so that the packet can be */
/* identified in the queue at the time of its
service completion interrupt. */
svc_complete = op_intrpt_schedule_self
(op_sim_time () + pk_svc_time, op_pk_id (pkptr));
if (op_ev_valid (svc_complete) == OPC_FALSE)
Master thesis MEE 03:24
Tommy Svensson 212
Alex Popescu
jsd_prio_error ("Unable to schedule self
interrupt for service completion.");
/* Make the server busy. */
server_busy = 1;
}
FSM_PROFILE_SECTION_OUT ("jsd_prio [svc_start
enter execs]", state3_enter_exec)
/** state (svc_start) exit executives **/
FSM_STATE_EXIT_FORCED (3, "svc_start", "jsd_prio
[svc_start exit execs]")
FSM_PROFILE_SECTION_IN ("jsd_prio [svc_start
exit execs]", state3_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("jsd_prio [svc_start
exit execs]", state3_exit_exec)
/** state (svc_start) transition processing **/
FSM_TRANSIT_FORCE (1, state1_enter_exec, ;, "default",
"", "svc_start", "idle")
/*----------------------------------------------
-----------*/
/** state (svc_comp) enter executives **/
FSM_STATE_ENTER_FORCED (4, state4_enter_exec,
"svc_comp", "jsd_prio [svc_comp enter execs]")
FSM_PROFILE_SECTION_IN ("jsd_prio [svc_comp
enter execs]", state4_enter_exec)
{
/** These executives are encountered when a
packet completes **/
/** service. They record some statistics,
convert the packet **/
/** into an acknowledgement packet, and send it
back to the **/
/** address specified by the the orig_id and
orig_port fields **/
/** of the packet.
**/
/* Determine the id of the packet just
completing service. */
/* This is passed as the code associated with
the service */
/* completion interrupt.
*/
pkid = op_intrpt_code ();
Master thesis MEE 03:24
Tommy Svensson 213
Alex Popescu
/* Locate the packet and determine which
subqueue it is located in and queue position. */
success_code=0;
sub_q_no=0;
position=0;
for (sub_q_no=0;sub_q_no<3;sub_q_no++)
{
/* Determine the number of packets
currently in the queue. */
dval = op_subq_stat (sub_q_no,
OPC_QSTAT_PKSIZE);
if (dval == OPC_DBL_INVALID)
jsd_prio_error ("Unable to get
number of packets in subqueue.");
num_pkts = (int) dval;
/* Determine if this packet is located in
this subqueue. And if so,the queue position of this packet */
/* and obtain a pointer to it.
*/
for (position = 0; position < num_pkts;
position++)
{
pkptr = op_subq_pk_access (sub_q_no,
position);
if (pkptr != OPC_NIL && op_pk_id
(pkptr) == pkid)
{
success_code=1;
break;
}
}
if (success_code==1)
break;
}
/* Check to make sure that a packet pointer was
in fact obtained. */
if (position == num_pkts)
op_sim_message ("Error: could not find
packet in queue at svc_comp state.", "");
else
{
/* Extract the packet just finishing
service. */
pkptr = op_subq_pk_remove (sub_q_no,
position);
if (pkptr == OPC_NIL)
jsd_prio_error ("Unable to get
packet from subqueue.");
Master thesis MEE 03:24
Tommy Svensson 214
Alex Popescu
/* Determine when this packet first
entered the processor */
/* and how long it has been in the
processor. */
if (op_pk_nfd_get (pkptr, "svc_start",
&svc_start) == OPC_COMPCODE_FAILURE)
jsd_prio_error ("Unable to get
service start time from packet.");
time_in_processor = op_sim_time () -
svc_start;
/* Determine the original service time of
this packet and how */
/* much processing delay it has
experienced in the queue. */
if (op_pk_nfd_get (pkptr, "svc_time",
&original_svc_time) == OPC_COMPCODE_FAILURE)
jsd_prio_error ("Unable to get
original service time from packet.");
processing_delay = time_in_processor -
original_svc_time;
/* Prevent any rounding off errors. */
if (processing_delay < 0)
processing_delay = 0.0;
/* Write the processing delay statistic.
*/
op_stat_write (inst_delay_shandle,
processing_delay);
/* Write the normalized delay statistic.
*/
if (original_svc_time > 0.0)
op_stat_write
(normalized_delay_shandle, time_in_processor / original_svc_time);
/* Add to the counters for the total
processing delay and the */
/* number of packets serviced for use by
the average delay statistic. */
total_delay += processing_delay;
num_pks_serviced++;
/* Write the mean delay statistic.*/
op_stat_write (mean_delay_shandle,
total_delay / num_pks_serviced);
/* Add to the counter of total work
completed by the queue */
/* for use by the average throughput
statistic. */
total_work += original_svc_time;
/* Update the statistic. */
Master thesis MEE 03:24
Tommy Svensson 215
Alex Popescu
op_stat_write (avg_thruput_shandle,
total_work / op_sim_time ());
/* Convert the job packet to a job
completion ack. */
if (op_pk_nfd_set (pkptr, "ack", 1) ==
OPC_COMPCODE_FAILURE)
jsd_prio_error ("Unable to set
acknowledgement flag in packet.");
/* Extract the originator's object id and
port, */
/* and deliver the ack packet to the
originator. */
if (op_pk_nfd_get (pkptr, "orig_id",
&orig_id) == OPC_COMPCODE_FAILURE ||
op_pk_nfd_get (pkptr, "orig_port",
&orig_port) == OPC_COMPCODE_FAILURE)
{
jsd_prio_error ("Unable to get
originator's ID or port from packet.");
}
op_pk_deliver (pkptr, orig_id, orig_port);
/* Make the server idle again. */
server_busy = 0;
}
}
FSM_PROFILE_SECTION_OUT ("jsd_prio [svc_comp
enter execs]", state4_enter_exec)
/** state (svc_comp) exit executives **/
FSM_STATE_EXIT_FORCED (4, "svc_comp", "jsd_prio
[svc_comp exit execs]")
FSM_PROFILE_SECTION_IN ("jsd_prio [svc_comp exit
execs]", state4_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("jsd_prio [svc_comp
exit execs]", state4_exit_exec)
/** state (svc_comp) transition processing **/
FSM_PROFILE_SECTION_IN ("jsd_prio [svc_comp trans
conditions]", state4_trans_conds)
FSM_INIT_COND (!QUEUE_EMPTY)
FSM_DFLT_COND
FSM_TEST_LOGIC ("svc_comp")
FSM_PROFILE_SECTION_OUT ("jsd_prio [svc_comp trans
conditions]", state4_trans_conds)
FSM_TRANSIT_SWITCH
{
Master thesis MEE 03:24
Tommy Svensson 216
Alex Popescu
FSM_CASE_TRANSIT (0, 3, state3_enter_exec, ;,
"!QUEUE_EMPTY", "", "svc_comp", "svc_start")
FSM_CASE_TRANSIT (1, 1, state1_enter_exec, ;,
"default", "", "svc_comp", "idle")
}
/*----------------------------------------------
-----------*/
}
FSM_EXIT (0,jsd_prio)
}
}
#if defined (__cplusplus)
extern "C" {
#endif
extern VosT_Fun_Status Vos_Catmem_Register (const char * , int ,
VosT_Void_Null_Proc, VosT_Address *);
extern VosT_Address Vos_Catmem_Alloc (VosT_Address, size_t);
extern VosT_Fun_Status Vos_Catmem_Dealloc (VosT_Address);
#if defined (__cplusplus)
}
#endif
Compcode
jsd_prio_init (void ** gen_state_pptr)
{
int _block_origin = 0;
static VosT_Address obtype = OPC_NIL;
FIN (jsd_prio_init (gen_state_pptr))
if (obtype == OPC_NIL)
{
/* Initialize memory management */
if (Vos_Catmem_Register ("proc state vars (jsd_prio)",
sizeof (jsd_prio_state), Vos_Vnop, &obtype) ==
VOSC_FAILURE)
{
FRET (OPC_COMPCODE_FAILURE)
}
}
*gen_state_pptr = Vos_Catmem_Alloc (obtype, 1);
if (*gen_state_pptr == OPC_NIL)
{
FRET (OPC_COMPCODE_FAILURE)
}
else
{
/* Initialize FSM handling */
((jsd_prio_state *)(*gen_state_pptr))->current_block = 0;
Master thesis MEE 03:24
Tommy Svensson 217
Alex Popescu
FRET (OPC_COMPCODE_SUCCESS)
}
}
void
jsd_prio_diag (void)
{
/* No Diagnostic Block */
}
void
jsd_prio_terminate (void)
{
int _block_origin = __LINE__;
FIN (jsd_prio_terminate (void))
Vos_Catmem_Dealloc (pr_state_ptr);
FOUT
}
/* Undefine shortcuts to state variables to avoid */
/* syntax error in direct access to fields of */
/* local variable prs_ptr in jsd_prio_svar function. */
#undef server_busy
#undef table_exists
#undef num_lines
#undef processing_rate
#undef last_update_time
#undef total_busy_time
#undef work_left_last
#undef total_work
#undef total_delay
#undef num_pks_serviced
#undef win_size
#undef Util_Stat_Hndl
#undef Work_Left_Stat_Hndl
#undef own_id
#undef svc_complete
#undef Job_Desc_Table
#undef busy_signal_shandle
#undef inst_delay_shandle
#undef inst_wk_left_shandle
#undef normalized_delay_shandle
#undef mean_util_shandle
#undef avg_thruput_shandle
#undef mean_delay_shandle
Master thesis MEE 03:24
Tommy Svensson 218
Alex Popescu
void
jsd_prio_svar (void * gen_ptr, const char * var_name, char ** var_p_ptr)
{
jsd_prio_state *prs_ptr;
FIN (jsd_prio_svar (gen_ptr, var_name, var_p_ptr))
if (var_name == OPC_NIL)
{
*var_p_ptr = (char *)OPC_NIL;
FOUT
}
prs_ptr = (jsd_prio_state *)gen_ptr;
if (strcmp ("server_busy" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->server_busy);
FOUT
}
if (strcmp ("table_exists" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->table_exists);
FOUT
}
if (strcmp ("num_lines" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->num_lines);
FOUT
}
if (strcmp ("processing_rate" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->processing_rate);
FOUT
}
if (strcmp ("last_update_time" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->last_update_time);
FOUT
}
if (strcmp ("total_busy_time" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->total_busy_time);
FOUT
}
if (strcmp ("work_left_last" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->work_left_last);
FOUT
}
if (strcmp ("total_work" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->total_work);
FOUT
}
if (strcmp ("total_delay" , var_name) == 0)
{
Master thesis MEE 03:24
Tommy Svensson 219
Alex Popescu
*var_p_ptr = (char *) (&prs_ptr->total_delay);
FOUT
}
if (strcmp ("num_pks_serviced" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->num_pks_serviced);
FOUT
}
if (strcmp ("win_size" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->win_size);
FOUT
}
if (strcmp ("Util_Stat_Hndl" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->Util_Stat_Hndl);
FOUT
}
if (strcmp ("Work_Left_Stat_Hndl" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->Work_Left_Stat_Hndl);
FOUT
}
if (strcmp ("own_id" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->own_id);
FOUT
}
if (strcmp ("svc_complete" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->svc_complete);
FOUT
}
if (strcmp ("Job_Desc_Table" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->Job_Desc_Table);
FOUT
}
if (strcmp ("busy_signal_shandle" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->busy_signal_shandle);
FOUT
}
if (strcmp ("inst_delay_shandle" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->inst_delay_shandle);
FOUT
}
if (strcmp ("inst_wk_left_shandle" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->inst_wk_left_shandle);
FOUT
}
if (strcmp ("normalized_delay_shandle" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->normalized_delay_shandle);
FOUT
Master thesis MEE 03:24
Tommy Svensson 220
Alex Popescu
}
if (strcmp ("mean_util_shandle" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->mean_util_shandle);
FOUT
}
if (strcmp ("avg_thruput_shandle" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->avg_thruput_shandle);
FOUT
}
if (strcmp ("mean_delay_shandle" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->mean_delay_shandle);
FOUT
}
*var_p_ptr = (char *)OPC_NIL;
FOUT
}
Master thesis MEE 03:24
Tommy Svensson 221
Alex Popescu
Appendix 2
/* Process model C form file: jsd_prmpt_res.pr.c */
/* This variable carries the header into the object file */
static const char jsd_prmpt_res_pr_c [] = "MIL_3_Tfile_Hdr_ 90A 30A
modeler 7 3EF9869E 3EF9869E 1 its-2503-5 exjobb 0 0 none none 0 0 none 0
0 0 0 0 0
";
#include <string.h>
/* OPNET system definitions */
#include <opnet.h>
#if defined (__cplusplus)
extern "C" {
#endif
FSM_EXT_DECS
#if defined (__cplusplus)
} /* end of 'extern "C"' */
#endif
/* Header Block */
#include <stdlib.h> /* atof(), atoi() */
typedef struct {
int job_type;
double job_size;
} JsdT_Job_Desc;
#define QUEUE_EMPTY op_q_empty ()
#define ARRIVAL op_intrpt_type () == OPC_INTRPT_STRM
#define SVC_COMPLETION op_intrpt_type () == OPC_INTRPT_SELF
#define GET_INST_SUCCESS 0 /* Success codes for
get_instructions () function */
#define GET_INST_NO_JOB_TYPE -1
#define GET_INST_NO_JOB_TABLE -2
#define GET_INST_NO_ENTRY -3
#include "jsd_win_avg.ex.h"
static int jsd_prmpt_res_get_instructions (Packet * pkptr, double *
pk_inst_ptr);
static void jsd_prmpt_res_error (const char * msg);
/* End of Header Block */
Master thesis MEE 03:24
Tommy Svensson 222
Alex Popescu
#if !defined (VOSD_NO_FIN)
#undef BIN
#undef BOUT
#define BIN FIN_LOCAL_FIELD(last_line_passed) = __LINE__ -
_block_origin;
#define BOUT BIN
#define BINIT FIN_LOCAL_FIELD(last_line_passed) = 0; _block_origin =
__LINE__;
#else
#define BINIT
#endif /* #if !defined (VOSD_NO_FIN) */
/* State variable definitions */
typedef struct
{
/* Internal state tracking for FSM */
FSM_SYS_STATE
/* State Variables */
int server_busy;
int table_exists;
int num_lines;
double processing_rate;
double current_priority;
double last_update_time;
double total_busy_time;
double work_left_last;
double total_work;
double total_delay;
double num_pks_serviced;
double win_size;
JsdT_Win_Stat_Hndl* Util_Stat_Hndl;
JsdT_Win_Stat_Hndl* Work_Left_Stat_Hndl;
Objid own_id;
Evhandle svc_complete;
JsdT_Job_Desc* Job_Desc_Table;
Objid job_type_table_id;
Stathandle busy_signal_shandle;
Stathandle inst_delay_shandle;
Stathandle inst_wk_left_shandle;
Stathandle normalized_delay_shandle;
Stathandle mean_util_shandle;
Stathandle avg_thruput_shandle;
Stathandle mean_delay_shandle;
int current_subq;
} jsd_prmpt_res_state;
#define pr_state_ptr ((jsd_prmpt_res_state*)
SimI_Mod_State_Ptr)
#define server_busy pr_state_ptr->server_busy
#define table_exists pr_state_ptr->table_exists
#define num_lines pr_state_ptr->num_lines
#define processing_rate pr_state_ptr->processing_rate
Master thesis MEE 03:24
Tommy Svensson 223
Alex Popescu
#define current_priority pr_state_ptr->current_priority
#define last_update_time pr_state_ptr->last_update_time
#define total_busy_time pr_state_ptr->total_busy_time
#define work_left_last pr_state_ptr->work_left_last
#define total_work pr_state_ptr->total_work
#define total_delay pr_state_ptr->total_delay
#define num_pks_serviced pr_state_ptr->num_pks_serviced
#define win_size pr_state_ptr->win_size
#define Util_Stat_Hndl pr_state_ptr->Util_Stat_Hndl
#define Work_Left_Stat_Hndl pr_state_ptr-
>Work_Left_Stat_Hndl
#define own_id pr_state_ptr->own_id
#define svc_complete pr_state_ptr->svc_complete
#define Job_Desc_Table pr_state_ptr->Job_Desc_Table
#define job_type_table_id pr_state_ptr-
>job_type_table_id
#define busy_signal_shandle pr_state_ptr-
>busy_signal_shandle
#define inst_delay_shandle pr_state_ptr-
>inst_delay_shandle
#define inst_wk_left_shandle pr_state_ptr-
>inst_wk_left_shandle
#define normalized_delay_shandle pr_state_ptr-
>normalized_delay_shandle
#define mean_util_shandle pr_state_ptr-
>mean_util_shandle
#define avg_thruput_shandle pr_state_ptr-
>avg_thruput_shandle
#define mean_delay_shandle pr_state_ptr-
>mean_delay_shandle
#define current_subq pr_state_ptr->current_subq
/* This macro definition will define a local variable called */
/* "op_sv_ptr" in each function containing a FIN statement. */
/* This variable points to the state variable data structure, */
/* and can be used from a C debugger to display their values. */
#undef FIN_PREAMBLE
#define FIN_PREAMBLE jsd_prmpt_res_state *op_sv_ptr = pr_state_ptr;
/* Function Block */
enum { _block_origin = __LINE__ };
static int
jsd_prmpt_res_get_instructions (Packet * pkptr, double * pk_inst_ptr)
{
int job_type, i;
/** This function takes as input a pointer to a packet, and
returns **/
/** a double corresponding to the number of instructions in the
**/
/** packet. If the instructions field in the packet is not set,
the **/
/** function determines the number of instructions by getting the
**/
Master thesis MEE 03:24
Tommy Svensson 224
Alex Popescu
/** type of the job from the job_type field of the packet, and
**/
/** looking up the number of instructions for that type of job in
**/
/** the Job_Desc_Table, which has been read in from an external
file **/
/** in the init state.
**/
FIN (jsd_prmpt_res_get_instructions (pkptr, pk_inst_ptr))
/* Get the number of instructions directly */
/* from the named field in the packet. */
if (op_pk_nfd_get (pkptr, "instructions", pk_inst_ptr) ==
OPC_COMPCODE_FAILURE)
jsd_prmpt_res_error ("Unable to get instructions field from
packet.");
FRET (GET_INST_SUCCESS);
}
static void
jsd_prmpt_res_error (const char * msg)
{
/** Print an error message and exit the simulation. **/
FIN (jsd_prmpt_res_error (msg));
op_sim_end ("Error in JSD preempt and resume process
(jsd_prmpt_res):",
msg, OPC_NIL, OPC_NIL);
FOUT;
}
/* End of Function Block */
/* Undefine optional tracing in FIN/FOUT/FRET */
/* The FSM has its own tracing code and the other */
/* functions should not have any tracing. */
#undef FIN_TRACING
#define FIN_TRACING
#undef FOUTRET_TRACING
#define FOUTRET_TRACING
#if defined (__cplusplus)
extern "C" {
#endif
void jsd_prmpt_res (void);
Compcode jsd_prmpt_res_init (void **);
void jsd_prmpt_res_diag (void);
void jsd_prmpt_res_terminate (void);
void jsd_prmpt_res_svar (void *, const char *, char **);
#if defined (__cplusplus)
} /* end of 'extern "C"' */
#endif
Master thesis MEE 03:24
Tommy Svensson 225
Alex Popescu
/* Process model interrupt handling procedure */
void
jsd_prmpt_res (void)
{
int _block_origin = 0;
FIN (jsd_prmpt_res ());
if (1)
{
Packet* pkptr;
Packet* head_pkptr;
Packet* low_pkptr;
Objid orig_id;
int orig_port;
int insert_ok;
int svc_time_determined;
int success_code;
int i;
int sub_q_no;
double pk_instructions;
double pk_svc_time;
double low_pk_svc_time;
double old_svc_time;
double time_processed;
double time_in_processor;
double svc_start;
double original_svc_time;
double processing_delay;
double mean_util;
double avg_throughput;
double mean_proc_delay;
double pk_prio;
char job_type_filename [64];
char err_str [256];
char* line;
int line_id;
int job_type;
double instructions;
FSM_ENTER (jsd_prmpt_res)
FSM_BLOCK_SWITCH
{
/*----------------------------------------------------
-----*/
/** state (init) enter executives **/
FSM_STATE_ENTER_FORCED_NOLABEL (0, "init",
"jsd_prmpt_res [init enter execs]")
FSM_PROFILE_SECTION_IN ("jsd_prmpt_res [init
enter execs]", state0_enter_exec)
{
Master thesis MEE 03:24
Tommy Svensson 226
Alex Popescu
/** These executives are encountered only once,
at the beginning of the simulation. **/
/** Their purpose is to initialize the process
model. The attributes of this particular **/
/** module are determined and state variables
are initialized. If a job_type_filename **/
/** was set, the file is read and parsed into a
job description table. **/
/* Initially the server is idle. */
server_busy = 0;
/* Initially the current priority is 0. */
current_priority = 0.0;
/* Initially the current subqueue is 0. */
current_subq = 0;
/* Get queue module's own object id. */
own_id = op_id_self ();
/* Get assigned value of server processing rate.
*/
if (op_ima_obj_attr_get (own_id,
"processing_rate", &processing_rate) == OPC_COMPCODE_FAILURE)
jsd_prmpt_res_error ("Unable to get
processing rate from attribute.");
/* Get assigned value of the window size for
windowed stats. */
if (op_ima_obj_attr_get (own_id, "win_size",
&win_size) == OPC_COMPCODE_FAILURE)
jsd_prmpt_res_error ("Unable to get window
size from attribute.");
/* Initialize some state variables dealing with
statistics. */
last_update_time = op_sim_time ();
total_busy_time = 0.0;
work_left_last = 0.0;
total_work = 0.0;
/* Initialize the structures for the windowed
stats. */
Util_Stat_Hndl = jsd_win_avg_create
("Jsd.Windowed Utilization", win_size, OPC_STAT_LOCAL);
Work_Left_Stat_Hndl = jsd_win_avg_create
("Jsd.Windowed Work Left (sec)", win_size, OPC_STAT_LOCAL);
/* Register Statistics. */
busy_signal_shandle = op_stat_reg
("Jsd.Busy Signal", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
inst_delay_shandle = op_stat_reg
("Jsd.Instantaneous Delay (sec)", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
Master thesis MEE 03:24
Tommy Svensson 227
Alex Popescu
inst_wk_left_shandle = op_stat_reg
("Jsd.Instantaneous Work Left (sec)", OPC_STAT_INDEX_NONE,
OPC_STAT_LOCAL);
normalized_delay_shandle = op_stat_reg
("Jsd.Normalized Delay", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
mean_util_shandle = op_stat_reg
("Jsd.Total Busy Time", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
avg_thruput_shandle = op_stat_reg
("Jsd.Total Work", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
mean_delay_shandle = op_stat_reg
("Jsd.Mean Delay (sec)", OPC_STAT_INDEX_NONE, OPC_STAT_LOCAL);
}
FSM_PROFILE_SECTION_OUT ("jsd_prmpt_res [init
enter execs]", state0_enter_exec)
/** state (init) exit executives **/
FSM_STATE_EXIT_FORCED (0, "init", "jsd_prmpt_res [init
exit execs]")
FSM_PROFILE_SECTION_IN ("jsd_prmpt_res [init
exit execs]", state0_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("jsd_prmpt_res [init
exit execs]", state0_exit_exec)
/** state (init) transition processing **/
FSM_TRANSIT_FORCE (1, state1_enter_exec, ;, "default",
"", "init", "idle")
/*----------------------------------------------
-----------*/
/** state (idle) enter executives **/
FSM_STATE_ENTER_UNFORCED (1, state1_enter_exec,
"idle", "jsd_prmpt_res [idle enter execs]")
FSM_PROFILE_SECTION_IN ("jsd_prmpt_res [idle
enter execs]", state1_enter_exec)
{
}
FSM_PROFILE_SECTION_OUT ("jsd_prmpt_res [idle
enter execs]", state1_enter_exec)
/** blocking after enter executives of unforced state.
**/
FSM_EXIT (3,jsd_prmpt_res)
/** state (idle) exit executives **/
FSM_STATE_EXIT_UNFORCED (1, "idle", "jsd_prmpt_res
[idle exit execs]")
FSM_PROFILE_SECTION_IN ("jsd_prmpt_res [idle
exit execs]", state1_exit_exec)
{
Master thesis MEE 03:24
Tommy Svensson 228
Alex Popescu
/** These executives are encountered whenever
there is a stream interrupt (arrival), or a **/
/** self interrupt (service completion). In
either case, we want to record some statistics. **/
/** If the server is busy at this point, we will
want to record a 1.0 for each statistic from **/
/** the last update time until the current
update time. If the server is free, we will want **/
/** to record a 0.0. Thus we will use the value
of server_busy as the value to record. **/
/* Update the busy signal. */
op_stat_write_t (busy_signal_shandle,
server_busy, last_update_time);
/* Update the windowed utilization statistic. */
jsd_win_avg_update (Util_Stat_Hndl, (double)
server_busy);
/* Update the statistic for the instantaneous
total amount of unfinished work in the queue. */
op_stat_write_t (inst_wk_left_shandle,
work_left_last, last_update_time);
/* Update the statistic for the windowed
unfinished work in the queue. */
jsd_win_avg_update (Work_Left_Stat_Hndl,
work_left_last);
work_left_last -= (server_busy * (op_sim_time ()
- last_update_time));
/* Prevent rounding off errors. */
if (work_left_last < 0.0)
work_left_last = 0.0;
/* Add to the total_busy_time for use by the
mean_utilization stat. */
total_busy_time += (server_busy * (op_sim_time
() - last_update_time));
/* Update the statistic. */
op_stat_write (mean_util_shandle,
total_busy_time/ op_sim_time ());
/* Set the last_update_time for use by the next
event. */
last_update_time = op_sim_time ();
}
FSM_PROFILE_SECTION_OUT ("jsd_prmpt_res [idle
exit execs]", state1_exit_exec)
/** state (idle) transition processing **/
FSM_PROFILE_SECTION_IN ("jsd_prmpt_res [idle trans
conditions]", state1_trans_conds)
Master thesis MEE 03:24
Tommy Svensson 229
Alex Popescu
FSM_INIT_COND (SVC_COMPLETION)
FSM_TEST_COND (ARRIVAL)
FSM_TEST_LOGIC ("idle")
FSM_PROFILE_SECTION_OUT ("jsd_prmpt_res [idle trans
conditions]", state1_trans_conds)
FSM_TRANSIT_SWITCH
{
FSM_CASE_TRANSIT (0, 4, state4_enter_exec, ;,
"SVC_COMPLETION", "", "idle", "svc_comp")
FSM_CASE_TRANSIT (1, 2, state2_enter_exec, ;,
"ARRIVAL", "", "idle", "arrival")
}
/*----------------------------------------------
-----------*/
/** state (arrival) enter executives **/
FSM_STATE_ENTER_FORCED (2, state2_enter_exec,
"arrival", "jsd_prmpt_res [arrival enter execs]")
FSM_PROFILE_SECTION_IN ("jsd_prmpt_res [arrival
enter execs]", state2_enter_exec)
{
/** These executives are encountered when a
packet arrives on an input stream. **/
/** The incoming packet is enqueued in priority
order in subqueue 0. If the **/
/** priority of the incoming packet is higher
than that of a packet being served, **/
/** the packet being served is preempted by the
incoming packet. **/
/* Acquire the arriving packet.
*/
/* Multiple arriving streams are supported.
*/
pkptr = op_pk_get (op_intrpt_strm());
if (pkptr == OPC_NIL)
jsd_prmpt_res_error ("Unable to get packet
from input stream.");
/** Determine the remaining service time of the
incoming packet. **/
/* If the svc_time field of the packet is set,
we can */
/* read the remaining service time directly from
it. */
if (op_pk_nfd_is_set (pkptr, "svc_time"))
{
if (op_pk_nfd_get (pkptr, "svc_time",
&pk_svc_time) == OPC_COMPCODE_FAILURE)
jsd_prmpt_res_error ("Unable to get
remaining service time from packet.");
/* Set a success flag to be used later. */
Master thesis MEE 03:24
Tommy Svensson 230
Alex Popescu
svc_time_determined = 1;
}
/* Otherwise we need to determine the number of
instructions */
/* in the packet. */
else
{
/* Determine the number of instructions in
the packet. */
success_code =
jsd_prmpt_res_get_instructions (pkptr, &pk_instructions);
/* If the number of instructions was
successfully determined, */
/* compute the service time of the packet.
*/
if (success_code == GET_INST_SUCCESS)
{
pk_svc_time = pk_instructions /
processing_rate;
/* Since the svc_time field was not
previously set, */
/* set it now for later statistical
reference. */
if (op_pk_nfd_set (pkptr,
"svc_time", pk_svc_time) == OPC_COMPCODE_FAILURE)
jsd_prmpt_res_error ("Unable
to get service time from packet.");
/* Set a success flag to be used
later. */
svc_time_determined = 1;
}
else
{
/* It was not possible to get the
number of instructions from the packet. */
svc_time_determined = 0;
sprintf (err_str, "Error: the
job_type field was not set.");
/* Print error messages and
deallocate the packet. */
op_sim_message (err_str, "Dropping
the packet and continuing.");
op_pk_destroy (pkptr);
/* Set flag to ensure that
transition to svc_start does not occur. */
insert_ok = 0;
}
}
Master thesis MEE 03:24
Tommy Svensson 231
Alex Popescu
/* Check whether the svc_time was determined
successfully. */
if (svc_time_determined == 1)
{
/* Write the remaining service time into
the packet. */
if (op_pk_nfd_set (pkptr,
"svc_time_remain", pk_svc_time) == OPC_COMPCODE_FAILURE)
jsd_prmpt_res_error ("Unable to set
remaining service time in packet.");
/* Set the svc_start field to the current
time, to keep track of */
/* when the packet first entered the
processor. */
if (op_pk_nfd_set (pkptr, "svc_start",
op_sim_time ()) == OPC_COMPCODE_FAILURE)
jsd_prmpt_res_error ("Unable to set
service start time in packet.");
/* Check if the server is busy. If not,
the packet will be enqueued. */
if (server_busy)
{
/* If the server is busy, preemption
may be necessary. */
/* Check if the priority of the
incoming packet is higher than */
/* the priority of the packet
currently being served. */
if (op_pk_priority_get (pkptr) >
current_priority)
{
/* If so, preemption of the
packet in service is necessary. */
/* Get a pointer to the packet
currently in service. */
head_pkptr = op_subq_pk_access
(current_subq , OPC_QPOS_HEAD);
if (head_pkptr == OPC_NIL)
jsd_prmpt_res_error
("Unable to get packet from head of subqueue.");
/* Determine how much
processing time the packet required */
/* before it entered the
server. */
if (op_pk_nfd_get (head_pkptr,
"svc_time_remain", &old_svc_time) == OPC_COMPCODE_FAILURE)
jsd_prmpt_res_error
("Unable to get remaining service time from packet.");
/* Determine how much time has
been spent processing this packet so far. */
time_processed = op_sim_time
() - op_pk_stamp_time_get (head_pkptr);
Master thesis MEE 03:24
Tommy Svensson 232
Alex Popescu
/* Change the service time
remaining in the packet being removed from the server. */
if (op_pk_nfd_set (head_pkptr,
"svc_time_remain", old_svc_time - time_processed) ==
OPC_COMPCODE_FAILURE)
{
jsd_prmpt_res_error
("Unable to set remaining service time in packet.");
}
/* Cancel the interrupt which
indicates the end of this job. */
if (op_intrpt_cancel
(svc_complete) == OPC_COMPCODE_FAILURE)
jsd_prmpt_res_error
("Unable to cancel job completion interrupt.");
/* Make the server not busy.
*/
server_busy = 0;
}
}
/* Get the packets priority, return
type is double! */
pk_prio=op_pk_priority_get (pkptr);
/* Attempt to enqueue the packet in
priority order in subqueue pk_prio. */
/* This code will be executed whether or
not preemption was necessary. */
if (op_subq_pk_insert ((int)pk_prio,
pkptr, OPC_QPOS_TAIL) != OPC_QINS_OK)
{
/* The insertion failed (due to a
full queue). Determine the */
/* packet with the lowest priority
and remove it from the queue. */
low_pkptr = op_subq_pk_remove
((int)pk_prio, OPC_QPOS_TAIL);
if (low_pkptr == OPC_NIL)
jsd_prmpt_res_error ("Unable
to get lowest priority packet from subqueue.");
/* Determine the remaining service
time of the low priority packet. */
if (op_pk_nfd_get (low_pkptr,
"svc_time_remain", &low_pk_svc_time) == OPC_COMPCODE_FAILURE)
jsd_prmpt_res_error ("Unable
to get remaining service time from packet.");
/* Subtract this amount of time from
the work left in the queue. */
work_left_last -= low_pk_svc_time;
Master thesis MEE 03:24
Tommy Svensson 233
Alex Popescu
/* Deallocate the packet with the
lowest priority. */
op_pk_destroy (low_pkptr);
/* Attempt to re-enqueue the new
packet in priority order in subqueue 0. */
if (op_subq_pk_insert ((int)pk_prio,
pkptr, OPC_QPOS_PRIO) != OPC_QINS_OK)
{
/* The insertion failed again.
Deallocate the new packet. */
op_pk_destroy (pkptr);
/* Set flag indicating
insertion fail. This flag is used to */
/* determine transition out of
this state. */
insert_ok = 0;
}
else
{
/* Insertion was successful */
insert_ok = 1;
/* Add the service time of the
inserted packet to */
/* the work left in the queue,
for statistical use. */
work_left_last += pk_svc_time;
}
}
else
{
/* Insertion was successful */
insert_ok = 1;
/* Add the service time of the
inserted packet to */
/* the work left in the queue, for
statistical use. */
work_left_last += pk_svc_time;
}
}
}
FSM_PROFILE_SECTION_OUT ("jsd_prmpt_res [arrival
enter execs]", state2_enter_exec)
/** state (arrival) exit executives **/
FSM_STATE_EXIT_FORCED (2, "arrival", "jsd_prmpt_res
[arrival exit execs]")
FSM_PROFILE_SECTION_IN ("jsd_prmpt_res [arrival
exit execs]", state2_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("jsd_prmpt_res [arrival
exit execs]", state2_exit_exec)
Master thesis MEE 03:24
Tommy Svensson 234
Alex Popescu
/** state (arrival) transition processing **/
FSM_PROFILE_SECTION_IN ("jsd_prmpt_res [arrival trans
conditions]", state2_trans_conds)
FSM_INIT_COND (!server_busy && insert_ok)
FSM_DFLT_COND
FSM_TEST_LOGIC ("arrival")
FSM_PROFILE_SECTION_OUT ("jsd_prmpt_res [arrival trans
conditions]", state2_trans_conds)
FSM_TRANSIT_SWITCH
{
FSM_CASE_TRANSIT (0, 3, state3_enter_exec, ;,
"!server_busy && insert_ok", "", "arrival", "svc_start")
FSM_CASE_TRANSIT (1, 1, state1_enter_exec, ;,
"default", "", "arrival", "idle")
}
/*----------------------------------------------
-----------*/
/** state (svc_start) enter executives **/
FSM_STATE_ENTER_FORCED (3, state3_enter_exec,
"svc_start", "jsd_prmpt_res [svc_start enter execs]")
FSM_PROFILE_SECTION_IN ("jsd_prmpt_res
[svc_start enter execs]", state3_enter_exec)
{
/** When entering these executives, there will
be a packet at the **/
/** head of subqueue 0 that requires service.
This state begins **/
/** service for the packet and schedules an
interrupt for the **/
/** time of completion of service.
**/
sub_q_no=0;
for (i=2; i>=0; i--)
{
if (!op_subq_empty(i))
{
sub_q_no=i;
}
}
/* Get a handle on the packet at the head of
subqueue 0. */
/* This does not remove the packet.
*/
pkptr = op_subq_pk_access (sub_q_no,
OPC_QPOS_HEAD);
if (pkptr == OPC_NIL)
jsd_prmpt_res_error ("Unable to access
packet at head of subqueue.");
Master thesis MEE 03:24
Tommy Svensson 235
Alex Popescu
/* Set the current priority to the priority of
the packet beginning service. */
current_priority = op_pk_priority_get (pkptr);
/* Set the current subqueue to the subqueue of
the packet beginning service. */
current_subq = sub_q_no;
/* Extract the remaining service time of the
packet. */
if (op_pk_nfd_get (pkptr, "svc_time_remain",
&pk_svc_time) == OPC_COMPCODE_FAILURE)
jsd_prmpt_res_error ("Unable to get
remaining service time from packet.");
/* Schedule an interrupt for this process at the
time where service ends. */
svc_complete = op_intrpt_schedule_self
(op_sim_time () + pk_svc_time, 0);
if (op_ev_valid (svc_complete) == OPC_FALSE)
jsd_prmpt_res_error ("Unable to schedule
self interrupt for service completion.");
/* Stamp packet so that we know when processing
started. */
op_pk_stamp (pkptr);
/* Make the server busy. */
server_busy = 1;
}
FSM_PROFILE_SECTION_OUT ("jsd_prmpt_res
[svc_start enter execs]", state3_enter_exec)
/** state (svc_start) exit executives **/
FSM_STATE_EXIT_FORCED (3, "svc_start", "jsd_prmpt_res
[svc_start exit execs]")
FSM_PROFILE_SECTION_IN ("jsd_prmpt_res
[svc_start exit execs]", state3_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("jsd_prmpt_res
[svc_start exit execs]", state3_exit_exec)
/** state (svc_start) transition processing **/
FSM_TRANSIT_FORCE (1, state1_enter_exec, ;, "default",
"", "svc_start", "idle")
/*----------------------------------------------
-----------*/
/** state (svc_comp) enter executives **/
FSM_STATE_ENTER_FORCED (4, state4_enter_exec,
"svc_comp", "jsd_prmpt_res [svc_comp enter execs]")
Master thesis MEE 03:24
Tommy Svensson 236
Alex Popescu
FSM_PROFILE_SECTION_IN ("jsd_prmpt_res [svc_comp
enter execs]", state4_enter_exec)
{
/** These executives are encountered when a
packet completes **/
/** service. They record some statistics,
convert the packet **/
/** into an acknowledgement packet, and send it
back to the **/
/** address specified by the the orig_id and
orig_port fields **/
/** of the packet.
**/
/* Extract the packet at the head of the queue.
*/
/* This is the packet just finishing service.
*/
pkptr = op_subq_pk_remove (current_subq,
OPC_QPOS_HEAD);
if (pkptr == OPC_NIL)
jsd_prmpt_res_error ("Unable to get packet
from head of subqueue.");
/* Determine when this packet first entered the
processor */
/* and how long it has been in the processor.
*/
if (op_pk_nfd_get (pkptr, "svc_start",
&svc_start) == OPC_COMPCODE_FAILURE)
jsd_prmpt_res_error ("Unable to get
service start time from packet.");
time_in_processor = op_sim_time () - svc_start;
/* Determine the original service time of this
packet and how */
/* much processing delay it has experienced in
the queue. */
if (op_pk_nfd_get (pkptr, "svc_time",
&original_svc_time) == OPC_COMPCODE_FAILURE)
jsd_prmpt_res_error ("Unable to get
original service time from packet.");
processing_delay = time_in_processor -
original_svc_time;
/* Prevent rounding off error. */
if (processing_delay < 0.0)
processing_delay = 0.0;
/* Write the processing delay statistic. */
op_stat_write (inst_delay_shandle,
processing_delay);
/* Write the normalized delay statistic. */
op_stat_write (normalized_delay_shandle,
(time_in_processor / original_svc_time));
Master thesis MEE 03:24
Tommy Svensson 237
Alex Popescu
/* Add to the counters for the total processing
delay and the */
/* number of packets serviced for use by the
average delay statistic. */
total_delay += processing_delay;
num_pks_serviced++;
/* Update the statistic.*/
op_stat_write (mean_delay_shandle, total_delay /
num_pks_serviced);
/* Add to the counter of total work completed by
the queue */
/* for use by the average throughput statistic.
*/
total_work += original_svc_time;
/* Update the statistic. */
op_stat_write (avg_thruput_shandle, total_work /
op_sim_time ());
/* Convert the job packet to a job completion
ack. */
if (op_pk_nfd_set (pkptr, "ack", 1) ==
OPC_COMPCODE_FAILURE)
jsd_prmpt_res_error ("Unable to set
acknowledgement flag in packet.");
/* Extract the originator's object id and port,
*/
/* and deliver the ack packet to the originator.
*/
if (op_pk_nfd_get (pkptr, "orig_id", &orig_id)
== OPC_COMPCODE_FAILURE ||
op_pk_nfd_get (pkptr, "orig_port",
&orig_port) == OPC_COMPCODE_FAILURE)
{
jsd_prmpt_res_error ("Unable to get
originator's object ID or port from packet.");
}
op_pk_deliver (pkptr, orig_id, orig_port);
/* Set the current priority to 0, since nothing
*/
/* is being serviced at this moment.
*/
current_priority = 0.0;
/* Make the server idle again. */
server_busy = 0;
}
FSM_PROFILE_SECTION_OUT ("jsd_prmpt_res
[svc_comp enter execs]", state4_enter_exec)
Master thesis MEE 03:24
Tommy Svensson 238
Alex Popescu
/** state (svc_comp) exit executives **/
FSM_STATE_EXIT_FORCED (4, "svc_comp", "jsd_prmpt_res
[svc_comp exit execs]")
FSM_PROFILE_SECTION_IN ("jsd_prmpt_res [svc_comp
exit execs]", state4_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("jsd_prmpt_res
[svc_comp exit execs]", state4_exit_exec)
/** state (svc_comp) transition processing **/
FSM_PROFILE_SECTION_IN ("jsd_prmpt_res [svc_comp trans
conditions]", state4_trans_conds)
FSM_INIT_COND (!QUEUE_EMPTY)
FSM_DFLT_COND
FSM_TEST_LOGIC ("svc_comp")
FSM_PROFILE_SECTION_OUT ("jsd_prmpt_res [svc_comp
trans conditions]", state4_trans_conds)
FSM_TRANSIT_SWITCH
{
FSM_CASE_TRANSIT (0, 3, state3_enter_exec, ;,
"!QUEUE_EMPTY", "", "svc_comp", "svc_start")
FSM_CASE_TRANSIT (1, 1, state1_enter_exec, ;,
"default", "", "svc_comp", "idle")
}
/*----------------------------------------------
-----------*/
}
FSM_EXIT (0,jsd_prmpt_res)
}
}
#if defined (__cplusplus)
extern "C" {
#endif
extern VosT_Fun_Status Vos_Catmem_Register (const char * , int ,
VosT_Void_Null_Proc, VosT_Address *);
extern VosT_Address Vos_Catmem_Alloc (VosT_Address, size_t);
extern VosT_Fun_Status Vos_Catmem_Dealloc (VosT_Address);
#if defined (__cplusplus)
}
#endif
Compcode
jsd_prmpt_res_init (void ** gen_state_pptr)
{
int _block_origin = 0;
static VosT_Address obtype = OPC_NIL;
Master thesis MEE 03:24
Tommy Svensson 239
Alex Popescu
FIN (jsd_prmpt_res_init (gen_state_pptr))
if (obtype == OPC_NIL)
{
/* Initialize memory management */
if (Vos_Catmem_Register ("proc state vars (jsd_prmpt_res)",
sizeof (jsd_prmpt_res_state), Vos_Vnop, &obtype) ==
VOSC_FAILURE)
{
FRET (OPC_COMPCODE_FAILURE)
}
}
*gen_state_pptr = Vos_Catmem_Alloc (obtype, 1);
if (*gen_state_pptr == OPC_NIL)
{
FRET (OPC_COMPCODE_FAILURE)
}
else
{
/* Initialize FSM handling */
((jsd_prmpt_res_state *)(*gen_state_pptr))->current_block =
0;
FRET (OPC_COMPCODE_SUCCESS)
}
}
void
jsd_prmpt_res_diag (void)
{
/* No Diagnostic Block */
}
void
jsd_prmpt_res_terminate (void)
{
int _block_origin = __LINE__;
FIN (jsd_prmpt_res_terminate (void))
Vos_Catmem_Dealloc (pr_state_ptr);
FOUT
}
/* Undefine shortcuts to state variables to avoid */
/* syntax error in direct access to fields of */
/* local variable prs_ptr in jsd_prmpt_res_svar function. */
Master thesis MEE 03:24
Tommy Svensson 240
Alex Popescu
#undef server_busy
#undef table_exists
#undef num_lines
#undef processing_rate
#undef current_priority
#undef last_update_time
#undef total_busy_time
#undef work_left_last
#undef total_work
#undef total_delay
#undef num_pks_serviced
#undef win_size
#undef Util_Stat_Hndl
#undef Work_Left_Stat_Hndl
#undef own_id
#undef svc_complete
#undef Job_Desc_Table
#undef job_type_table_id
#undef busy_signal_shandle
#undef inst_delay_shandle
#undef inst_wk_left_shandle
#undef normalized_delay_shandle
#undef mean_util_shandle
#undef avg_thruput_shandle
#undef mean_delay_shandle
#undef current_subq
void
jsd_prmpt_res_svar (void * gen_ptr, const char * var_name, char **
var_p_ptr)
{
jsd_prmpt_res_state *prs_ptr;
FIN (jsd_prmpt_res_svar (gen_ptr, var_name, var_p_ptr))
if (var_name == OPC_NIL)
{
*var_p_ptr = (char *)OPC_NIL;
FOUT
}
prs_ptr = (jsd_prmpt_res_state *)gen_ptr;
if (strcmp ("server_busy" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->server_busy);
FOUT
}
if (strcmp ("table_exists" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->table_exists);
FOUT
}
if (strcmp ("num_lines" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->num_lines);
Master thesis MEE 03:24
Tommy Svensson 241
Alex Popescu
FOUT
}
if (strcmp ("processing_rate" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->processing_rate);
FOUT
}
if (strcmp ("current_priority" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->current_priority);
FOUT
}
if (strcmp ("last_update_time" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->last_update_time);
FOUT
}
if (strcmp ("total_busy_time" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->total_busy_time);
FOUT
}
if (strcmp ("work_left_last" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->work_left_last);
FOUT
}
if (strcmp ("total_work" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->total_work);
FOUT
}
if (strcmp ("total_delay" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->total_delay);
FOUT
}
if (strcmp ("num_pks_serviced" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->num_pks_serviced);
FOUT
}
if (strcmp ("win_size" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->win_size);
FOUT
}
if (strcmp ("Util_Stat_Hndl" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->Util_Stat_Hndl);
FOUT
}
if (strcmp ("Work_Left_Stat_Hndl" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->Work_Left_Stat_Hndl);
FOUT
}
Master thesis MEE 03:24
Tommy Svensson 242
Alex Popescu
if (strcmp ("own_id" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->own_id);
FOUT
}
if (strcmp ("svc_complete" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->svc_complete);
FOUT
}
if (strcmp ("Job_Desc_Table" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->Job_Desc_Table);
FOUT
}
if (strcmp ("job_type_table_id" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->job_type_table_id);
FOUT
}
if (strcmp ("busy_signal_shandle" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->busy_signal_shandle);
FOUT
}
if (strcmp ("inst_delay_shandle" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->inst_delay_shandle);
FOUT
}
if (strcmp ("inst_wk_left_shandle" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->inst_wk_left_shandle);
FOUT
}
if (strcmp ("normalized_delay_shandle" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->normalized_delay_shandle);
FOUT
}
if (strcmp ("mean_util_shandle" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->mean_util_shandle);
FOUT
}
if (strcmp ("avg_thruput_shandle" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->avg_thruput_shandle);
FOUT
}
if (strcmp ("mean_delay_shandle" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->mean_delay_shandle);
FOUT
}
if (strcmp ("current_subq" , var_name) == 0)
{
Master thesis MEE 03:24
Tommy Svensson 243
Alex Popescu
*var_p_ptr = (char *) (&prs_ptr->current_subq);
FOUT
}
*var_p_ptr = (char *)OPC_NIL;
FOUT
}
Master thesis MEE 03:24
Tommy Svensson 244
Alex Popescu
Appendix 3
/* Process model C form file: ta_gen.pr.c */
/* This variable carries the header into the object file */
static const char ta_gen_pr_c [] = "MIL_3_Tfile_Hdr_ 90A 30A modeler 7
3EF84C02 3EF84C02 1 its-2503-5 exjobb 0 0 none none 0 0 none 0 0 0 0 0 0
";
#include <string.h>
/* OPNET system definitions */
#include <opnet.h>
#if defined (__cplusplus)
extern "C" {
#endif
FSM_EXT_DECS
#if defined (__cplusplus)
} /* end of 'extern "C"' */
#endif
/* Header Block */
#define JSDC_SVC_TIME 1 /* Symbolic constants to determine
*/
#define JSDC_INSTRUCTIONS 2 /* which type of packets this */
#define JSDC_RCV_IN_STRM 0 /* Packet stream definitions */
#define JSDC_XMT_OUT_STRM 0
#define JSDC_CREATE_INTRPT 0 /* The intrpt code for packet
creation */
/* Transition macros */
#define CREATE (op_intrpt_type () == OPC_INTRPT_SELF && \
op_intrpt_code () == JSDC_CREATE_INTRPT)
#define ARRIVAL (op_intrpt_type () == OPC_INTRPT_STRM && \
op_intrpt_strm () == JSDC_RCV_IN_STRM)
void jsd_gen_request_creation ();
void jsd_gen_error ();
/* End of Header Block */
#if !defined (VOSD_NO_FIN)
#undef BIN
#undef BOUT
Master thesis MEE 03:24
Tommy Svensson 245
Alex Popescu
#define BIN FIN_LOCAL_FIELD(last_line_passed) = __LINE__ -
_block_origin;
#define BOUT BIN
#define BINIT FIN_LOCAL_FIELD(last_line_passed) = 0; _block_origin =
__LINE__;
#else
#define BINIT
#endif /* #if !defined (VOSD_NO_FIN) */
/* State variable definitions */
typedef struct
{
/* Internal state tracking for FSM */
FSM_SYS_STATE
/* State Variables */
Objid own_id;
int active;
double instruction_range;
double priority_range;
Distribution * next_dist;
double ia_time;
} ta_gen_state;
#define pr_state_ptr ((ta_gen_state*)
SimI_Mod_State_Ptr)
#define own_id pr_state_ptr->own_id
#define active pr_state_ptr->active
#define instruction_range pr_state_ptr-
>instruction_range
#define priority_range pr_state_ptr->priority_range
#define next_dist pr_state_ptr->next_dist
#define ia_time pr_state_ptr->ia_time
/* This macro definition will define a local variable called */
/* "op_sv_ptr" in each function containing a FIN statement. */
/* This variable points to the state variable data structure, */
/* and can be used from a C debugger to display their values. */
#undef FIN_PREAMBLE
#define FIN_PREAMBLE ta_gen_state *op_sv_ptr = pr_state_ptr;
/* Function Block */
enum { _block_origin = __LINE__ };
void
jsd_gen_request_creation ()
{
double next_creation_time;
Evhandle evh;
/** This function computes the time until the next packet creation
**/
/** from an exponential distribution based on the value of
**/
Master thesis MEE 03:24
Tommy Svensson 246
Alex Popescu
/** the ia_time attribute. The function schedules an interrupt
**/
/** at the time of the next creation.
**/
FIN (jsd_gen_request_creation ());
/* Only schedule interrupts if this generator is currently active.
*/
if (active)
{
/* Determine the next packet creation time. */
next_creation_time = op_dist_outcome (next_dist);
if (next_creation_time == OPC_DBL_INVALID)
jsd_gen_error ("Unable to get next packet creation
time from distribution.");
/* Schedule an interrupt for that time. */
evh = op_intrpt_schedule_self (op_sim_time () +
next_creation_time, JSDC_CREATE_INTRPT);
if (op_ev_valid (evh) == OPC_FALSE)
jsd_gen_error ("Unable to schedule self interrupt for
next packet creation.");
}
FOUT;
}
void
jsd_gen_error (msg)
char* msg;
{
/** Print an error message and exit the simulation. **/
FIN (jsd_gen_error (msg));
op_sim_end ("Error in JSD traffic generation process (jsd_gen):",
msg, OPC_NIL, OPC_NIL);
FOUT;
}
/* End of Function Block */
/* Undefine optional tracing in FIN/FOUT/FRET */
/* The FSM has its own tracing code and the other */
/* functions should not have any tracing. */
#undef FIN_TRACING
#define FIN_TRACING
#undef FOUTRET_TRACING
#define FOUTRET_TRACING
#if defined (__cplusplus)
extern "C" {
#endif
void ta_gen (void);
Compcode ta_gen_init (void **);
Master thesis MEE 03:24
Tommy Svensson 247
Alex Popescu
void ta_gen_diag (void);
void ta_gen_terminate (void);
void ta_gen_svar (void *, const char *, char **);
#if defined (__cplusplus)
} /* end of 'extern "C"' */
#endif
/* Process model interrupt handling procedure */
void
ta_gen (void)
{
int _block_origin = 0;
FIN (ta_gen ());
if (1)
{
Packet* pkptr;
double dval;
double svc_time;
double instructions;
double priority;
FSM_ENTER (ta_gen)
FSM_BLOCK_SWITCH
{
/*----------------------------------------------------
-----*/
/** state (init) enter executives **/
FSM_STATE_ENTER_FORCED_NOLABEL (0, "init", "ta_gen
[init enter execs]")
FSM_PROFILE_SECTION_IN ("ta_gen [init enter
execs]", state0_enter_exec)
{
/** These executives are encountered only once,
at the beginning of the simulation. **/
/** simulation. Their purpose is to initialize
the process model. The attributes **/
/** of this particular generator are determined
and distributions are loaded. **/
/* Get generator module's own object id. */
own_id = op_id_self ();
/* Get the assigned value for the average packet
interarrival times. */
if (op_ima_obj_attr_get (own_id, "ia_time",
&ia_time) == OPC_COMPCODE_FAILURE)
jsd_gen_error ("Unable to get mean packet
interarrival time from attribute.");
Master thesis MEE 03:24
Tommy Svensson 248
Alex Popescu
/* Determine whether this particular generator
is active. This attribute is useful */
/* for being able to "delete" generators without
having to modify the node model. */
if (op_ima_obj_attr_get (own_id, "active",
&active) == OPC_COMPCODE_FAILURE)
jsd_gen_error ("Unable to get activity
flag from attribute.");
/* Determine the upper bound of the number of
instructions of packets generated. */
if (op_ima_obj_attr_get (own_id,
"instruction_range", &instruction_range) == OPC_COMPCODE_FAILURE)
jsd_gen_error ("Unable to get number of
instructions range from attribute.");
/* Determine the upper bound of the range of
priorities of packets generated. */
if (op_ima_obj_attr_get (own_id,
"priority_range", &priority_range) == OPC_COMPCODE_FAILURE)
jsd_gen_error ("Unable to get priority
range from attribute.");
/* Load the distribution function for the packet
interarrival times. */
next_dist = op_dist_load ("exponential",
ia_time, 0.0);
if (next_dist == OPC_NIL)
jsd_gen_error ("Unable to load packet
arrival distribution.");
}
FSM_PROFILE_SECTION_OUT ("ta_gen [init enter
execs]", state0_enter_exec)
/** state (init) exit executives **/
FSM_STATE_EXIT_FORCED (0, "init", "ta_gen [init exit
execs]")
FSM_PROFILE_SECTION_IN ("ta_gen [init exit
execs]", state0_exit_exec)
{
/* When exiting this state, schedule the next
interrupt for */
/* a packet creation by calling
jsd_gen_request_creation(). */
jsd_gen_request_creation ();
}
FSM_PROFILE_SECTION_OUT ("ta_gen [init exit
execs]", state0_exit_exec)
/** state (init) transition processing **/
FSM_TRANSIT_FORCE (1, state1_enter_exec, ;, "default",
"", "init", "idle")
/*----------------------------------------------
-----------*/
Master thesis MEE 03:24
Tommy Svensson 249
Alex Popescu
/** state (idle) enter executives **/
FSM_STATE_ENTER_UNFORCED (1, state1_enter_exec,
"idle", "ta_gen [idle enter execs]")
FSM_PROFILE_SECTION_IN ("ta_gen [idle enter
execs]", state1_enter_exec)
{
}
FSM_PROFILE_SECTION_OUT ("ta_gen [idle enter
execs]", state1_enter_exec)
/** blocking after enter executives of unforced state.
**/
FSM_EXIT (3,ta_gen)
/** state (idle) exit executives **/
FSM_STATE_EXIT_UNFORCED (1, "idle", "ta_gen [idle exit
execs]")
FSM_PROFILE_SECTION_IN ("ta_gen [idle exit
execs]", state1_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("ta_gen [idle exit
execs]", state1_exit_exec)
/** state (idle) transition processing **/
FSM_PROFILE_SECTION_IN ("ta_gen [idle trans
conditions]", state1_trans_conds)
FSM_INIT_COND (CREATE)
FSM_TEST_COND (ARRIVAL)
FSM_DFLT_COND
FSM_TEST_LOGIC ("idle")
FSM_PROFILE_SECTION_OUT ("ta_gen [idle trans
conditions]", state1_trans_conds)
FSM_TRANSIT_SWITCH
{
FSM_CASE_TRANSIT (0, 2, state2_enter_exec, ;,
"CREATE", "", "idle", "xmt")
FSM_CASE_TRANSIT (1, 3, state3_enter_exec, ;,
"ARRIVAL", "", "idle", "rcv")
FSM_CASE_TRANSIT (2, 1, state1_enter_exec, ;,
"default", "", "idle", "idle")
}
/*----------------------------------------------
-----------*/
/** state (xmt) enter executives **/
FSM_STATE_ENTER_FORCED (2, state2_enter_exec, "xmt",
"ta_gen [xmt enter execs]")
Master thesis MEE 03:24
Tommy Svensson 250
Alex Popescu
FSM_PROFILE_SECTION_IN ("ta_gen [xmt enter
execs]", state2_enter_exec)
{
/** These executives are encountered when a
self-interrupt ocurrs, **/
/** indicating that it is time to create and
send a new packet. **/
/* Create a packet with the jsd format, and
retain the packet pointer. */
pkptr = op_pk_create_fmt ("jsd_pk");
if (pkptr == OPC_NIL)
jsd_gen_error ("Unable to create
packet.");
/* Set the orig_id and orig_port so that the
packet will be delivered */
/* back to this generator when it has been
serviced. */
if (op_pk_nfd_set (pkptr, "orig_id", own_id) ==
OPC_COMPCODE_FAILURE ||
op_pk_nfd_set (pkptr, "orig_port",
JSDC_RCV_IN_STRM) == OPC_COMPCODE_FAILURE)
{
jsd_gen_error ("Unable to set ID or port
in newly created packet.");
}
/* The jsd packet format also contains an ack
field, but */
/* it will be left unset, since the packet was
just */
/* created and the field default is unset. This
will */
/* indicate that this packet is a request and
not an ack. */
/** Set the appropriate field of the packet
**/
/* instructions = op_dist_uniform
(instruction_range); */
instructions = instruction_range;
if (instructions == OPC_DBL_INVALID)
jsd_gen_error ("Unable to get instructions
from distribution.");
if (op_pk_nfd_set (pkptr, "instructions",
instructions) == OPC_COMPCODE_FAILURE)
jsd_gen_error ("Unable to set instructions
in packet.");
/* Determine and set the priority of this
packet. */
Master thesis MEE 03:24
Tommy Svensson 251
Alex Popescu
/* priority = op_dist_uniform (priority_range);
*/
priority = priority_range;
if (priority == OPC_DBL_INVALID)
jsd_gen_error ("Unable to get priority
from distribution.");
op_pk_priority_set (pkptr, priority);
/* Send the packet over the XMT_OUT stream. */
op_pk_send (pkptr, JSDC_XMT_OUT_STRM);
}
FSM_PROFILE_SECTION_OUT ("ta_gen [xmt enter
execs]", state2_enter_exec)
/** state (xmt) exit executives **/
FSM_STATE_EXIT_FORCED (2, "xmt", "ta_gen [xmt exit
execs]")
FSM_PROFILE_SECTION_IN ("ta_gen [xmt exit
execs]", state2_exit_exec)
{
/* When exiting this state, schedule the next
interrupt for */
/* a packet creation by calling
jsd_gen_request_creation(). */
jsd_gen_request_creation ();
}
FSM_PROFILE_SECTION_OUT ("ta_gen [xmt exit
execs]", state2_exit_exec)
/** state (xmt) transition processing **/
FSM_TRANSIT_FORCE (1, state1_enter_exec, ;, "default",
"", "xmt", "idle")
/*----------------------------------------------
-----------*/
/** state (rcv) enter executives **/
FSM_STATE_ENTER_FORCED (3, state3_enter_exec, "rcv",
"ta_gen [rcv enter execs]")
FSM_PROFILE_SECTION_IN ("ta_gen [rcv enter
execs]", state3_enter_exec)
{
/** These executives are encountered when a
packet is received on the **/
/** RCV_IN_STRM. The packet is destroyed to
free its memory requirements. **/
/* Acquire the incoming packet. */
pkptr = op_pk_get (JSDC_RCV_IN_STRM);
/* Deallocate the packet. */
if (pkptr != OPC_NIL)
op_pk_destroy (pkptr);
}
Master thesis MEE 03:24
Tommy Svensson 252
Alex Popescu
FSM_PROFILE_SECTION_OUT ("ta_gen [rcv enter
execs]", state3_enter_exec)
/** state (rcv) exit executives **/
FSM_STATE_EXIT_FORCED (3, "rcv", "ta_gen [rcv exit
execs]")
FSM_PROFILE_SECTION_IN ("ta_gen [rcv exit
execs]", state3_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("ta_gen [rcv exit
execs]", state3_exit_exec)
/** state (rcv) transition processing **/
FSM_TRANSIT_FORCE (1, state1_enter_exec, ;, "default",
"", "rcv", "idle")
/*----------------------------------------------
-----------*/
}
FSM_EXIT (0,ta_gen)
}
}
#if defined (__cplusplus)
extern "C" {
#endif
extern VosT_Fun_Status Vos_Catmem_Register (const char * , int ,
VosT_Void_Null_Proc, VosT_Address *);
extern VosT_Address Vos_Catmem_Alloc (VosT_Address, size_t);
extern VosT_Fun_Status Vos_Catmem_Dealloc (VosT_Address);
#if defined (__cplusplus)
}
#endif
Compcode
ta_gen_init (void ** gen_state_pptr)
{
int _block_origin = 0;
static VosT_Address obtype = OPC_NIL;
FIN (ta_gen_init (gen_state_pptr))
if (obtype == OPC_NIL)
{
/* Initialize memory management */
if (Vos_Catmem_Register ("proc state vars (ta_gen)",
sizeof (ta_gen_state), Vos_Vnop, &obtype) ==
VOSC_FAILURE)
{
Master thesis MEE 03:24
Tommy Svensson 253
Alex Popescu
FRET (OPC_COMPCODE_FAILURE)
}
}
*gen_state_pptr = Vos_Catmem_Alloc (obtype, 1);
if (*gen_state_pptr == OPC_NIL)
{
FRET (OPC_COMPCODE_FAILURE)
}
else
{
/* Initialize FSM handling */
((ta_gen_state *)(*gen_state_pptr))->current_block = 0;
FRET (OPC_COMPCODE_SUCCESS)
}
}
void
ta_gen_diag (void)
{
/* No Diagnostic Block */
}
void
ta_gen_terminate (void)
{
int _block_origin = __LINE__;
FIN (ta_gen_terminate (void))
Vos_Catmem_Dealloc (pr_state_ptr);
FOUT
}
/* Undefine shortcuts to state variables to avoid */
/* syntax error in direct access to fields of */
/* local variable prs_ptr in ta_gen_svar function. */
#undef own_id
#undef active
#undef instruction_range
#undef priority_range
#undef next_dist
#undef ia_time
void
ta_gen_svar (void * gen_ptr, const char * var_name, char ** var_p_ptr)
{
Master thesis MEE 03:24
Tommy Svensson 254
Alex Popescu
ta_gen_state *prs_ptr;
FIN (ta_gen_svar (gen_ptr, var_name, var_p_ptr))
if (var_name == OPC_NIL)
{
*var_p_ptr = (char *)OPC_NIL;
FOUT
}
prs_ptr = (ta_gen_state *)gen_ptr;
if (strcmp ("own_id" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->own_id);
FOUT
}
if (strcmp ("active" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->active);
FOUT
}
if (strcmp ("instruction_range" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->instruction_range);
FOUT
}
if (strcmp ("priority_range" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->priority_range);
FOUT
}
if (strcmp ("next_dist" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->next_dist);
FOUT
}
if (strcmp ("ia_time" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->ia_time);
FOUT
}
*var_p_ptr = (char *)OPC_NIL;
FOUT
}
Master thesis MEE 03:24
Tommy Svensson 255
Alex Popescu
Appendix 4
/* Process model C form file: ta_wfq.pr.c */
/* This variable carries the header into the object file */
static const char ta_wfq_pr_c [] = "MIL_3_Tfile_Hdr_ 90A 30A modeler 7
3EFDA029 3EFDA029 1 its-2503-5 exjobb 0 0 none none 0 0 none 0 0 0 0 0 0
";
#include <string.h>
/* OPNET system definitions */
#include <opnet.h>
#if defined (__cplusplus)
extern "C" {
#endif
FSM_EXT_DECS
#if defined (__cplusplus)
} /* end of 'extern "C"' */
#endif
/* Header Block */
#include <stdlib.h> /* atof(), atoi() */
#define QUEUE_EMPTY op_q_empty ()
/* Packet arrival macro */
#define PK_ARRIVAL op_intrpt_type () == OPC_INTRPT_STRM
/* Service completion macro */
#define SVC_COMPLETION op_intrpt_type () == OPC_INTRPT_SELF
#define SUBQ_INACTIVE 0
#define SUBQ_ACTIVE 1
#define SUBQ_EMPTY 0
#define SERVER_FREE 0
#define SERVER_BUSY 1
double VT (void);
void ta_wfq_error (char * msg);
double retmaximum (double val1,double val2);
double SoQ_calc(int sq);
double get_VFT (int sq);
/* End of Header Block */
#if !defined (VOSD_NO_FIN)
#undef BIN
Master thesis MEE 03:24
Tommy Svensson 256
Alex Popescu
#undef BOUT
#define BIN FIN_LOCAL_FIELD(last_line_passed) = __LINE__ -
_block_origin;
#define BOUT BIN
#define BINIT FIN_LOCAL_FIELD(last_line_passed) = 0; _block_origin =
__LINE__;
#else
#define BINIT
#endif /* #if !defined (VOSD_NO_FIN) */
/* State variable definitions */
typedef struct
{
/* Internal state tracking for FSM */
FSM_SYS_STATE
/* State Variables */
double processing_rate;
Objid own_id;
double weight[3];
int active_queues[3];
int server_busy;
} ta_wfq_state;
#define pr_state_ptr ((ta_wfq_state*)
SimI_Mod_State_Ptr)
#define processing_rate pr_state_ptr->processing_rate
#define own_id pr_state_ptr->own_id
#define weight pr_state_ptr->weight
#define active_queues pr_state_ptr->active_queues
#define server_busy pr_state_ptr->server_busy
/* This macro definition will define a local variable called */
/* "op_sv_ptr" in each function containing a FIN statement. */
/* This variable points to the state variable data structure, */
/* and can be used from a C debugger to display their values. */
#undef FIN_PREAMBLE
#define FIN_PREAMBLE ta_wfq_state *op_sv_ptr = pr_state_ptr;
/* Function Block */
enum { _block_origin = __LINE__ };
double VT (void)
{
int no_active_q;
int i;
double virtual_time;
/** This function returns the virtual time **/
/* Determine number of active queues */
for (i=0;i<3;i++)
{
no_active_q += active_queues[i];
}
Master thesis MEE 03:24
Tommy Svensson 257
Alex Popescu
/* Calculate virtual time*/
virtual_time = 1/retmaximum(1.0 , no_active_q);
return virtual_time;
}
double retmaximum (double val1,double val2)
{
/** This function takes two values as arguments and returns the
**/
/** biggest value **/
if (val1 < val2)
return val2;
else
return val1;
}
double SoQ_calc(int sq)
{
double tot_weight;
double SoQ_value;
int i;
/** This function returns share of queue **/
tot_weight=0;
for (i=0;i<3;i++)
{
if (active_queues[i]== SUBQ_ACTIVE )
tot_weight+=weight[i];
}
if (tot_weight==0.0)
ta_wfq_error ("Unable to determine SoQ");
SoQ_value = weight[sq]/tot_weight;
return SoQ_value;
}
double get_VFT (int sq)
{
double dval;
double prev_pk_vft;
Packet* pkptr;
/* Determine how many jobs there are in the queue. */
dval = op_subq_stat (sq, OPC_QSTAT_PKSIZE);
if (dval == OPC_DBL_INVALID)
ta_wfq_error ("Unable to get number of packets in
subqueue.");
if ( (int)dval == SUBQ_EMPTY)
{
return 0.0;
Master thesis MEE 03:24
Tommy Svensson 258
Alex Popescu
}
else
{
/* Get a handle to the tail packet */
pkptr = op_subq_pk_access (sq,OPC_QPOS_TAIL);
if (pkptr == OPC_NIL)
ta_wfq_error ("Unable to access packet in subqueue.");
/* Determine VFT */
if (op_pk_nfd_get (pkptr, "svc_time_remain", &prev_pk_vft)
== OPC_COMPCODE_FAILURE)
ta_wfq_error ("Unable to get remaining service time
from packet.");
return prev_pk_vft;
}
}
void
ta_wfq_error (msg)
char* msg;
{
/** Print an error message and exit the simulation. **/
FIN (ta_wfq_error (msg));
op_sim_end ("Error in WFQ process (ta_wfq):",
msg, OPC_NIL, OPC_NIL);
FOUT
}
/* End of Function Block */
/* Undefine optional tracing in FIN/FOUT/FRET */
/* The FSM has its own tracing code and the other */
/* functions should not have any tracing. */
#undef FIN_TRACING
#define FIN_TRACING
#undef FOUTRET_TRACING
#define FOUTRET_TRACING
#if defined (__cplusplus)
extern "C" {
#endif
void ta_wfq (void);
Compcode ta_wfq_init (void **);
void ta_wfq_diag (void);
void ta_wfq_terminate (void);
void ta_wfq_svar (void *, const char *, char **);
#if defined (__cplusplus)
} /* end of 'extern "C"' */
#endif
Master thesis MEE 03:24
Tommy Svensson 259
Alex Popescu
/* Process model interrupt handling procedure */
void
ta_wfq (void)
{
int _block_origin = 0;
FIN (ta_wfq ());
if (1)
{
Packet* pkptr;
Objid orig_id;
int i;
int subq_no;
double pk_prio;
double VST;
double VFT;
double min_VFT;
double SoQ;
double dval;
double instructions;
double SVC_TIME;
FSM_ENTER (ta_wfq)
FSM_BLOCK_SWITCH
{
/*----------------------------------------------------
-----*/
/** state (init) enter executives **/
FSM_STATE_ENTER_FORCED_NOLABEL (0, "init", "ta_wfq
[init enter execs]")
FSM_PROFILE_SECTION_IN ("ta_wfq [init enter
execs]", state0_enter_exec)
{
/** These executives are encountered only once,
at the beginning of the simulation. **/
/** Their purpose is to initialize the process
model. The attributes of this particular **/
/** module are determined and state variables
are initialized. **/
/* Get queue module's own object id. */
own_id = op_id_self ();
/* Get assigned value of server processing rate.
*/
if (op_ima_obj_attr_get (own_id,
"processing_rate", &processing_rate) == OPC_COMPCODE_FAILURE)
ta_wfq_error ("Unable to get processing
rate from attribute.");
for(i=0;i<3;i++)
{
/* Get assigned value of the queue0-queue2
weight. */
Master thesis MEE 03:24
Tommy Svensson 260
Alex Popescu
if (op_ima_obj_attr_get (own_id,
"queue_weight0", &weight[i] ) == OPC_COMPCODE_FAILURE)
ta_wfq_error ("Unable to get queue
weight from attribute.");
}
/* Set subqueues to inactive */
for(i=0;i<3;i++)
{
active_queues[i]=SUBQ_INACTIVE;
}
/* Set server as free */
server_busy= SERVER_FREE;
}
FSM_PROFILE_SECTION_OUT ("ta_wfq [init enter
execs]", state0_enter_exec)
/** state (init) exit executives **/
FSM_STATE_EXIT_FORCED (0, "init", "ta_wfq [init exit
execs]")
FSM_PROFILE_SECTION_IN ("ta_wfq [init exit
execs]", state0_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("ta_wfq [init exit
execs]", state0_exit_exec)
/** state (init) transition processing **/
FSM_TRANSIT_FORCE (1, state1_enter_exec, ;, "default",
"", "init", "idle")
/*----------------------------------------------
-----------*/
/** state (idle) enter executives **/
FSM_STATE_ENTER_UNFORCED (1, state1_enter_exec,
"idle", "ta_wfq [idle enter execs]")
FSM_PROFILE_SECTION_IN ("ta_wfq [idle enter
execs]", state1_enter_exec)
{
}
FSM_PROFILE_SECTION_OUT ("ta_wfq [idle enter
execs]", state1_enter_exec)
/** blocking after enter executives of unforced state.
**/
FSM_EXIT (3,ta_wfq)
/** state (idle) exit executives **/
Master thesis MEE 03:24
Tommy Svensson 261
Alex Popescu
FSM_STATE_EXIT_UNFORCED (1, "idle", "ta_wfq [idle exit
execs]")
FSM_PROFILE_SECTION_IN ("ta_wfq [idle exit
execs]", state1_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("ta_wfq [idle exit
execs]", state1_exit_exec)
/** state (idle) transition processing **/
FSM_PROFILE_SECTION_IN ("ta_wfq [idle trans
conditions]", state1_trans_conds)
FSM_INIT_COND (SVC_COMPLETION)
FSM_TEST_COND (PK_ARRIVAL)
FSM_TEST_LOGIC ("idle")
FSM_PROFILE_SECTION_OUT ("ta_wfq [idle trans
conditions]", state1_trans_conds)
FSM_TRANSIT_SWITCH
{
FSM_CASE_TRANSIT (0, 3, state3_enter_exec, ;,
"SVC_COMPLETION", "", "idle", "svc_comp")
FSM_CASE_TRANSIT (1, 2, state2_enter_exec, ;,
"PK_ARRIVAL", "", "idle", "enqueue")
}
/*----------------------------------------------
-----------*/
/** state (enqueue) enter executives **/
FSM_STATE_ENTER_FORCED (2, state2_enter_exec,
"enqueue", "ta_wfq [enqueue enter execs]")
FSM_PROFILE_SECTION_IN ("ta_wfq [enqueue enter
execs]", state2_enter_exec)
{
/** These executives are encountered when a
packet arrives on an input stream. **/
/* Acquire the arriving packet. */
/* Multiple arriving streams are supported. */
pkptr = op_pk_get (op_intrpt_strm());
if (pkptr == OPC_NIL)
ta_wfq_error ("Unable to get packet from
input stream.");
/* Determine this packet's priority */
pk_prio=op_pk_priority_get (pkptr);
/* Set subQueue as active */
active_queues[(int)pk_prio] = SUBQ_ACTIVE;
/* Determine VFT for packet in queue tail */
VFT = get_VFT( (int)pk_prio );
Master thesis MEE 03:24
Tommy Svensson 262
Alex Popescu
/* Calculate Vitrual Start Time */
VST = retmaximum ( VFT , VT() );
/* Get the number of instructions directly
*/
/* from the named field in the packet.
*/
if (op_pk_nfd_get (pkptr, "instructions",
&instructions) == OPC_COMPCODE_FAILURE)
ta_wfq_error ("Unable to get instructions
field from packet.");
/* Calculate Service time fr this packet */
SVC_TIME = instructions/processing_rate;
/* Calculate Share of Queue */
SoQ = SoQ_calc((int)pk_prio);
/* Calculate Virtual Finish Time*/
VFT = VST + SVC_TIME/SoQ;
/* Attach the VFT to the packet */
if (op_pk_nfd_set (pkptr, "svc_time_remain",
VFT) == OPC_COMPCODE_FAILURE)
ta_wfq_error ("Unable to set VFT field in
packet.");
/* Attach the service time to the packet */
if (op_pk_nfd_set (pkptr, "svc_time", SVC_TIME)
== OPC_COMPCODE_FAILURE)
ta_wfq_error ("Unable to set VFT field in
packet.");
/* Attempt to enqueue the packet at the tail of
subqueue pk_prio. */
if (op_subq_pk_insert ((int)pk_prio, pkptr,
OPC_QPOS_TAIL) != OPC_QINS_OK)
{
/* The insertion failed (due to a full
queue). Deallocate the packet. */
op_pk_destroy (pkptr);
}
}
FSM_PROFILE_SECTION_OUT ("ta_wfq [enqueue enter
execs]", state2_enter_exec)
/** state (enqueue) exit executives **/
FSM_STATE_EXIT_FORCED (2, "enqueue", "ta_wfq [enqueue
exit execs]")
FSM_PROFILE_SECTION_IN ("ta_wfq [enqueue exit
execs]", state2_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("ta_wfq [enqueue exit
execs]", state2_exit_exec)
Master thesis MEE 03:24
Tommy Svensson 263
Alex Popescu
/** state (enqueue) transition processing **/
FSM_PROFILE_SECTION_IN ("ta_wfq [enqueue trans
conditions]", state2_trans_conds)
FSM_INIT_COND (!server_busy)
FSM_DFLT_COND
FSM_TEST_LOGIC ("enqueue")
FSM_PROFILE_SECTION_OUT ("ta_wfq [enqueue trans
conditions]", state2_trans_conds)
FSM_TRANSIT_SWITCH
{
FSM_CASE_TRANSIT (0, 4, state4_enter_exec, ;,
"!server_busy", "", "enqueue", "scheduler")
FSM_CASE_TRANSIT (1, 1, state1_enter_exec, ;,
"default", "", "enqueue", "idle")
}
/*----------------------------------------------
-----------*/
/** state (svc_comp) enter executives **/
FSM_STATE_ENTER_FORCED (3, state3_enter_exec,
"svc_comp", "ta_wfq [svc_comp enter execs]")
FSM_PROFILE_SECTION_IN ("ta_wfq [svc_comp enter
execs]", state3_enter_exec)
{
/** These executives are encountered when a
packet completes **/
/** service.
**/
/* Determine the subqueue of the packet just
completing service. */
/* This is passed as the code associated with
the service */
/* completion interrupt.
*/
subq_no = op_intrpt_code ();
/* Extract the packet which is the current job.
*/
/* This is the packet just finishing service.
*/
pkptr = op_subq_pk_remove (subq_no,
OPC_QPOS_HEAD);
if (pkptr == OPC_NIL)
ta_wfq_error ("Unable to extract packet to
service from subqueue.");
/* Packet has been serviced. Deallocate the
packet. */
op_pk_destroy (pkptr);
/* Determine if subqueue is empty */
Master thesis MEE 03:24
Tommy Svensson 264
Alex Popescu
dval = op_subq_stat (subq_no, OPC_QSTAT_PKSIZE);
if (dval == OPC_DBL_INVALID)
ta_wfq_error ("Unable to get number of
packets in subqueue.");
if (dval==0.0)
active_queues[subq_no]=SUBQ_INACTIVE;
/* Determine if there still are packets i the
system */
if (QUEUE_EMPTY)
server_busy=SERVER_FREE;
}
FSM_PROFILE_SECTION_OUT ("ta_wfq [svc_comp enter
execs]", state3_enter_exec)
/** state (svc_comp) exit executives **/
FSM_STATE_EXIT_FORCED (3, "svc_comp", "ta_wfq
[svc_comp exit execs]")
FSM_PROFILE_SECTION_IN ("ta_wfq [svc_comp exit
execs]", state3_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("ta_wfq [svc_comp exit
execs]", state3_exit_exec)
/** state (svc_comp) transition processing **/
FSM_PROFILE_SECTION_IN ("ta_wfq [svc_comp trans
conditions]", state3_trans_conds)
FSM_INIT_COND (!QUEUE_EMPTY)
FSM_DFLT_COND
FSM_TEST_LOGIC ("svc_comp")
FSM_PROFILE_SECTION_OUT ("ta_wfq [svc_comp trans
conditions]", state3_trans_conds)
FSM_TRANSIT_SWITCH
{
FSM_CASE_TRANSIT (0, 4, state4_enter_exec, ;,
"!QUEUE_EMPTY", "", "svc_comp", "scheduler")
FSM_CASE_TRANSIT (1, 1, state1_enter_exec, ;,
"default", "", "svc_comp", "idle")
}
/*----------------------------------------------
-----------*/
/** state (scheduler) enter executives **/
FSM_STATE_ENTER_FORCED (4, state4_enter_exec,
"scheduler", "ta_wfq [scheduler enter execs]")
FSM_PROFILE_SECTION_IN ("ta_wfq [scheduler enter
execs]", state4_enter_exec)
{
/** These executives schedules the packet with
smallest VFQ for transmisstion. **/
Master thesis MEE 03:24
Tommy Svensson 265
Alex Popescu
/* Determine subq with smallest VFT */
subq_no=0;
min_VFT=0.0;
for (i=0;i<3;i++)
{
if (active_queues[i]==SUBQ_ACTIVE)
{
/* Get a handle to the HoL packet */
pkptr = op_subq_pk_access
(i,OPC_QPOS_HEAD);
if (pkptr == OPC_NIL)
ta_wfq_error ("Unable to
access packet in subqueue.");
/* Determine VFT */
if (op_pk_nfd_get (pkptr,
"svc_time_remain", &VFT) == OPC_COMPCODE_FAILURE)
ta_wfq_error ("Unable to get
VFT from packet.");
if (min_VFT==0.0)
{
min_VFT=VFT;
subq_no=i;
}
else if (min_VFT>VFT)
{
min_VFT=VFT;
subq_no=i;
}
}
}
/* Access packet with smallest VFT */
pkptr = op_subq_pk_access
(subq_no,OPC_QPOS_HEAD);
if (pkptr == OPC_NIL)
ta_wfq_error ("Unable to access packet in
subqueue.");
/* Determine the packet's service time */
if (op_pk_nfd_get (pkptr, "svc_time", &SVC_TIME)
== OPC_COMPCODE_FAILURE)
ta_wfq_error ("Unable to get service time
from packet.");
/* Schedule the packet for service */
op_intrpt_schedule_self (op_sim_time () +
SVC_TIME, subq_no);
/* Set server as busy */
server_busy=SERVER_BUSY;
}
Master thesis MEE 03:24
Tommy Svensson 266
Alex Popescu
FSM_PROFILE_SECTION_OUT ("ta_wfq [scheduler
enter execs]", state4_enter_exec)
/** state (scheduler) exit executives **/
FSM_STATE_EXIT_FORCED (4, "scheduler", "ta_wfq
[scheduler exit execs]")
FSM_PROFILE_SECTION_IN ("ta_wfq [scheduler exit
execs]", state4_exit_exec)
{
}
FSM_PROFILE_SECTION_OUT ("ta_wfq [scheduler exit
execs]", state4_exit_exec)
/** state (scheduler) transition processing **/
FSM_TRANSIT_FORCE (1, state1_enter_exec, ;, "default",
"", "scheduler", "idle")
/*----------------------------------------------
-----------*/
}
FSM_EXIT (0,ta_wfq)
}
}
#if defined (__cplusplus)
extern "C" {
#endif
extern VosT_Fun_Status Vos_Catmem_Register (const char * , int ,
VosT_Void_Null_Proc, VosT_Address *);
extern VosT_Address Vos_Catmem_Alloc (VosT_Address, size_t);
extern VosT_Fun_Status Vos_Catmem_Dealloc (VosT_Address);
#if defined (__cplusplus)
}
#endif
Compcode
ta_wfq_init (void ** gen_state_pptr)
{
int _block_origin = 0;
static VosT_Address obtype = OPC_NIL;
FIN (ta_wfq_init (gen_state_pptr))
if (obtype == OPC_NIL)
{
/* Initialize memory management */
if (Vos_Catmem_Register ("proc state vars (ta_wfq)",
sizeof (ta_wfq_state), Vos_Vnop, &obtype) ==
VOSC_FAILURE)
{
Master thesis MEE 03:24
Tommy Svensson 267
Alex Popescu
FRET (OPC_COMPCODE_FAILURE)
}
}
*gen_state_pptr = Vos_Catmem_Alloc (obtype, 1);
if (*gen_state_pptr == OPC_NIL)
{
FRET (OPC_COMPCODE_FAILURE)
}
else
{
/* Initialize FSM handling */
((ta_wfq_state *)(*gen_state_pptr))->current_block = 0;
FRET (OPC_COMPCODE_SUCCESS)
}
}
void
ta_wfq_diag (void)
{
/* No Diagnostic Block */
}
void
ta_wfq_terminate (void)
{
int _block_origin = __LINE__;
FIN (ta_wfq_terminate (void))
Vos_Catmem_Dealloc (pr_state_ptr);
FOUT
}
/* Undefine shortcuts to state variables to avoid */
/* syntax error in direct access to fields of */
/* local variable prs_ptr in ta_wfq_svar function. */
#undef processing_rate
#undef own_id
#undef weight
#undef active_queues
#undef server_busy
void
ta_wfq_svar (void * gen_ptr, const char * var_name, char ** var_p_ptr)
{
ta_wfq_state *prs_ptr;
Master thesis MEE 03:24
Tommy Svensson 268
Alex Popescu
FIN (ta_wfq_svar (gen_ptr, var_name, var_p_ptr))
if (var_name == OPC_NIL)
{
*var_p_ptr = (char *)OPC_NIL;
FOUT
}
prs_ptr = (ta_wfq_state *)gen_ptr;
if (strcmp ("processing_rate" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->processing_rate);
FOUT
}
if (strcmp ("own_id" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->own_id);
FOUT
}
if (strcmp ("weight" , var_name) == 0)
{
*var_p_ptr = (char *) (prs_ptr->weight);
FOUT
}
if (strcmp ("active_queues" , var_name) == 0)
{
*var_p_ptr = (char *) (prs_ptr->active_queues);
FOUT
}
if (strcmp ("server_busy" , var_name) == 0)
{
*var_p_ptr = (char *) (&prs_ptr->server_busy);
FOUT
}
*var_p_ptr = (char *)OPC_NIL;
FOUT
}