1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
|
\chapter{DelayBox: Per-Flow Delay and Loss}
\label{chap:delaybox}
DelayBox is an ns node that should be placed in between the source and
destination nodes. With Delaybox, packets from a TCP flow can be
delayed, dropped, and/or forced through a bottleneck link before being
passed on to the next node. A distribution can be used to specify
delay, loss, and/or bottleneck link speed for a source - destination
pair. Each flow between that source - destination pair draws from the
distribution to determine its characteristics. Delays in DelayBox are
per-flow, rather than per-packet. Since DelayBox distinguishes between
flows, the {\tt fid\_} variable (flow identifier) should be set for
each flow in the simulation. DelayBox can be used with both Tcp and
FullTcp agents.
\section{Implementation Details}
DelayBox maintains two tables: a rule table and a flow table. Entries
in the rule table are added by the user in the OTcl simulation script
and give an outline of how flows from a source to a destination should
be treated. The fields are source, destination, delay Random Variable
(in ms), loss rate Random Variable (in fraction of packets dropped),
and bottleneck link speed Random Variable (in Mbps). The bottleneck
link speed field is optional. Entries in the flow table are created
internally and specify exactly how each flow should be handled. Its
values are obtained by sampling from the distributions given in the
rule table. The fields are source, destination, flow ID, delay, loss,
and bottleneck link speed (if applicable). Full-TCP flows are defined
as beginning at the receipt of the first SYN of a new flow ID and
ending after the sending of the first FIN. Packets after the first
FIN are forwarded immediately (<i>i.e.</i>, they are neither delayed
nor dropped by DelayBox). For TcpAgent, flows are defined as beginning
at the receipt of the first 40 byte packet of a new flow ID. Since
there are no FIN packets in TcpAgent, TcpAgent flows are never
considered finished nor are they removed from the flow table.
DelayBox also maintains a set of queues to handle delaying packets.
There is one queue per entry in the flow table. These queues are
implemented as delta queues, in that the time to transfer the packet
is kept only for the head packet. All other packets are stored with
the difference between the time they should be transferred and the
time the previous packet should be transferred. The actual time the
previous packet should be transferred is stored in the variable {\tt
deltasum\_}, named so because it is the sum of all delta values in
the queue (including the head packet's transfer time). If the
bottleneck link speed has been specified for the flow, a processing
delay is computed for each packet by dividing the size of the packet
by the flow's bottleneck link speed.
When a packet is received, its transfer time (current time + delay) is
calculated. (This transfer time is the time that the first bit of the
packet will begin transfer. Packets that wait in the queue behind
this packet must be delayed by the amount of time to transfer all bits
of the packet over the bottleneck link.) There are two scenarios to
consider in deciding how to set the packet's delta:
\begin{enumerate}
\item If the packet is due to be transferred before the last bit of
the last packet in the queue, its delta (the time between transferring
the previous packet and transferring this packet) is set to the
previous packet's processing delay. This packet has to queue
behind the previous packet, but will be ready to be transmitted as
soon as the previous packet has completed its transfer.
\item If the packet is due to be transferred after the last bit of
the last packet in the queue, its delta is difference between this
packet's transfer time and the previous packet's transfer time.
\end{enumerate}
If the current packet is the only packet in the queue, DelayBox
schedules a timer for the receipt of the packet. When this timer
expires, DelayBox will pass the packet on to the standard packet
forwarder for processing. Once a packet has been passed up,
DelayBox will look for the next packet in the queue to be
processed and schedule a timer for its transfer. All packets, both
data and ACKs, are delayed in this manner.
Packets that should be dropped are neither queued nor passed on. All
packets in a queue are from the same connection and are delayed
the same amount (except for delays due to packet size) and are
dropped with the same probability. {\bf Note:} Drops at DelayBox are
not recorded in the trace-queue file.
\section{Example}
More examples are available in the {\tt tcl/ex/delaybox/} directory of the
ns source code. The validation script {\tt test-suite-delaybox.tcl}
is in {\tt tcl/test/} and can be run with the command {\tt
test-all-delaybox} from that directory.
\begin{verbatim}
# test-delaybox.tcl - NS file transfer with DelayBox
# setup ns
remove-all-packet-headers; # removes all packet headers
add-packet-header IP TCP; # adds TCP/IP headers
set ns [new Simulator]; # instantiate the simulator
global defaultRNG
$defaultRNG seed 999
# create nodes
set n_src [$ns node]
set db(0) [$ns DelayBox]
set db(1) [$ns DelayBox]
set n_sink [$ns node]
# setup links
$ns duplex-link $db(0) $db(1) 100Mb 1ms DropTail
$ns duplex-link $n_src $db(0) 100Mb 1ms DropTail
$ns duplex-link $n_sink $db(1) 100Mb 1ms DropTail
set src [new Agent/TCP/FullTcp]
set sink [new Agent/TCP/FullTcp]
$src set fid_ 1
$sink set fid_ 1
# attach agents to nodes
$ns attach-agent $n_src $src
$ns attach-agent $n_sink $sink
# make the connection
$ns connect $src $sink
$sink listen
# create random variables
set recvr_delay [new RandomVariable/Uniform]; # delay 1-20 ms
$recvr_delay set min_ 1
$recvr_delay set max_ 20
set sender_delay [new RandomVariable/Uniform]; # delay 20-100 ms
$sender_delay set min_ 20
$sender_delay set max_ 100
set recvr_bw [new RandomVariable/Constant]; # bw 100 Mbps
$recvr_bw set val_ 100
set sender_bw [new RandomVariable/Uniform]; # bw 1-20 Mbps
$sender_bw set min_ 1
$sender_bw set max_ 20
set loss_rate [new RandomVariable/Uniform]; # loss 0-1% loss
$loss_rate set min_ 0
$loss_rate set max_ 0.01
# setup rules for DelayBoxes
$db(0) add-rule [$n_src id] [$n_sink id] $recvr_delay $loss_rate $recvr_bw
$db(1) add-rule [$n_src id] [$n_sink id] $sender_delay $loss_rate $sender_bw
# output delays to files
$db(0) set-delay-file "db0.out"
$db(1) set-delay-file "db1.out"
# schedule traffic
$ns at 0.5 "$src advance 10000"
$ns at 1000.0 "$db(0) close-delay-file; $db(1) close-delay-file; exit 0"
# start the simulation
$ns run
\end{verbatim}
\section{Commands at a Glance}
The following commands on the DelayBox class can be accessed from OTcl:
{\tt [\$ns DelayBox]}\\
Creates a new DelayBox node.
{\tt \$delaybox add-rule <srcNodeID> <dstNodeID> <delayRV> [<lossRV>] [<linkSpeedRV>]}\\
Add a rule to the rule table, specifying delay, loss rate, and
bottleneck link speed RandomVariables for packets flowing from {\tt
srcNode} to {\tt dstNode}. Delay is required, but loss rate and
link speed are optional.
{\tt \$delaybox list-rules}\\
List all rules in the rule table
{\tt \$delaybox list-flows}\\
List all flows in the flow table
{\tt \$delaybox set-asymmetric}\\
Specifies that the delay should be only on the data path rather than
applied to both the data and ACK paths
{\tt \$delaybox set-delay-file <filename>}\\
Output delays for each flow to {\tt filename}. Format: {\tt srcNode
dstNode fid delay}
{\tt \$delaybox close-delay-file}\\
Closes the file where delays are written
{\tt \$delaybox set-debug <int>}\\
Set the debugging level
\begin{itemize}
\item{1: Output when packets are dropped at DelayBox}
\item{2: Level 1 + \\
Contents of the queue at each queue operation
}
\end{itemize}
|