Mobile Multimedia Streaming Improvements with Freeze-DCCP

Olivier Mehani, Roksana Boreli, Guillaume Jourjon, Thierry Ernst

To demonstrate the performance improvements of our proposed Freeze-DCCP/TFRC, we use the Orbit testbed to emulate vertical handovers and observe the impact on a CBR video stream. Rather than the intrinsic bandwidth made available to the video stream, its quality has been assessed. To this end, the peak-signal-to-noise ratio metric has been used. See also the Nicta publication page.

IMPORTANT NOTE This case study was last tested with OMF 5.3.1. It may require some updates to be reproduced with the latest OMF version.

Scenario

A user viewing a video stream on their mobile device goes out for a coffee then comes back home.

A user, initially (t1) at home, receiving a video stream on their mobile terminal connected to their home Wi-Fi network. They decide to get a coffee from the corner shop. On the way there, the terminal loses its connectivity to the home network, and hands off to the 3G network (t2). The coffee shop has a public wireless network, to which the terminal connects when it get in range (t3). With their coffee in hand, the user then heads back home, losing connectivity to the public Wi-Fi network and performing an handover to 3G at t4 , and finally reconnecting to their home network at t5.

Implementation

The experiment is run on two nodes of the Norbit testbed.

OMF experiment using the Norbit testbed

On the sender side, traffic is sent from a DCCP-enabled Iperf client. The packet size and frequency is adjusted to match those of the packetised video stream. This version of Iperf has also been instrumented using OML to report standard metrics such as troughput and packet loss.

On the receiver side, a custom application receives the DCCP traffic. Based on the sequence identifier in the Iperf headers, it which frames have been received properly, and which ones have been lost. It then reports the associated PSNR, which was precomputed for efficiency. For a lost frame, the PSNR is that of the initial raw frame to a image containing only noise.

Handovers disconnections are emulated using iptables, while network parameters are defined using tc and netem. The DCCP receiver is in charge of freezing and unfreezing the connection about one RTT before the handoff so that the traffic can be suspended on time.

Output

A PSNR graph is plotted and updated in real-time by the experiment controller as the scenario is executed. It shows a comparison of the normal protocol and the proposed improvement.

PSNR graph at the end of the experiment

The experiment controller's dashboard, however, gives access to more information about the experiment and its current state.

Experiment dashboard Experimental scripts currently executing Experimental scripts currently executing: receiver application description Logs of the current experiment XML representation of the current state of the experiment

Code

This demo is based on several components which have been specifically written or adapted:

Experiment script

  1 #!/usr/bin/omf exec 
  2 # $Id: freezedccp-qoe.rb 1775 2010-10-13 05:48:31Z omehani $
  3 #
  4 # Copyright (c) 2010, Nicta, Olivier Mehani <olivier.mehani@nicta.com.au>
  5 # All rights reserved.
  6 #
  7 # Redistribution and use in source and binary forms, with or without
  8 # modification, are permitted provided that the following conditions
  9 # are met:
 10 # 1. Redistributions of source code must retain the above copyright notice, this
 11 #    list of conditions and the following disclaimer.
 12 # 2. Redistributions in binary form must reproduce the above copyright notice,
 13 #    this list of conditions and the following disclaimer in the documentation
 14 #    and/or other materials provided with the distribution.
 15 # 3. Neither the name of Nicta nor the names of its contributors
 16 #    may be used to endorse or promote products derived from this software
 17 #    without specific prior written permission.
 18 #
 19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 20 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 21 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 22 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 23 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 24 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 25 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 26 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 27 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 28 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 29 # POSSIBILITY OF SUCH DAMAGE.
 30 # 
 31 defProperty('src', 'omf.nicta.node10', "ID of sender node")
 32 defProperty('dst', 'omf.nicta.node11', "ID of receiver node")
 33 defProperty('freezesrc', 'omf.nicta.node12', "ID of Freeze sender node")
 34 defProperty('freezedst', 'omf.nicta.node13', "ID of Freeze receiver node")
 35 defProperty('interface', 'exp0', "The network interface to use")
 36 defProperty('netid', '42', "Second byte of the class B network address (N in 10.N.x.y)")
 37 
 38 # Traffic emulation
 39 defProperty('payloadsize', "1324" , "Data payload size, in bytes")
 40 defProperty('datarate', "1M", "Application datarate, in bit/second")
 41 defProperty('interval', "0.5", "Interval in second for consecutive Iperf reporting") # XXX: why can't this be a float?
 42 defProperty('intervalrcv', "1", "Interval in second for consecutive Iperf receiver reporting")
 43 
 44 # Networks emulation
 45 defProperty('minbuffersize', 50, "Minimal buffer size for TC shaping, in kilobytes")
 46 defProperty('coredelay', 0.025, "Emulated delay of the core network in seconds")
 47 defProperty('homebw', 1, "Emulated bandwidth of the home network in Mbit/second")
 48 defProperty('homedelay', 0.001, "Emulated delay of the home network in seconds")
 49 defProperty('wanbw', 0.5, "Emulated bandwidth of the WAN in Mbit/second")
 50 defProperty('wandelay', 0.1, "Emulated delay of the WAN in seconds")
 51 defProperty('cafebw', 0.7, "Emulated bandwidth of the cafe network in Mbit/second")
 52 defProperty('cafedelay', 0.01, "Emulated delay of the cafe network in seconds")
 53 defProperty('wlossrate', 0, "Emulated wireless packet loss rate in percent")
 54 
 55 # Timing
 56 defProperty('t2', 30, "Time of first switch to WAN in seconds")
 57 defProperty('t3', 60, "Time of switch to cafe network in seconds")
 58 defProperty('t4', 90, "Time of second switch to WAN in seconds")
 59 defProperty('t5', 120, "Time of switch back to home network in seconds")
 60 defProperty('duration', 150, "Duration of the experiment in seconds")
 61 
 62 MEGABITS = 1048576
 63 
 64 srcaddr="192.168.#{property.netid}.#{property.src.value.match(/[0-9]+/)[0]}" 
 65 dstaddr="192.168.#{property.netid}.#{property.dst.value.match(/[0-9]+/)[0]}" 
 66 freezesrcaddr="192.168.#{property.netid}.#{property.freezesrc.value.match(/[0-9]+/)[0]}" 
 67 freezedstaddr="192.168.#{property.netid}.#{property.freezedst.value.match(/[0-9]+/)[0]}" 
 68 
 69 scenario = [
 70     { 'bw' => property.homebw,    'delay' => property.homedelay,    'duration' => property.t2 },
 71     { 'bw' => property.wanbw,    'delay' => property.wandelay,    'duration' => property.t3 - property.t2 },
 72     { 'bw' => property.cafebw,    'delay' => property.cafedelay,    'duration' => property.t4 - property.t3 },
 73     { 'bw' => property.wanbw,    'delay' => property.wandelay,    'duration' => property.t5 - property.t4 },
 74     { 'bw' => property.homebw,    'delay' => property.homedelay,    'duration' => property.duration - property.t5 },
 75 ]
 76 
 77 # Needs [655] as per #415
 78 addTab(:defaults)
 79 addTab(:graph2) do |tab|
 80     opts = { :postfix => %{QoE of DCCP and Freeze-DCCP streams in mobility scenarios}, :updateEvery => 1 }
 81     tab.addGraph("PSNR", opts) do |g|
 82         psnr_data = {}
 83         mp = ms('video')
 84         mp.project(:oml_sender_id, :oml_ts_server, :psnr_avg).each do |sample|
 85             id, time, psnr = sample.tuple
 86             (psnr_data[id] ||= []) << [time, psnr]
 87         end
 88         psnr_data.each do |d,v|
 89             g.addLine(v, :label => msSenderName[d])
 90         end
 91 
 92         freeze_data = {}
 93         mp = ms('dccp')
 94         mp.project(:oml_sender_id, :oml_ts_server, :freezestate_last).each do |sample|
 95             id, time, freeze = sample.tuple
 96             (freeze_data[id] ||= []) << [time, freeze]
 97         end
 98         freeze_data.each do |d,v|
 99             g.addLine(v, :label => "frozen #{msSenderName[d]}")
100         end
101     end
102     tab.addGraph("Senders", opts) do |g|
103         x_data = {}
104         rtt_data = {}
105         p_data = {}
106         mp = ms('TFRC_Info')
107         mp.project(:oml_sender_id, :oml_ts_server, :x_avg, :rtt_avg, :p_avg).each do |sample|
108             id, time, x, rtt, p = sample.tuple
109             (x_data[id] ||= []) << [time, 8*x/2000] # XXX
110             (rtt_data[id] ||= []) << [time, rtt]
111             (p_data[id] ||= []) << [time, p==0?0:Math.log(p*10**3)]
112         end
113         x_data.each do |d,v|
114             g.addLine(v, :label => "X #{msSenderName[d]} [kbps]")
115         end
116         rtt_data.each do |d,v|
117             g.addLine(v, :label => "RTT #{msSenderName[d]} [ms]")
118         end
119         p_data.each do |d,v|
120             g.addLine(v, :label => "p #{msSenderName[d]} (*10^3, log)")
121         end
122     end
123     tab.addGraph("Receivers", opts) do |g|
124         x_recv_data = {}
125         rtt_data = {}
126         p_data = {}
127         freeze_data = {}
128         mp = ms('dccp')
129         mp.project(:oml_sender_id, :oml_ts_server, :x_recv_avg, :rtt_avg, :p_avg, :freezestate_last).each do |sample|
130             id, time, x_recv, rtt, p, freeze = sample.tuple
131             (x_recv_data[id] ||= []) << [time, 8*x_recv/1000]
132             (rtt_data[id] ||= []) << [time, rtt]
133             (p_data[id] ||= []) << [time, p==0?0:Math.log(p*10**3)]
134             (freeze_data[id] ||= []) << [time, freeze]
135         end
136         x_recv_data.each do |d,v|
137             g.addLine(v, :label => "Xrecv #{msSenderName[d]} [kbps]")
138         end
139         rtt_data.each do |d,v|
140             g.addLine(v, :label => "RTT #{msSenderName[d]} [ms]")
141         end
142         p_data.each do |d,v|
143             g.addLine(v, :label => "p #{msSenderName[d]} (*10^3, log)")
144         end
145         freeze_data.each do |d,v|
146             g.addLine(v, :label => "frozen #{msSenderName[d]}")
147         end
148     end
149 end
150 
151 defApplication('iperf20','iperf20'){|a|
152     a.name = "iperf2" 
153     a.version(0, 0, 1)
154     a.path = "/root/iperf" 
155     a.shortDescription = "Iperf traffic generator" 
156     a.description = <<TEXT
157 Iperf is a traffic generator for TCP, UDP and DCCP traffic. It contains
158 generators producing various forms of packet streams and port for sending these
159 packets via various transports, such as TCP, UDP and DCCP.
160 TEXT
161 
162     # Define the properties that can be configured for this application
163     # 
164     # syntax: defProperty(name, description, mnemonic = nil, options = nil)
165     #
166     a.defProperty('udp', 'Use UDP, otherwise TCP by default', 'u',  {:order => 2, :dynamic => false, :type => :boolean})
167     a.defProperty('dccp', 'Use DCCP, otherwise TCP by default', 'd',  {:order => 2, :dynamic => false, :type => :boolean})
168     a.defProperty('reportstyle', 'Report Style', 'y',  {:dynamic => false, :type => :string})
169     a.defProperty('client', 'Run as client', 'c',  {:order => 1, :dynamic => false, :type => :string})
170     a.defProperty('server', 'Client/Server', 's', {:type => :boolean, :dynamic => false})
171     a.defProperty('port', 'Sender port number', 'p', {:type => :integer, :dynamic => false})
172     a.defProperty('window', 'TCP Send Window Size', nil, {:type => :integer, :dynamic => false})
173     a.defProperty('time', "Duration of traffic generation(secs)", nil, {:type => :integer, :dynamic => false})
174     a.defProperty('len', "Buffer length (A.K.A. datagram payload size)", 'l',  {:dynamic => false, :type => :string})
175     a.defProperty('bandwidth', "Offered load for UDP", 'b',  {:dynamic => false, :type => :string})
176     a.defProperty('parallel', "Number of parallel flows", nil, {:type => :integer, :dynamic => false})
177     a.defProperty('interval', "Interval between reports (sec)", nil, {:type => :string, :dynamic => false})
178 
179     # Define the Measurement Points and associated metrics that are available for this application
180     #
181     a.defMeasurement("Peer_Info"){ |m|
182         m.defMetric('ID', :long)
183         m.defMetric('local_address', :string)
184         m.defMetric('local_port', :long)
185         m.defMetric('foreign_address', :string)
186         m.defMetric('foreign_port', :long)
187     }
188     a.defMeasurement("TCP_Info"){ |m|
189         m.defMetric('ID', :long)
190         m.defMetric('Begin_interval', :float)
191         m.defMetric('End_interval', :float)
192         m.defMetric('Transfer', :float)
193         m.defMetric('Bandwidth', :float)
194     }
195     a.defMeasurement("UDP_Periodic_Info"){ |m|
196         m.defMetric('ID', :long)
197         m.defMetric('Begin_interval', :float)
198         m.defMetric('End_interval', :float)
199         m.defMetric('Transfer', :float)
200         m.defMetric('Bandwidth', :float)
201     }
202     a.defMeasurement("UDP_Rich_Info"){ |m|
203         m.defMetric('ID', :long)
204         m.defMetric('Begin_interval', :float)
205         m.defMetric('End_interval', :float)
206         m.defMetric('Transfer', :float)
207         m.defMetric('Bandwidth', :float)
208         m.defMetric('Jitter', :float)
209         m.defMetric('Packet_Lost', :long)
210         m.defMetric('Total_Packet', :long)
211         m.defMetric('PLR', :float)
212     }
213     a.defMeasurement("DCCP_Info"){ |m|
214         m.defMetric('ID', :long)
215         m.defMetric('Begin_interval', :float)
216         m.defMetric('End_interval', :float)
217         m.defMetric('Transfer', :float)
218         m.defMetric('Bandwidth', :float)
219         m.defMetric('Jitter', :float)
220         m.defMetric('Packet_Lost', :long)
221         m.defMetric('Total_Packet', :long)
222         m.defMetric('PLR', :float)
223     }
224     a.defMeasurement("TFRC_Info"){ |m|
225         m.defMetric('ID', :long)
226         m.defMetric('x', :float, "Sender rate in Bps")
227         m.defMetric('x_recv', :float, "(Remote) Receive rate in Bps")
228         m.defMetric('x_calc', :float, "Calculated rate in Bps")
229         m.defMetric('rtt', :float, "RTT in ms")
230         m.defMetric('p', :float)
231         m.defMetric('rto', :float)
232         m.defMetric('ipi', :float)
233     }
234     #a.omlPrefix = 'iperf2'
235 }
236 
237 defPrototype("SenderNode") { |proto|
238     proto.name = "SenderNode" 
239     proto.description = "An Iperf DCCP sender node" 
240 
241     proto.defProperty('destination', 'Name or IP address of the destination')
242 
243     proto.defProperty('bandwidth', 'Application sending rate, in bps', property.datarate)
244     proto.defProperty('len', 'Send buffer size', property.payloadsize)
245     proto.defProperty('time', 'Duration of the transmission', property.duration*4)
246     proto.defProperty('interval', 'Reporting interval', property.interval)
247 
248     proto.addApplication("iperf20", "iperf20") { |app|
249         app.setProperty('dccp', true)
250         app.setProperty('reportstyle', 'o')
251 
252         app.bindProperty('client', 'destination')
253         app.bindProperty('bandwidth', 'bandwidth')
254         app.bindProperty('len', 'len')
255         app.bindProperty('time', 'time')
256         app.bindProperty('interval', 'interval')
257 
258         app.measure('TFRC_Info', :interval => 1) { |mp|
259             mp.filter('x', 'avg')    # sender's rate
260             mp.filter('rtt', 'avg')    # RTT
261             mp.filter('p', 'avg')    # loss event rate
262         }
263     }
264 }
265 
266 # OMF is not aware of those filters (#407 & #408)
267 # The following should be added to
268 # /usr/share/omf-expctl-5.3/omf-expctl/oml/filter.rb
269 #
270 # FilterSpec.register(:sum) do |s|
271 #     s.addParam 'sum', 'FLOAT'
272 # end
273 # FilterSpec.register(:delta) do |s|
274 #     s.addParam 'delta', 'FLOAT'
275 # end
276 
277 defPrototype("ReceiverNode") { |proto|
278     proto.name = "ReceiverNode" 
279     proto.description = "A DCCP receiver node which measures QoE" 
280 
281     proto.addApplication("freezedccp_qoe_recv_app", "freezedccp_qoe_recv_app") { |app|
282         app.measure('dccp', :interval => 1) { |mp|
283             mp.filter('x_recv', 'avg')    # trsprate
284             mp.filter('rtt', 'avg')        # rtt
285             mp.filter('p', 'avg')        # loss event rate
286             mp.filter('freezestate', 'last') # frozen state
287         }
288         app.measure('stream', :interval => 1) { |mp|
289             mp.filter('id', 'delta')    # npkts-tot
290             mp.filter('npkts', 'delta')    # npkts
291             mp.filter('nloss', 'delta')    # nloss
292             mp.filter('size', 'sum')    # apprate
293         }
294         app.measure('video', :interval => 1) { |mp|
295             mp.filter('id', 'delta')    # nframes
296             mp.filter('psnr', 'avg')    # psnr
297         }
298     }
299 }
300 
301 # We define the Freeze nodes first so the application instance names don't
302 # get a _2 appended (see #413)
303 defGroup('FreezeSender', property.freezesrc) {|node|
304     node.prototype("SenderNode", {
305         'destination' => freezedstaddr,
306         'bandwidth' => "#{property.datarate}",
307         'len' => "#{property.payloadsize}",
308         'time' => property.duration*4,
309         'interval' => property.interval,
310     })
311     node.net.e0.ip = freezesrcaddr
312 }
313 defGroup('Sender', property.src) {|node|
314     node.prototype("SenderNode", {
315         'destination' => dstaddr,
316         'bandwidth' => "#{property.datarate}",
317         'len' => "#{property.payloadsize}",
318         'time' => property.duration*4,
319         'interval' => property.interval,
320     })
321     node.net.e0.ip = srcaddr
322 }
323 defGroup('FreezeReceiver', property.freezedst) {|node|
324     node.prototype("ReceiverNode")
325     node.net.e0.ip = freezedstaddr
326 }
327 defGroup('Receiver', property.dst) {|node|
328     node.prototype("ReceiverNode")
329     node.net.e0.ip = dstaddr
330 }
331 
332 defGroup('Actors', ["Sender","Receiver", "FreezeSender", "FreezeReceiver"]) 
333 defGroup('Senders', ["Sender", "FreezeSender"]) 
334 defGroup('Receivers', ["Receiver", "FreezeReceiver"]) 
335 
336 def cleanup () 
337     group("Actors").exec("killall -9 iperf freezedccp_qoe_recv; tc qdisc del dev #{property.interface} root; 
338                   tc qdisc del dev #{property.interface} ingress; iptables -F")
339 end
340 
341 def init(bw, delay)
342     group("Actors").exec("modprobe sch_htb; modprobe sch_netem")
343     group("Actors").exec("modprobe xt_dccp")
344     group("Actors").exec("sysctl -w net.dccp.default.seq_window=10000 net.dccp.default.rx_ccid=3 net.dccp.default.tx_ccid=3")
345 
346     cleanup
347 
348     group("Actors").exec("tc qdisc add dev #{property.interface} root handle 1 netem delay #{delay}s loss #{property.wlossrate}%; \
349                   tc qdisc add dev #{property.interface} handle ffff: ingress; \
350                   tc filter add dev #{property.interface} parent ffff: protocol ip prio 50 u32 match \
351                   ip src 0.0.0.0/0 police rate #{bw}Mbit burst #{[property.minbuffersize, bw * 2].max}k drop flowid 1")
352 
353     wait 10 
354 end
355 
356 # Message passing function has not been completely adapted in OMF-5.3
357 # The sendMessage method in
358 # /usr/share/omf-expctl-5.3/omf-expctl/node/rootNodeSetPath.rb (l. 216)
359 # should be changed to
360 #
361 # def sendMessage(name, *args)
362 #   @nodeSet.send(ECCommunicator.instance.create_message(:cmdtype => :STDIN,
363 #                                                        :appID => name,
364 #                                                        :value => "#{args.join(' ')}"))
365 # end
366 
367 def reconnect(bw, delay)
368     discoduration=2.5 + 2 * delay
369     info "Connecting to network (#{bw}Mbps/#{delay}s), handoff duration #{discoduration}" 
370     group("Actors").exec("tc qdisc change dev #{property.interface} root handle 1 netem delay #{delay}s loss #{property.wlossrate}%; \
371                   tc filter change dev #{property.interface} parent ffff: handle 800::800 protocol ip prio 50 u32 match \
372                   ip src 0.0.0.0/0 police rate #{bw}Mbit burst #{[property.minbuffersize, bw * 2].max}k drop flowid 1; \
373                   sleep #{discoduration}s; \
374                   iptables -D OUTPUT -o #{property.interface} -j DROP; \
375                   iptables -D INPUT -i #{property.interface} -j DROP")
376     group("FreezeReceiver").sendMessage("freezedccp_qoe_recv_app", "unfreeze")
377 end
378 
379 def disconnect(rtt)
380     group("FreezeReceiver").sendMessage("freezedccp_qoe_recv_app", "freeze")
381     info "Handing off" 
382     group("Actors").exec("sleep #{rtt}s; \
383                   iptables -A INPUT -i #{property.interface} -j DROP; \
384                   iptables -A OUTPUT -o #{property.interface} -j DROP")
385 end
386 
387 onEvent(:ALL_UP_AND_INSTALLED) { |node|
388     init(scenario[0]['bw'], scenario[0]['delay'] + property.coredelay)
389     first = true
390 
391     info "Starting receivers..."  
392     group("Receivers").startApplications
393     wait 10
394     info "Starting senders..."  
395     group("Senders").startApplications
396 
397     scenario.each { |step|
398         delay = step['delay'] + property.coredelay
399         rtt = 2 * delay
400 
401         if first != true
402             reconnect(step['bw'], delay)
403         end
404 
405         # Freeze one RTT before disconnection,
406         # the remaining RTT is accounted for in disconnect()
407         wait step['duration'] - rtt
408 
409         disconnect(rtt)
410         first = false
411     }
412 
413     cleanup
414 
415     Experiment.done
416 }
  • Lines 31--60: define the configurable parameters and default values such as nodes, duration or link capacities;
  • Lines 64--67: derive IP addresses from the selected nodes' ID;
  • Lines 69--75: define the scenario “phases” as a Ruby array for later iteration;
  • Lines 77--149: add a tab to the EC's dashboard with graphs showing various metrics measured on the testbed nodes;
  • Lines 151--235: (re-(re-))define the Iperf application;
  • Lines 237-299: define sender and receiver nodes prototypes;
  • Lines 301--332: instantiate those prototype for the selected nodes;
  • Lines 332-334: define handy groups of nodes for easier manipulation;
  • Lines 336--385: helper functions to be used during the experiment;
  • Lines 387--416: main experimental loop, iterating over the scenario “phases” and emulating both network handoffs and network conditiens for each.

scenario.png - A user viewing a video stream on their mobile device goes out for a coffee then comes back home. (24.7 kB) Olivier Mehani, 08/09/2010 04:07 pm

experiment.png - OMF experiment using the Norbit testbed (35.4 kB) Olivier Mehani, 08/09/2010 04:07 pm

2010mehani_freezedccp_poster.pdf - Demonstration poster (175.8 kB) Olivier Mehani, 08/09/2010 04:23 pm

iperf-2.0.2-dccp-oml.tar.bz2 - Iperf 2.02 with DCCP and OML support (282.1 kB) Olivier Mehani, 13/10/2010 04:39 pm

freezedccp_qoe_recv.tar.bz2 - Freeze-DCCP receiver computing the PSNR of the received stream (6.4 kB) Olivier Mehani, 13/10/2010 05:01 pm

freezedccp-qoe.rb - OEDL script driving the experiment (16.1 kB) Olivier Mehani, 13/10/2010 05:01 pm

graph.png - PSNR graph at the end of the experiment (64.2 kB) Olivier Mehani, 13/10/2010 06:00 pm

dash.png - Experiment dashboard (76.7 kB) Olivier Mehani, 13/10/2010 06:02 pm

log.png - Logs of the current experiment (128.9 kB) Olivier Mehani, 13/10/2010 06:02 pm

state.png - XML representation of the current state of the experiment (110 kB) Olivier Mehani, 13/10/2010 06:02 pm

scripts.png - Experimental scripts currently executing (155 kB) Olivier Mehani, 13/10/2010 06:02 pm

scripts2.png - Experimental scripts currently executing: receiver application description (140.4 kB) Olivier Mehani, 13/10/2010 06:02 pm