All Classes Namespaces Files Functions Pages
executescenario.tcl
Go to the documentation of this file.
1 ##
2 # @brief Basic namespace for all Excentis Tcl extensions
3 #
4 namespace eval excentis {
5 
6 ##
7 # @brief This namespace holds all ByteBlower-related Tcl extensions, including the ByteBlower higher-layer Tcl API.
8 #
9 # These procedures are developed for higher-level usage of the ByteBlower API.
10 # They are mainly used to simplify running specific Test Scenarios similar to
11 # scenarios you know from the ByteBlower GUI.
12 #
13 namespace eval ByteBlower {
14 
15 ## \file
16 #
17 # @brief Core module that <b>executes higher-layer scenario configurations</b> and <b>returns the scenario results</b> requested through that configuration.
18 #
19 # This module and its two main methods <tt>ExecuteScenario</tt> and <tt>ExecuteScenarioRT</tt> form the core of the ByteBlower higher-layer (HL) Tcl API:
20 # <ul>
21 # <li>Scenario configurations, which is nothing more then a list of traffic flow configurations, are passed as input to these methods.</li>
22 # <li>They are subsequently parsed and mapped to objects in the lower-layer API. This happens transparent to the user.</li>
23 # <li>The scenario is then immediately executed (i.e. all traffic flows are started).</li>
24 # <li>After the scenario is finished, a set of result values are returned. The structure of the result is based on the provided scenario configuration.</li>
25 # <li>Finally, all objects created before and during execution are destroyed, so the ByteBlower server is in the same state as before.</li>
26 # </ul>
27 #
28 # The real-time variant makes sure a callback method containing intermediate results is executed at a fixed time interval. This method can be implemented
29 # by the calling script to handle real-time results as desired.
30 #
31 # Most other modules in the ByteBlowerHL API are built as wrappers around these calls, adding extra logic or predefining some of settings in the scenario configuration.
32 #
33 # @copyright Excentis nv - www.excentis.com
34 #
35 
36 package require excentis_basic
37 
38 set ::ByteBlowerExecuteScenarioResult ""
39 set ::ByteBlowerExecuteScenarioDone 0
40 set ::ByteBlowerExecuteScenarioWait 1
41 
42 ##
43 # @brief Method to retrieve the objects to pass at Ports.Start and WirelessEndpoints.Start
44 #
45 proc x.GetDevicesToStart { txPorts rxPorts } {
46  set portsToStart [ list ]
47  set wepsToStart [ list ]
48  foreach txPort $txPorts {
49  switch -- [ $txPort Get _ClassName ] {
50  "ByteBlowerPort" {
51  if { [ lsearch $portsToStart $txPort ] == -1 } {
52  lappend portsToStart $txPort
53  }
54  }
55  "WirelessEndpoint" {
56  if { [ lsearch $wepsToStart $txPort ] == -1 } {
57  lappend wepsToStart $txPort
58  }
59  }
60 
61  }
62  }
63 
64  foreach rxPort $rxPorts {
65  switch -- [ $rxPort Get _ClassName ] {
66  "WirelessEndpoint" {
67  if { [ lsearch $wepsToStart $rxPort ] == -1 } {
68  lappend wepsToStart $rxPort
69  }
70  }
71 
72  }
73  }
74  return [ list $portsToStart $wepsToStart ]
75 }
76 
77 ##
78 # @brief Method to start the wireless endpoints.
79 # @return nothing
80 #
81 proc x.StartWirelessEndpoints { wirelessEndpoints } {
82  foreach wirelessEndpoint $wirelessEndpoints {
83  # Claim the devices, it is ours!
84  $wirelessEndpoint Lock 1
85 
86  # Clear previously stored results
87  $wirelessEndpoint Result.Clear
88  }
89 
90  set bb [ ByteBlower Instance.Get ]
91  eval $bb WirelessEndpoints.Prepare.Async $wirelessEndpoints
92  eval $bb WirelessEndpoints.Prepare $wirelessEndpoints
93 
94  eval $bb WirelessEndpoints.StartAndWait $wirelessEndpoints
95 
96 }
97 
98 proc x.StopWirelessEndpoints { wirelessEndpoints } {
99 
100 }
101 
102 proc x.WaitForWirelessEndpoints { wirelessEndpoints } {
103 
104  set check_interval 1000;#ms
105 
106  foreach endpoint $wirelessEndpoints {
107  set ::wep_hb($endpoint) [ $endpoint Heartbeat.Timestamp.Last.Get ]
108  set hb_interval [ expr int(double([$endpoint Heartbeat.Interval.Get ]) / 1000000) ]
109  if { ${hb_interval} < $check_interval} {
110  set check_interval $hb_interval
111  }
112  }
113 
114  set check_interval [ expr $check_interval / 2 ]
115 
116  while 1 {
117  set ::hb_check_after 0
118  after $check_interval "set ::hb_check_after 1"
119  vwait ::hb_check_after
120  unset ::hb_check_after
121 
122  set nrOk 0
123  foreach endpoint $wirelessEndpoints {
124  set cur_heartbeat [ $endpoint Heartbeat.Timestamp.Last.Get ]
125  if { $cur_heartbeat > $::wep_hb($endpoint)} {
126  incr nrOk
127  }
128  }
129  if { $nrOk == [ llength $wirelessEndpoints ]} {
130  array unset ::wep_hb
131  return 1
132  }
133  }
134 
135  array unset ::wep_hb
136  return 0
137 
138 }
139 
140 ##
141 # @brief Central method of the higher-layer API which executes declarative scenario configurations and returns the scenario results.
142 #
143 # This method sets up the scenario flows, runs them and collects information about them. After executing the scenario all created
144 # objects are removed from the interacting @apiref{ByteBlowerPort} objects, so thay return to the same pre-scenario state.
145 #
146 # This method is synchronous and will return the global scenario results once it is finished. To handle intermediate results, there is
147 # a similar method @apiref{excentis::ByteBlower::ExecuteScenarioRT,ExecuteScenarioRT}.
148 #
149 # @note
150 # At this point, only frame blasting scenarios can be run with the higher-layer API.
151 #
152 # @param scenarioConfig
153 # The declarative scenario configuration. See the @ref TclApiHLOverview "higher-layer API overview" for more information.
154 #
155 # @param args
156 # Scenario-level option list in the form of a list of key-value pairs:
157 # @dlist
158 # @dlitem{-extended, Flag that changes default types of various scenario components to return extended results. It may be overridden by the specific component characteristics.
159 # @defaultvalue{0}
160 # }
161 # @dlitem{-finaltimetowait, Sets the time in ms to wait after the last flow is finished. This allows packets which are in transit to arrive at their destination.
162 # @defaultvalue{5000 (5s)}
163 # }
164 # @dlitem{-scoutingfinaltimetowait, Sets the time in ms to wait after the last scouting frames is transmitted. This allows packets which are in transit to prepare the network path and arrive at their destination.
165 # @defaultvalue{1000 (1s)}
166 # }
167 # @enddlist
168 #
169 # @return
170 # The result data structure. See the @ref TclApiHLOverview "higher-layer API overview" for more information.
171 #
172 proc ExecuteScenario { scenarioConfig args } {
173  set scenarioResultList [ list ]
174 
175  #--
176  #-- PARSE ARGS
177  #--
178  set extended 0
179  set timetowait 5000
180  set scoutingTimetowait 1000
181 
182  set walker 0
183  for { set walker 0} { $walker < [ llength $args ]} { incr walker} {
184  set arg [ lindex $args $walker ]
185  switch -- $arg {
186  -extended {
187  set extended 1
188  }
189  -finaltimetowait {
190  incr walker
191  set timetowait [ lindex $args $walker ]
192  }
193  -scoutingfinaltimetowait {
194  incr walker
195  set scoutingTimetowait [ lindex $args $walker ]
196  }
197  }
198  }
199 
200  #--
201  #-- PREPARE
202  #--
203  set temp [ x.ExecuteScenario.ScenarioConfig.Parse $scenarioConfig $extended ]
204  set txPorts [ lindex $temp 0 ]
205  set rxPorts [ lindex $temp 1 ]
206  set duration [ lindex $temp 2 ]
207  set scenarioObjectList [ lindex $temp 3 ]
208  set scenarioPrepareObjectList [ lindex $temp 4 ]
209 
210  if { [ catch {
211  x.ExecuteScenario.PrepareNetwork $scenarioPrepareObjectList $scoutingTimetowait
212  } dummy ]} {
213  # --- Cleanup all created objects (using 'catching' version)
214  x.ExecuteScenario.Cleanup $scenarioPrepareObjectList
215  x.ExecuteScenario.Error $scenarioObjectList $dummy
216  }
217 
218  #--
219  #-- CLEANUP of prepare objects
220  #--
221  x.ExecuteScenario.Cleanup $scenarioPrepareObjectList
222 
223  switch -exact -- [ catch {
224  #--
225  #-- INIT RX SIDE
226  #--
227  foreach flowObjectList $scenarioObjectList {
228  foreach {item value} $flowObjectList {
229  if { [ string equal $item "-rx" ] && ![ string equal $value "NA" ] } {
230  # If the rx side has a capture active, start is.
231  # If it has another trigger, reset it.
232  set description [ $value Description.Get ]
233  if { [ regexp {capture} $description ] } {
234  $value Start
235  } else {
236  $value Result.Clear
237  }
238  }
239  }
240  }
241 
242  #--
243  #-- START SCENARIO
244  #--
245  set stop 0
246 
247 
248  # Select byteblower ports to start, select wireless endpoints to start
249  foreach { portsToStart wepsToStart } [ x.GetDevicesToStart $txPorts $rxPorts ] { break; }
250  x.StartWirelessEndpoints $wepsToStart
251 
252 
253  # Start traffic on tx ports
254  eval ByteBlower Ports.Start $portsToStart
255  # Calculate the duration
256  set duration [expr int(ceil($duration)) ]
257  # Recalculate duration ( duration - sum (all inital times to wait) )
258  set duration [expr $duration - [ x.ExecuteScenario.CheckTxErrors $scenarioObjectList $txPorts ] ]
259  if { $::ByteBlowerExecuteScenarioWait } {
260  # Wait for traffic to stop
261  after $duration set stop 1
262  vwait stop
263  unset stop
264 
265  #--
266  #-- STOP SCENARIO + GET RESULTS
267  #--
268  eval ByteBlower Ports.Stop $portsToStart
269 
270  #
271  # -- Wait for timetowait
272  #
273  if { $timetowait != 0 } {
274  set stop 0
275  after $timetowait set stop 1
276  vwait stop
277  unset stop
278  }
279  x.StopWirelessEndpoints $wepsToStart
280  x.WaitForWirelessEndpoints $wepsToStart
281 
282 
283  set scenarioResultList [ x.ExecuteScenario.Results.Get $scenarioObjectList $extended ]
284  } else {
285  set command [ list ::excentis::ByteBlower::x.ExecuteScenario.Finished [ list $txPorts] [ list $scenarioObjectList ] [ list $extended ] ]
286  eval after $duration $command
287  return
288  }
289  } dummy ] {
290  # TCL_ERROR
291  1 {
292  # --- Cleanup all created objects (using 'catching' version)
293  x.ExecuteScenario.Error $scenarioObjectList $dummy
294  }
295  # TCL_RETURN
296  2 {
297  return $dummy
298  }
299  default {
300  #--
301  #-- CLEANUP + RETURN RESULTS
302  #--
303  x.ExecuteScenario.Cleanup $scenarioObjectList
304  return $scenarioResultList
305  }
306  }
307 }
308 
309 ##
310 # @brief Central method of the higher-layer API which executes declarative scenario configurations and returns the scenario results.
311 #
312 # This method sets up the scenario flows, runs them and collects information about them. After executing the scenario all created
313 # objects are removed from the interacting @apiref{ByteBlowerPort} objects, so thay return to the same pre-scenario state.
314 #
315 # The method is synchronous and will return the global scenario results once it has finished. However, it will also periodically
316 # execute a callback method containing the intermediate results. If this real-time result functionality is not required, a similar method
317 # @apiref{excentis::ByteBlower::ExecuteScenario,ExecuteScenario} may also be used.
318 #
319 # @note
320 # At this point, only frame blasting scenarios can be run with the higher-layer API.
321 #
322 # @param scenarioConfig
323 # The declarative scenario configuration. See the @ref TclApiHLOverview "higher-layer API overview" for more information.
324 #
325 # @param args
326 # Scenario-level option list in the form of a list of key-value pairs:
327 # @dlist
328 # @dlitem{-extended,Flag that changes default types of various scenario components to return extended results. It may be overridden by the specific component characteristics.
329 # @defaultvalue{0}
330 # }
331 # @dlitem{-finaltimetowait,Sets the time in ms to wait after the last flow is finished. This allows packets which are in transit to arrive at their destination.
332 # @defaultvalue{5000 (5s)}
333 # }
334 # @dlitem{-scoutingfinaltimetowait, Sets the time in ms to wait after the last scouting frames is transmitted. This allows packets which are in transit to prepare the network path and arrive at their destination.
335 # @defaultvalue{1000 (1s)}
336 # }
337 # @dlitem{-updateinterval,Sets the time in ms between result updates. After every update interval the callback procedure is called.
338 # @defaultvalue{1000 (1s)}
339 # }
340 # @dlitem{-callback,Sets the callback method called at every update interval by specifying the method name. The procedure itself is defined by the calling script and
341 # has a single parameter @command{scenarioResultList} which contains the interval results.
342 # @defaultvalue{"DefaultCallback"}
343 # }
344 # @enddlist
345 #
346 # @return
347 # The result data structure. See the @ref TclApiHLOverview "higher-layer API overview" for more information.
348 # If an exception happens during the execution of the scenario, this exception object will be returned. The method Message.Get on this exception object will return the error-message.
349 # @apiexample
350 # @apisnippet{source IPv4.run.tcl}
351 # @apisnippetretval{ByteBlowerObject_1530880908_2}
352 # @apisnippet{% ByteBlowerObject_1530880908_2 Message.Get}
353 # @apisnippetretval{-server localhost Failed to connect with the ByteBlower server: byteblower-tp-p860.lab.excentis.com:9002}
354 # @endapiexample
355 #
356 proc ExecuteScenarioRT { scenarioConfig args } {
357  set scenarioResultList [ list ]
358 
359  #--
360  #-- PARSE ARGS
361  #--
362  set extended 0
363  set timetowait 5000
364  set scoutingTimetowait 1000
365  set updateinterval 1000
366  set callback 0
367 
368  set walker 0
369  for { set walker 0} { $walker < [ llength $args ]} { incr walker} {
370  set arg [ lindex $args $walker ]
371  switch -- $arg {
372  -extended {
373  set extended 1
374  }
375  -finaltimetowait {
376  incr walker
377  set timetowait [lindex $args $walker ]
378  }
379  -scoutingfinaltimetowait {
380  incr walker
381  set scoutingTimetowait [ lindex $args $walker ]
382  }
383  -updateinterval {
384  incr walker
385  set updateinterval [lindex $args $walker ]
386  }
387  -callback {
388  incr walker
389  set callback 1
390  set callbackMethod [ lindex $args $walker ]
391  }
392  }
393  }
394 
395  if {$callback == 0} {
396  # Apply default callback method
397  set callback 1
398  set callbackMethod "DefaultCallback"
399  }
400 
401  #--
402  #-- PREPARE
403  #--
404  set temp [ x.ExecuteScenario.ScenarioConfig.Parse $scenarioConfig $extended]
405  set txPorts [ lindex $temp 0 ]
406  set rxPorts [ lindex $temp 1 ]
407  set duration [ lindex $temp 2 ]
408  set scenarioObjectList [ lindex $temp 3 ]
409  set scenarioPrepareObjectList [ lindex $temp 4 ]
410 
411  if { [ catch {
412  x.ExecuteScenario.PrepareNetwork $scenarioPrepareObjectList $scoutingTimetowait
413  } dummy ]} {
414  # --- Cleanup all created objects (using 'catching' version)
415  x.ExecuteScenario.Cleanup $scenarioPrepareObjectList
416  x.ExecuteScenario.Error $scenarioObjectList $dummy
417  }
418 
419  #--
420  #-- CLEANUP of prepare objects
421  #--
422  x.ExecuteScenario.Cleanup $scenarioPrepareObjectList
423 
424  if { [ catch {
425  #--
426  #-- INIT RX SIDE
427  #--
428  foreach flowObjectList $scenarioObjectList {
429  foreach {item value} $flowObjectList {
430  if { [ string equal $item "-rx" ] && ![ string equal $value "NA" ] } {
431  # If the rx side has a capture active, start it.
432  # If it has another trigger, reset it.
433  set description [ $value Description.Get ]
434  if { [ regexp {capture} $description ] } {
435  $value Start
436  } else {
437  $value Result.Clear
438  }
439  }
440  }
441  }
442 
443  #--
444  #-- START SCENARIO
445  #--
446  set poll 0
447  set ::stop 0
448 
449  # Select byteblower ports to start, select wireless endpoints to start
450 
451  foreach { portsToStart wepsToStart } [ x.GetDevicesToStart $txPorts $rxPorts ] { break; }
452  x.StartWirelessEndpoints $wepsToStart
453 
454 
455  # Start traffic on tx ports
456  eval ByteBlower Ports.Start $portsToStart
457  # Calculate the duration
458  set duration [expr int(ceil($duration)) + $timetowait ]
459  # Wait for traffic to stop
460  after $duration "set ::stop 1"
461  set timestamp 0
462  while { $::stop != 1 } {
463  update
464  after $updateinterval set poll 1
465  vwait poll
466  set poll 0
467  # We just want a result of one flow, so we don't kill any ByteBlower server.
468  # Now, we will log
469  set timestamp [ x.ExecuteScenario.Timestamp.Next.Get $scenarioObjectList $timestamp $updateinterval ]
470  set scenarioTempResultList [ x.ExecuteScenario.InterRunResults.Get $scenarioObjectList $txPorts $extended $timestamp ]
471 
472 
473  if {$callback == 1} {
474  eval $callbackMethod {$scenarioTempResultList}
475  }
476  update
477  }
478 
479  #--
480  #-- STOP SCENARIO + GET RESULTS
481  #--
482  eval ByteBlower Ports.Stop $portsToStart
483 
484  x.StopWirelessEndpoints $wepsToStart
485  x.WaitForWirelessEndpoints $wepsToStart
486  set scenarioResultList [ x.ExecuteScenario.Results.Get $scenarioObjectList $extended ]
487  } dummy ]} {
488  # --- Cleanup all created objects (using 'catching' version)
489  #puts $::errorInfo
490  x.ExecuteScenario.Error $scenarioObjectList $dummy
491  }
492 
493  #--
494  #-- CLEANUP + RETURN RESULTS
495  #--
496  x.ExecuteScenario.Cleanup $scenarioObjectList
497  return $scenarioResultList
498 }
499 
500 ##
501 # @brief Default callback method for processing the real-time results that simply prints result values on every update interval.
502 #
503 # @param scenarioResultList
504 # The intermediate scenario result. It has the same format as the final scenario result, which is based on the
505 # scenario configuration.
506 proc DefaultCallback { scenarioResultList } {
507  set flowid 1
508  foreach flowResultList $scenarioResultList {
509  set txResult [ lindex [ lindex $flowResultList 1 ] 1 ]
510  set rxResult [ lindex [ lindex $flowResultList 3 ] 1 ]
511  puts "[clock format [clock seconds] -format {%Y-%m-%d %H:%M:%S}]\t$flowid\t$txResult\t$rxResult"
512  incr flowid 1
513  }
514 }
515 
516 proc x.ExecuteScenario.PrepareNetwork { scenarioPrepareObjectList scoutingTimetowait } {
517 #
518 # This method is called when the ExecuteScenario is about to start the
519 # Flow. When scouting frames are configured, they will be sent here.
520 #
521 # @param scenarioPrepareObjectList
522 # The scenario prepare object list. The scouting streams of all
523 # the objects in this list will be started.
524 #
525 
526  # Only wait when we actually have scouting frames to send
527  set doTimetowait 0
528 
529  #--
530  #-- TX SCOUTING STREAMS
531  #--
532  foreach flowPrepareObjectList $scenarioPrepareObjectList {
533  foreach { item value } $flowPrepareObjectList {
534  if { [ string equal $item "-scouting_tx" ]} {
535  foreach { scoutingStream scoutingDuration } $value { break}
536 
537  # Calculate the duration
538  set scoutingDuration [ expr int(ceil($scoutingDuration)) ]
539  #puts "Transmitting scouting frame for ${scoutingDuration}\[ms\]"
540 
541  $scoutingStream Start
542 
543  set ::scouting_stop 0
544  after $scoutingDuration { set ::scouting_stop 1 }
545  vwait ::scouting_stop
546  unset ::scouting_stop
547 
548  $scoutingStream Stop
549 
550  catch { unset scoutingStream } dummy
551  catch { unset scoutingDuration } dummy
552 
553  set doTimetowait $scoutingTimetowait
554  } else {
555  error "ByteBlowerHL error: Unsupported scenario prepare item '$item'"
556  }
557  }
558  }
559 
560  #
561  # -- Wait for scoutingTimetowait
562  #
563  if { $doTimetowait != 0} {
564  set ::scouting_stop 0
565  after $doTimetowait { set ::scouting_stop 1 }
566  vwait ::scouting_stop
567  unset ::scouting_stop
568  }
569 
570 }
571 
572 proc x.ExecuteScenario.Finished { txPorts scenarioObjectList extended } {
573 #
574 # This method is just called when a scenario is finished, and the user didn't want to wait
575 # for the results. This method will increment the variable ::ByteBlowerExcecuteScenarioDone
576 # and will store the result in ::ByteBlowerExecuteScenarioResult
577 #
578 # @param txPorts
579 # The list of transmitting ports, to match a failing stream to its
580 # source port.
581 #
582 # @param scenarioObjectList
583 # The scenario object list. The counters of all the objects in this
584 # list will be parsed and returned to the callback method.
585 #
586 # @param extended
587 # Boolean defines extended results are requested or not. Note this can
588 # be overridden using specific Tx and Rx parameters.
589 #
590 
591  incr ::ByteBlowerExecuteScenarioDone
592  puts "TxPorts: $txPorts"
593  puts "ObjectList: $scenarioObjectList"
594  puts "Extended: $extended"
595  eval ByteBlower Ports.Stop $txPorts
596  set ::ByteBlowerExecuteScenarioResult [ x.ExecuteScenario.Results.Get $scenarioObjectList $extended ]
597  x.ExecuteScenario.Cleanup $scenarioObjectList
598 }
599 
600 proc x.ExecuteScenario.GetWirelessEndpoints { scenarioObjectList } {
601  set wirelessEndpoints [ list ]
602 
603  foreach flow $scenarioObjectList {
604  foreach { key value } $flow {
605  switch -- $key {
606  "-tx" -
607  "-rx" {
608  if { [ TOOP Info -isobject $value ] } {
609  switch -- [ $value Get _ClassName ] {
610  "Tx.Stream.Mobile" -
611  "Rx.Trigger.Basic.Mobile" -
612  "Rx.Latency.Basic.Mobile" {
613  set parent [ $value Parent.Get ]
614  if { [ $parent Info -implements "WirelessEndpoint" ] } {
615  if { [ lsearch wirelessEndpoints $parent ] == -1 } {
616  lappend wirelessEndpoints $parent
617  }
618  }
619  }
620  }
621  }
622  }
623  }
624  }
625  }
626 
627  return $wirelessEndpoints
628 }
629 
630 proc x.ExecuteScenario.ScenarioConfig.Parse { scenarioConfig extended } {
631 #
632 # This method will just parse the configurations of the flows and create the
633 # various TX and RX flow objects, streams and receivers respectively. It also
634 # calculated the duration of the scenario, based on the duration of the flows in
635 # it.
636 #
637 # @param scenarioConfig
638 # Flow list as described in the Excecute scenario. This means it is a
639 # list of flow configurations. A flow configuration is itself a list
640 # of a Tx configuration and zero, one or more Rx configurations. Such
641 # Tx and Rx configurations are themself lists of name-value pairs.
642 #
643 # @param extended
644 # Boolean defines extended results are requested or not. Note this can
645 # be overridden using specific Tx and Rx parameters.
646 #
647 # @return
648 # List containing port and flow objects (oid's) and other relevant
649 # information that define.
650 # @list
651 # List of four elements: (1) a list of all Tx ports that will
652 # transmit flow traffic, (2) a list of all Rx ports that will
653 # receive flow traffic, (3) the duration of the test (in ns).
654 # The last element is (4) a list containing one list of flow
655 # objects for each flow. These flow objects define the flow
656 # data and consist of the Tx stream object(s) and the Rx
657 # receiver object(s).
658 #
659 
660  set txPorts [ list ]
661  set rxPorts [ list ]
662  set ::excentis::basic::rxPcapFileNames [ list ]
663  set scenarioObjectList [ list ]
664  set duration 0; #duration of longest flow in nanoseconds
665  set scenarioPrepareObjectList [ list ]
666 
667  if { [ catch {
668  foreach flowConfig $scenarioConfig {
669  set flowObjectList [ list ]
670  set flowPrepareObjectList [ list ]
671  # parse flow parameters
672  foreach {item value} $flowConfig {
673  switch -- $item {
674  -tx {
675  set txParamList $value
676  # parse tx parameters and configure tx port
677  foreach { txPort stream streamDuration scoutingStreamList } [ x.ExecuteScenario.TxParam.Parse $txParamList ] break
678  lappend flowObjectList "-tx" $stream
679  foreach scoutingStreamInfo $scoutingStreamList {
680  lappend flowPrepareObjectList "-scouting_tx" $scoutingStreamInfo
681  }
682  if { $streamDuration > $duration } {
683  set duration $streamDuration
684  }
685  # keep record of unique tx ports
686  if { [lsearch $txPorts $txPort] == -1 } {
687  lappend txPorts $txPort
688  }
689  }
690  -rx {
691  set rxParamList $value
692  # parse rx parameters and configure rx ports
693  foreach { rxPort trigger } [ x.ExecuteScenario.RxParam.Parse $rxParamList $extended ] break
694  lappend flowObjectList "-rx" $trigger
695  # keep record of unique rx ports
696  if { [lsearch $rxPorts $rxPort] == -1 } {
697  lappend rxPorts $rxPort
698  }
699  }
700  default {
701  puts "ByteBlowerHL warning: Invalid flow parameter ignored: $item"
702  }
703  }
704  }; # end parse flow configuration
705  lappend scenarioObjectList $flowObjectList
706  lappend scenarioPrepareObjectList $flowPrepareObjectList
707  }; # end parse scenario configuration
708  } dummy ]} {
709  # --- Cleanup all created objects (using 'catching' version)
710  x.ExecuteScenario.Error $scenarioObjectList $dummy
711  }
712  return [ list $txPorts $rxPorts $duration $scenarioObjectList $scenarioPrepareObjectList ]
713 }
714 
715 proc x.ExecuteScenario.CheckTxErrors { scenarioObjectList txPorts } {
716 #
717 # This procedure assesses the running scenario untill all the TX streams are
718 # running smoothly. If a TX stream could not be started, an error is thrown.
719 #
720 # @param scenarioObjectList
721 # The scenario object list. The counters of all the objects in this
722 # list will be parsed and returned to the callback method.
723 #
724 # @param txPorts
725 # The list of transmitting ports, to match a failing stream to its
726 # source port.
727 #
728 # @return
729 # The amount of time passed until all TX streams are correctly
730 # started. This is based on the start time of the streams. The
731 # scenario takes this passed time in account when measuring how long
732 # the scenario has to run further.
733 #
734 # @exception @varitem{tcl_error}
735 # If a TX stream could not be started, an error is thrown.
736 #
737 
738  set txList [ list ]
739 
740  #--- List all the tx flows
741  foreach flowObjectList $scenarioObjectList {
742  foreach {item value} $flowObjectList {
743  if {$item == "-tx"} {
744  set flow [ list $value [expr int([ $value InitialTimeToWait.Get ] / 1e6)] ]
745  lappend txList $flow
746  }
747  }
748  }
749 
750  #--- Sort them by InitailTimeToWait
751  set txList [ lsort -integer -index 1 $txList ]
752 
753  #--- Timeshift of 500ms
754  set timeWaited 0
755  after 500
756 
757  foreach txInfo $txList {
758  set flowStream [ lindex $txInfo 0 ]
759  set InitialTimeToWait [ lindex $txInfo 1 ]
760 
761  #--- Wait until this flow has started
762  set stop 0
763  set timer [ expr $InitialTimeToWait - $timeWaited ]
764  after [ expr $timer + 500 ] set stop 1
765  vwait stop
766 
767  #--- Check error
768  set txError "None"
769  if { [ $flowStream Info -implements Tx.Stream ]} {
770  set txError [ [ $flowStream Status.Get ] ErrorStatus.Get ]
771  }
772  if { $txError != "None"} {
773  # FOUND an ERROR on a flow
774  foreach txPort $txPorts {
775  foreach txPortStream [ $txPort Tx.Stream.Get ] {
776  if { $txPortStream == $flowStream} {
777  set descr [lindex [ split [ $txPort Description.Get ] "\n" ] 0 ]
778  error "ByteBlowerHL error: $txError on $descr"
779  }
780  }
781  }
782  }
783 
784 
785  #--- Update the total time spent up until this flow
786  set timeWaited [ expr $timeWaited + $timer ]
787  }
788 
789  #--- Return total time spent in this check method
790  return $timeWaited
791 }
792 
793 proc x.ExecuteScenario.Results.Get { scenarioObjectList extended } {
794 #
795 # This procedure gets the counter values for all the counter objects in the
796 # scenario and formats them according to the scenario configuration.
797 #
798 # @param scenarioObjectList
799 # The scenario object list. The counters of all the objects in this
800 # list will be parsed and returned as the scenario result.
801 #
802 # @param extended
803 # Boolean defines extended results are requested or not. Note it is
804 # used only for the TX part here. RX parts looked at extended value
805 # when they were parsed.
806 # @return
807 # The scenario result. Its structure is based on the scenario config.
808 #
809 
810  set wirelessEndpoints [ x.ExecuteScenario.GetWirelessEndpoints $scenarioObjectList ]
811  foreach wirelessEndpoint $wirelessEndpoints {
812  $wirelessEndpoint Result.Get
813  }
814 
815  # Stop captures on rx ports and get counters
816  set scenarioResultList [ list ]
817  set captureCounter 0
818  foreach flowObjectList $scenarioObjectList {
819  set flowResultList [ list ]
820  # Fill flow result list
821  foreach {item value} $flowObjectList {
822  switch -exact -- $item {
823  -rx {
824  if { $value != "NA"} {
825  # If the rx side has a capture active, start it.
826  # If it has another trigger, reset it.
827  if { [$value Info -implements Rx.Capture.Basic ] } {
828  $value Stop
829  lappend flowResultList "-rx" [$value Frames.Get]
830  # If we want a pcap file, we should perform this here.
831  set fileName [ lindex $::excentis::basic::rxPcapFileNames $captureCounter ]
832  if { $fileName != "" } {
833  $value Pcap.Save $fileName
834  }
835  incr captureCounter 1
836  } elseif { [$value Info -implements Rx.Trigger.SizeDistribution ] } {
837  #SizeDistribution triggers do not support Result yet!
838  set result [ $value Result.Get ]
839  set counters [ list ]
840  lappend counters NrOfFrames [ $result PacketCount.Get ]
841  lappend counters NrOfOctets [ $result ByteCount.Get ]
842  lappend counters NrOfUndersized [ $result PacketCount.BelowMinimum.Get ]
843  lappend counters NrOfOversized [ $result PacketCount.AboveMaximum.Get]
844  lappend flowResultList "-rx" $counters
845  } elseif { [$value Info -implements Rx.Latency.Basic ] || \
846  [$value Info -implements Rx.Latency.Basic.Mobile ] } {
847  set result [ $value Result.Get ]
848  $result Refresh
849 
850  set packetcount [$result PacketCount.Get]
851  set latencyminimum 0
852  set latencymaximum 0
853  set latencyaverage 0
854  set jitter 0
855  if { $packetcount != 0 } {
856  set latencyminimum [$result Latency.Minimum.Get]
857  set latencymaximum [$result Latency.Maximum.Get]
858  set latencyaverage [$result Latency.Average.Get]
859  set jitter [ $result Jitter.Get ]
860  }
861 
862  lappend flowResultList "-rx" [ list \
863  NrOfFrames $packetcount \
864  MinLatency $latencyminimum \
865  AvgLatency $latencyaverage \
866  MaxLatency $latencymaximum \
867  Jitter $jitter \
868  ]
869  $result Destructor
870  } elseif { [$value Info -implements Rx.OutOfSequence.Basic ] } {
871  set result [ $value Result.Get ]
872  $result Refresh
873  set rxFrames [ $result PacketCount.Get ]
874 
875  set rxOoS 0
876  if { $rxFrames != 0 } {
877  set rxOoS [ $result PacketCount.OutOfSequence.Get ]
878  }
879 
880  lappend flowResultList "-rx" [ list \
881  FramesOutOfSequence $rxOoS \
882  NrOfFrames $rxFrames \
883  ]
884  $result Destructor
885  } else {
886  set result [$value Result.Get]
887  $result Refresh
888  lappend flowResultList "-rx" [ list \
889  NrOfFrames [ $result PacketCount.Get ] \
890  NrOfOctets [ $result ByteCount.Get ] \
891  ]
892  $result Destructor
893  }
894  } else {
895  lappend flowResultList "-rx" "NA"
896  }
897  }
898  -tx {
899  if { $extended == 0 } {
900  set result [$value Result.Get]
901  $result Refresh
902  lappend flowResultList "-tx" [ list NrOfFramesSent [ $result PacketCount.Get ] ]
903  $result Destructor
904  } else {
905  set result [$value Result.Get]
906  $result Refresh
907  set output [ list NrOfFramesSent [ $result PacketCount.Get ] NrOfOctetsSent [ $result ByteCount.Get ] ]
908  # TODO: Add SizeDistribution...
909 
910 
911  foreach frame [ $value Frame.Get ] {
912  set frameOut [ list ]
913  set frameResult [ $frame Result.Get ]
914  lappend frameOut "NrOfFrames" [ $frameResult PacketCount.Get ]
915  lappend frameOut "NrOfOctets" [ $frameResult ByteCount.Get ]
916 
917  # Mobile frames only have a limited set of counters
918  if { ![ $frame Info -implements Frame.Mobile ] } {
919  lappend frameOut "FrameSizeMinimum" [ $frameResult Framesize.Minimum.Get ]
920  lappend frameOut "FrameSizeMaximum" [ $frameResult Framesize.Maximum.Get ]
921  }
922  lappend output $frame $frameOut
923 
924  }
925 
926  lappend flowResultList "-tx" $output
927  }
928 
929  # Add error info the result list
930  # If a server error can be seen, include it
931  # If not check manually for possible other (unexpected) errors
932  set txError "None"
933  if { [ $value Info -implements Tx.Stream ] } {
934  set txError [ [ $value Status.Get ] ErrorStatus.Get ]
935  }
936  if { $txError != "None" } {
937  lappend flowResultList "-error" $txError
938  } else {
939  # Throughput too high for Tx side?
940  set result [$value Result.Get]
941  $result Refresh
942  set framesSent [ $result PacketCount.Get ]
943  set framesRequested [ $value NumberOfFrames.Get ]
944  if { $framesSent < $framesRequested } {
945  lappend flowResultList "-error" "UnexpectedOutOfResources"
946  }
947  $result Destructor
948  }
949  }
950  default {
951  puts "ByteBlowerHL warning: Unknown flow parameter: '$item', not getting results for '$value'"
952  }
953  }
954  }
955 
956  # Add flow result list to the main list
957  lappend scenarioResultList $flowResultList
958  }
959  return $scenarioResultList
960 }
961 
962 proc x.ExecuteScenario.Timestamp.Next.Get { scenarioObjectList prevTimestamp updateinterval } {
963  if { $prevTimestamp == 0} {
964  # search the initial timestamp
965  # this is the first timestamp all history objects know + updateinterval(seconds) buckets
966  set timestamp 0
967  set historyObjects [ list ]
968  foreach flowObjectList $scenarioObjectList {
969  foreach {item value} $flowObjectList {
970  switch -exact -- $item {
971  -rx {
972  if { $value != "NA"} {
973  if { [$value Info -implements Rx.Trigger.Basic ] } {
974  set resultHistory [ $value Result.History.Get ]
975  $resultHistory Refresh
976  lappend historyObjects $resultHistory
977  }
978  }
979  }
980  -tx {
981  set resultHistory [ $value Result.History.Get ]
982  $resultHistory Refresh
983  lappend historyObjects $resultHistory
984  }
985  default {
986  puts "ByteBlowerHL warning: Unknown flow parameter: '$item', not getting next timestamp for '$value'"
987  }
988  }
989  }
990  }
991 
992 
993 
994  set first_ho [ lindex $historyObjects 0 ]
995  foreach fhob [ $first_ho Cumulative.Get ] {
996  set bts [ $fhob Timestamp.Get ]
997 
998  set all_hobs_found 1
999  foreach ho [ lrange $historyObjects 1 end ] {
1000  set hob_found 0
1001  foreach hob [ $ho Cumulative.Get ] {
1002  if { $bts == [ $hob Timestamp.Get ]} {
1003  set hob_found 1
1004  break;
1005  #found in this history object
1006  }
1007  }
1008  if { $hob_found == 0} {
1009  set all_hobs_found 0
1010  }
1011  }
1012  if { $all_hobs_found == 0} {
1013  continue
1014  } else {
1015  return [ expr $bts + ( $updateinterval * 1000000 ) ]
1016  }
1017 
1018  }
1019 
1020 
1021  } else {
1022  return [ expr $prevTimestamp + ( $updateinterval * 1000000 ) ]
1023  }
1024 
1025 
1026 
1027 
1028 
1029  return $timestamp
1030 }
1031 
1032 proc x.ExecuteScenario.Bucket.Search { bucketlist timestamp } {
1033 #
1034 # This procedure searches the next bucket to check in the bucketlist
1035 #
1036 # @return
1037 # the next bucket object
1038 
1039 
1040  foreach bucket $bucketlist {
1041  if { [ $bucket Timestamp.Get ] == $timestamp} {
1042  return $bucket
1043  }
1044  }
1045 
1046 }
1047 
1048 proc x.ExecuteScenario.InterRunResults.Get { scenarioObjectList txPorts extended timestamp } {
1049 #
1050 # This procedure gets the real-time counter values for all the counter objects
1051 # in the scenario and formats them according to the scenario configuration.
1052 # It also looks if all TX streams are still running and gives an error if one
1053 # has failed.
1054 #
1055 # @param scenarioObjectList
1056 # The scenario object list. The counters of all the objects in this list
1057 # will be parsed and returned to the callback method.
1058 #
1059 # @param txPorts
1060 # The list of transmitting ports, to match a failing stream to its
1061 # source port.
1062 #
1063 # @param extended
1064 # Boolean defines extended results are requested or not. Note it is
1065 # used only for the TX part here. RX parts looked at extended value
1066 # when they were parsed.
1067 #
1068 # @param timestamp
1069 # Timestamp of the snapshot to search. If the snapshot is not available,
1070 # we will use the latest available snapshot.
1071 #
1072 # @return
1073 # A real-time result. Its structure is based on the scenario config.
1074 #
1075 # @exception @varitem{tcl_error}
1076 # If a TX stream has failed at this time, an error is thrown.
1077 #
1078 
1079  set scenarioResultList [ list ]
1080 
1081 
1082  foreach flowObjectList $scenarioObjectList {
1083  set flowResultList [ list ]
1084  foreach {item value} $flowObjectList {
1085  switch -exact -- $item {
1086  -rx {
1087  if { $value != "NA"} {
1088  if { [$value Info -implements Rx.Capture.Basic ] } {
1089  # The -rx value is a RX Capture
1090  lappend flowResultList "-rx" [$value Frames.Get]
1091 
1092  } elseif { [$value Info -implements Rx.Trigger.Basic ] } {
1093  # The -rx Value is a RX Basic trigger
1094  # use the ResultHistory to fetch the latest "Cumulative
1095  # Result" to add as numRx entry
1096  set resultHistory [ $value Result.History.Get ]
1097 
1098 
1099  $resultHistory Refresh
1100 
1101  set buckets [ $resultHistory Cumulative.Get ]
1102  set the_bucket [ x.ExecuteScenario.Bucket.Search $buckets $timestamp ]
1103  if { $the_bucket == "" } {
1104  set the_bucket [ lindex $buckets end ]
1105  }
1106  set rxFrames [ $the_bucket PacketCount.Get ]
1107 
1108  lappend flowResultList "-rx" [ list "NrOfFrames" $rxFrames ]
1109  } elseif { [ $value Info -implements Rx.Trigger.Basic.Mobile ] } {
1110  # we don't have temporary results. Omit it...
1111  lappend flowResultList "-rx" [ list "NrOfFrames" 0 ]
1112  } elseif { ![$value Info -implements Rx.Trigger.SizeDistribution ] } {
1113  # Not trigger basic, not capture, not sizedistribution...
1114  set result [ $value Result.Get ]
1115  $result Refresh
1116  lappend flowResultList "-rx" [ list "NrOfFrames" [ $result PacketCount.Get ] ]
1117  $result Destructor
1118 
1119  } else {
1120 
1121  # SizeDistribution
1122  set result [ $value Result.Get ]
1123  $result Refresh
1124 
1125  set output [ list "NrOfFrames" [ $result PacketCount.Get ] ]
1126  lappend output "NrOfOctets" [ $result ByteCount.Get ]
1127  lappend output "NrOfUndersized" [ $result PacketCount.BelowMinimum.Get ]
1128  lappend output "NrOfOversized" [ $result PacketCount.AboveMaximum.Get ]
1129  lappend flowResultList "-rx" $output
1130  }
1131  } else {
1132  lappend flowResultList "-rx" "NA"
1133  }
1134  }
1135  -tx {
1136  if { $extended == 0 } {
1137 
1138  set resultHistory [ $value Result.History.Get ]
1139 
1140 
1141  $resultHistory Refresh
1142 
1143  set buckets [ $resultHistory Cumulative.Get ]
1144  set the_bucket [ x.ExecuteScenario.Bucket.Search $buckets $timestamp ]
1145  if { $the_bucket == "" } {
1146  set the_bucket [ lindex $buckets end ]
1147  }
1148  set txFrames [ $the_bucket PacketCount.Get ]
1149 
1150 
1151 
1152  lappend flowResultList "-tx" [ list "NrOfFramesSent" $txFrames ]
1153  #lappend flowResultList "-tx" [ $value Counters.Brief.Get ]
1154 
1155  } else {
1156  set result [$value Result.Get]
1157  $result Refresh
1158  set output [ list NrOfFramesSent [ $result PacketCount.Get ] ]
1159  # TODO: Add SizeDistribution...
1160  lappend flowResultList "-tx" $output
1161  }
1162  # --- Check error
1163  set txError "None"
1164  if { [ $value Info -implements Tx.Stream ] } {
1165  set txError [ [ $value Status.Get ] ErrorStatus.Get ]
1166  }
1167  if { $txError != "None" } {
1168  # FOUND an ERROR on a flow
1169  foreach txPort $txPorts {
1170  foreach txPortStream [ $txPort Tx.Stream.Get ] {
1171  if { $txPortStream == $value } {
1172  set descr [lindex [ split [ $txPort Description.Get ] "\n" ] 0 ]
1173  error "ByteBlowerHL error: $txError on $descr"
1174  }
1175  }
1176  }
1177  }
1178  }
1179  default {
1180  puts "ByteBlowerHL warning: Unknown flow parameter: '$item', not getting inter-run results for '$value'"
1181  }
1182  }
1183  }
1184  lappend scenarioResultList $flowResultList
1185  }
1186  return $scenarioResultList
1187 }
1188 
1189 proc x.ExecuteScenario.Cleanup { scenarioObjectList } {
1190 #
1191 # Cleans up the objects created during this scenario. This way, the port objects
1192 # are as clean as before the scenario was started.
1193 #
1194 # @param scenarioObjectList
1195 # The scenario object list. All the objects in this list will be
1196 # destroyed.
1197 #
1198  # Retrieve the Wireless Endpoints
1199  set wirelessEndpoints [ x.ExecuteScenario.GetWirelessEndpoints $scenarioObjectList ]
1200 
1201 
1202  foreach flowObjectList $scenarioObjectList {
1203  foreach {item value} $flowObjectList {
1204  switch -exact -- $item {
1205  -tcp {
1206  foreach {tcpitem tcpvalue} $value {
1207  catch { $tcpvalue Destructor } dummy
1208  }
1209  }
1210  -scouting_tx {
1211  foreach { scoutingStream scoutingDuration } $value { break }
1212  catch { $scoutingStream Destructor } dummy
1213  }
1214  -rx -
1215  -tx {
1216  catch { $value Destructor } dummy
1217  }
1218  default {
1219  puts "ByteBlowerHL warning: Unknown flow parameter: '$item', calling Destructor on '$value'"
1220  catch { $value Destructor } dummy
1221  }
1222  }
1223  }
1224  }
1225 
1226  foreach wirelessEndpoint $wirelessEndpoints {
1227  catch { $wirelessEndpoint Result.Clear }
1228  catch { $wirelessEndpoint Lock 0 }
1229  }
1230 }
1231 
1232 proc x.ExecuteScenario.Error { scenarioObjectList errorInfo } {
1233 #
1234 # Handles an error that occured during scenario execution. Specifically, this
1235 # procedure calls the destructor on all object created during the execution,
1236 # so the port objects are as clean as before the scenario was started.
1237 #
1238 # @param scenarioObjectList
1239 # The scenario object list. All the objects in this list will be
1240 # destroyed.
1241 #
1242 # @param errorInfo
1243 # The caught error information.
1244 #
1245 # @exception @varitem{tcl_error}
1246 # The original error is rethrown after cleanup.
1247 #
1248 
1249  x.ExecuteScenario.Cleanup $scenarioObjectList
1250 
1251  error $errorInfo
1252 }
1253 
1254 proc x.ExecuteScenario.TxParam.Parse { txParamList } {
1255 #
1256 # Parses the Tx port parameters and configures the specified port according to
1257 # them.If not all parameters are given, the defaults will be used.
1258 #
1259 # @param txParamList
1260 # The TX part configuration of a flow.
1261 #
1262 # @return
1263 # The Tx side objects (oid's) that were created using the parameters
1264 # and other relevant information.
1265 # @list
1266 # List of three elements: (1) the configured Tx port object,
1267 # (2) the Tx stream object, (3) the duration of this flow
1268 # (in nanoseconds) and (4) the list of scouting frame stream info.
1269 #
1270 
1271  # set default tx parameters
1272  set txPort ""
1273  set portFound 0
1274 
1275  set srcFrameList [ list ]
1276  set numberOfFrames 100; set interframegap 10000000; set initialTimeToWait 0
1277  set timingModifier "none"; set frameModifier "none"
1278  set latencyEnable 0; set outOfSequenceEnable 0
1279 
1280  set srcScoutingFrameList [ list ]
1281  set scoutingNumberOfFrames 2; set scoutingInitialTimeToWait 0
1282  set scoutingInterframegap 10000000 ;# 10[ms]
1283  set scoutingStreamLeadOutTime 100000000 ;# [100ms]
1284 
1285  set scoutingStreamList [ list ]
1286 
1287  # parse tx parameters
1288  #puts "TxParam.Parse: txParamList: $txParamList"
1289  foreach {item value} $txParamList {
1290  #puts "TxParam.Parse: Parsing item $item with value $value"
1291  switch -- $item {
1292  -port {
1293  if { ! $portFound } {
1294  set portFound 1
1295  set txPort $value
1296  } else {
1297  error "ByteBlowerHL error: Only 1 tx port allowed per tx port parameter list"
1298  }
1299  }
1300  -frame { lappend srcFrameList $value }
1301  -numberofframes { set numberOfFrames $value }
1302  -interframegap { set interframegap $value }
1303  -initialtimetowait { set initialTimeToWait $value }
1304  -framemodifier {
1305  if { $frameModifier == "none" } {
1306  set frameModifier $value
1307  } else {
1308  error "ByteBlowerHL error: Only 1 FrameModifier per frame is allowed"
1309  }
1310  }
1311 
1312  -timingmodifier { set timingModifier $value }
1313  -latency { set latencyEnable $value }
1314  -outofsequence { set outOfSequenceEnable $value }
1315  -scoutingframe { lappend srcScoutingFrameList $value }
1316  -scoutinginterframegap { set scoutingInterframegap $value }
1317  default { error "ByteBlowerHL error: Invalid tx port parameter: $item" }
1318  }
1319  }
1320 
1321  if { ! $portFound} {
1322  error "ByteBlowerHL error: No tx port found in flow parameter list"
1323  }
1324  if { $numberOfFrames < 0} {
1325  error "ByteBlowerHL error: Tx port parameter <numberofframes> must be a positive integer"
1326  }
1327 
1328  # create and configure the stream for scouting frames
1329  foreach srcScoutingFrame $srcScoutingFrameList {
1330  set scoutingStream [ $txPort Tx.Stream.Add ]
1331 
1332  #puts "TxParam.Parse: Creating scouting frame for $srcScoutingFrame"
1333  set scoutingFrameObject [ x.ExecuteScenario.TxParam.ScoutingFrame.Parse $scoutingStream $srcScoutingFrame ]
1334 
1335  $scoutingStream InitialTimeToWait.Set $scoutingInitialTimeToWait
1336  $scoutingStream InterFrameGap.Set $scoutingInterframegap
1337  $scoutingStream NumberOfFrames.Set $scoutingNumberOfFrames
1338 
1339  # calculate total scouting stream duration in milliseconds
1340  set scoutingDuration [ expr ( [ $scoutingStream InitialTimeToWait.Get ] / 1e6 ) + ( [ $scoutingStream InterFrameGap.Get ] / 1e6 * [ $scoutingStream NumberOfFrames.Get ] ) + ( $scoutingStreamLeadOutTime / 1e6 ) ]
1341 
1342  lappend scoutingStreamList [ list $scoutingStream $scoutingDuration ]
1343  }
1344 
1345  # create and configure the stream
1346  set stream [$txPort Tx.Stream.Add]
1347  foreach srcFrame $srcFrameList {
1348  #puts "TxParam.Parse: Creating frame for $srcFrame"
1349  set frameObject [ x.ExecuteScenario.TxParam.Frame.Parse $stream $srcFrame ]
1350  if {$latencyEnable == 1} {
1351  [ $frameObject FrameTag.Time.Get ] Enable 1
1352  } elseif {$latencyEnable == 0} {
1353  #do nothing
1354  } else {
1355  error "ByteBlowerHL error: Invalid latency flag: $latencyEnable"
1356  }
1357  if {$outOfSequenceEnable == 1} {
1358  [ $frameObject FrameTag.Sequence.Get ] Enable 1
1359  } elseif {$outOfSequenceEnable == 0} {
1360  #do nothing
1361  } else {
1362  error "ByteBlowerHL error: Invalid out-of-sequence flag: $outOfSequenceEnable"
1363  }
1364  }
1365  $stream InitialTimeToWait.Set $initialTimeToWait
1366  $stream InterFrameGap.Set $interframegap
1367  $stream NumberOfFrames.Set $numberOfFrames
1368 
1369  # calculate total flow duration in milliseconds
1370  set duration [expr ([$stream InitialTimeToWait.Get]/1e6) + ([$stream InterFrameGap.Get] / 1e6 * $numberOfFrames)]
1371 
1372  # apply the provided frame and/or time modifiers
1373  if { $frameModifier != "none"} {
1374  set frameMod [ x.ExecuteScenario.TxParam.FrameModifier.Parse $stream $frameModifier ]
1375  }
1376  if { $timingModifier != "none"} {
1377  set timingModifierObject [ x.ExecuteScenario.TxParam.TimingModifier.Parse $stream $timingModifier ]
1378  # adjust total flow duration for interburstgap
1379  if { [ string compare [ $timingModifierObject Get _ClassName ] TimingModifier.MultiBurst ] == 0} {
1380  set nofInterBurstGap [expr $numberOfFrames / [$timingModifierObject BurstSize.Get]]
1381  if {[expr fmod($numberOfFrames,[$timingModifierObject BurstSize.Get])] == 0} {
1382  incr nofInterBurstGap -1
1383  }
1384  set duration [expr $duration + ($nofInterBurstGap * [$timingModifierObject InterBurstGap.Get]/1e6)]
1385  }
1386  }
1387 
1388  # return the flow and its duration
1389  return [ list $txPort $stream $duration $scoutingStreamList ]
1390 }
1391 
1392 proc x.ExecuteScenario.TxParam.Frame.Parse { stream frameDescription } {
1393  if { [ string range [ lindex $frameDescription 0 ] 0 0 ] != "-"} {
1394  # old behaviour
1395  puts "ByteBlowerHL warning: Creating a frame using -frame { byte byte byte } which will be deprecated, please use -frame { -bytes { byte byte byte ... } }"
1396  set frame [ $stream Frame.Add ]
1397  $frame Bytes.Set $frameDescription
1398  return $frame
1399  }
1400 
1401  # new behaviour
1402  set bytes [ list ]
1403  set payload [ list ]
1404  set destinationAddress ""
1405  set sourcePort 0
1406  set destinationPort 0
1407  set sizemodifier "none"
1408  set fieldmodifiers [ list ]
1409  set l3autochecksum 0
1410  set l3autolength 0
1411  set l4autochecksum 0
1412  set l4autolength 0
1413 
1414  foreach { item value } $frameDescription {
1415  #puts "TxParam.Frame.Parse: Parsing $item with value $value"
1416  switch -- $item {
1417  -bytes {
1418  set bytes $value
1419  }
1420  -payload {
1421  set payload $value
1422  }
1423  -sourcePort {
1424  set sourcePort $value
1425  }
1426  -destinationPort {
1427  set destinationPort $value
1428  }
1429  -destinationAddress {
1430  set destinationAddress $value
1431  }
1432 
1433  -sizemodifier {
1434  if { $sizemodifier != "none" } {
1435  error "ByteBlowerHL error: Only one size modifier is allowed per frame."
1436  }
1437  set sizemodifier $value
1438  }
1439 
1440  -fieldmodifier {
1441  lappend fieldmodifiers $value
1442  }
1443  -l3autochecksum {
1444  set l3autochecksum $value
1445  }
1446  -l3autolength {
1447  set l3autolength $value
1448  }
1449  -l4autochecksum {
1450  set l4autochecksum $value
1451  }
1452  -l4autolength {
1453  set l4autolength $value
1454  }
1455  default {
1456  error "ByteBlowerHL error: Unknown frame descriptor: $item $value."
1457  }
1458  }
1459  }
1460 
1461  if { [ llength $bytes ] == 0 && [ llength $payload ] == 0} {
1462  error "ByteBlowerHL error: either -bytes or -payload must be given when creating a frame."
1463  }
1464 
1465  if { [ llength $bytes ] != 0 && [ llength $payload ] != 0} {
1466  error "ByteBlowerHL error: only one of -bytes and -payload must be given when creating a frame."
1467  }
1468 
1469  if { [ llength $payload ] != 0 && ( $sourcePort == 0 || $destinationPort == 0 || $destinationAddress == "" )} {
1470  error "ByteBlowerHL error: when using -payload, -sourcePort, -destinationPort and -destinationAddress must also be given!"
1471  }
1472 
1473 
1474  set frame [ $stream Frame.Add ]
1475  #puts "TxParam.Frame.Parse: Setting bytes $bytes"
1476  if { [ llength $bytes ] != 0} {
1477  if { ! [ $stream Info -implements Tx.Stream ]} {
1478  error "ByteBlowerHL error: -bytes can only be used on a ByteBlowerPort"
1479  }
1480  $frame Bytes.Set $bytes
1481  } elseif { [ llength $payload ] != 0} {
1482  if { ! [ $stream Info -implements Tx.Stream.Mobile ]} {
1483  error "ByteBlowerHL error: -payload can only be used on a Wireless Endpoint"
1484  }
1485 
1486  $frame Payload.Set $payload
1487  $stream Source.Port.Set $sourcePort
1488  $stream Destination.Port.Set $destinationPort
1489  $stream Destination.Address.Set $destinationAddress
1490  }
1491 
1492  if { ![ string equal $sizemodifier "none" ]} {
1493  #puts "TxParam.Frame.Parse: Parsing size modifier $sizemodifier"
1495  }
1496 
1497  foreach fieldmodifier $fieldmodifiers {
1498  #puts "TxParam.Frame.Parse: Parsing field modifier $fieldmodifier"
1500  }
1501 
1502  if { $l3autochecksum} {
1503  $frame L3.Auto.Checksum.Enable 1
1504  }
1505  if { $l3autolength} {
1506  $frame L3.Auto.Length.Enable 1
1507  }
1508  if { $l4autochecksum} {
1509  $frame L4.Auto.Checksum.Enable 1
1510  }
1511  if { $l3autolength} {
1512  $frame L4.Auto.Length.Enable 1
1513  }
1514 
1515 
1516 
1517 
1518  #puts "TxParam.Frame.Parse: Done"
1519  return $frame
1520 }
1521 
1522 proc x.ExecuteScenario.TxParam.ScoutingFrame.Parse { scoutingStream frameDescription } {
1523 #
1524 #
1525 # @param scoutingStream
1526 # Stream to configure the scouting frame on
1527 #
1528 # @param frameDescription
1529 # -bytes
1530 # Frame content
1531 # -l3autochecksum
1532 # Enable automatic Layer3 checksum correction
1533 # Default: enabled (1)
1534 # -l3autolength
1535 # Enable automatic Layer3 length correction
1536 # Default: enabled (1)
1537 # -l4autochecksum
1538 # Enable automatic Layer4 checksum correction
1539 # Default: enabled (1)
1540 # -l4autolength
1541 # Enable automatic Layer4 length correction
1542 # Default: enabled (1)
1543 #
1544 
1545  set bytes [ list ]
1546  set l3autochecksum 1
1547  set l3autolength 1
1548  set l4autochecksum 1
1549  set l4autolength 1
1550 
1551  foreach { item value } $frameDescription {
1552  #puts "TxParam.ScoutingFrame.Parse: Parsing $item with value $value"
1553  switch -- $item {
1554  -bytes {
1555  set bytes $value
1556  }
1557  -l3autochecksum {
1558  set l3autochecksum $value
1559  }
1560  -l3autolength {
1561  set l3autolength $value
1562  }
1563  -l4autochecksum {
1564  set l4autochecksum $value
1565  }
1566  -l4autolength {
1567  set l4autolength $value
1568  }
1569  default {
1570  error "ByteBlowerHL error: Unknown frame descriptor: $item $value."
1571  }
1572  }
1573  }
1574 
1575  if { [ llength $bytes ] == 0} {
1576  error "ByteBlowerHL error: -bytes must be given when creating a frame."
1577  }
1578 
1579  set scoutingFrame [ $scoutingStream Frame.Add ]
1580  #puts "TxParam.ScoutingFrame.Parse: Setting bytes $bytes"
1581  $scoutingFrame Bytes.Set $bytes
1582 
1583  if { $l3autochecksum} {
1584  $scoutingFrame L3.Auto.Checksum.Enable 1
1585  }
1586  if { $l3autolength} {
1587  $scoutingFrame L3.Auto.Length.Enable 1
1588  }
1589  if { $l4autochecksum} {
1590  $scoutingFrame L4.Auto.Length.Enable 1
1591  }
1592  if { $l3autolength} {
1593  $scoutingFrame L4.Auto.Checksum.Enable 1
1594  }
1595 
1596  #puts "TxParam.ScoutingFrame.Parse: Done"
1597  return $scoutingFrame
1598 }
1599 
1600 proc x.ExecuteScenario.TxParam.FrameFieldModifier.Parse { frame fieldModifier } {
1601 #
1602 # Parses the arguments specific for a frame field modifier option and creates a
1603 # frame modifier using that configuration.
1604 #
1605 # @param frame
1606 # The frame object (oid) on which the size modifier should be
1607 # applied.
1608 # @param frameModifier
1609 # The frame modifier configuration.
1610 # @return
1611 # The frame modifier object (oid)
1612 #
1613  set type "none"
1614  set offset 58
1615  set length 2
1616  set minimum 0
1617  set maximum 65535
1618  set step 1
1619  set initialvalue 0
1620 
1621  foreach {item value} $fieldModifier {
1622  switch -- $item {
1623  -type {
1624  set type $value
1625  }
1626  -offset {
1627  set offset $value
1628  }
1629  -length {
1630  set length $value
1631  }
1632  -minimum {
1633  set minimum $value
1634  }
1635  -maximum {
1636  set maximum $value
1637  }
1638  -step {
1639  set step $value
1640  }
1641  -initialvalue {
1642  set initialvalue $value
1643  }
1644  default {
1645  error "ByteBlowerHL error: Unknown configuration item for a FrameFieldModifier $item $value"
1646  }
1647  }
1648  }
1649 
1650  switch -- $type {
1651  incremental -
1652  random {
1653  set modifier [ $frame Modifier.Field.[ string totitle $type ].Add ]
1654  }
1655  none {
1656  error "ByteBlowerHL error: -type must be given in the FrameFieldModifier configuration"
1657  }
1658  default {
1659  error "ByteBlowerHL error: Unknown Frame Field Modifier type $type"
1660  }
1661  }
1662 
1663  $modifier Offset.Set $offset
1664  $modifier Length.Set $length
1665  $modifier Minimum.Set $minimum
1666  $modifier Maximum.Set $maximum
1667 
1668  switch -- $type {
1669  incremental {
1670  $modifier Step.Set $step
1671  $modifier InitialValue.Set $initialvalue
1672  }
1673  random {
1674  # nothing else to do
1675  }
1676  }
1677 
1678  return $modifier
1679 
1680 }
1681 
1682 proc x.ExecuteScenario.TxParam.FrameSizeModifier.Parse { frame frameModifier } {
1683 #
1684 # Parses the arguments specific for a frame size modifier Tx option and creates a
1685 # frame modifier using that configuration.
1686 #
1687 # @param frame
1688 # The frame object (oid) on which the size modifier should be
1689 # applied.
1690 # @param frameModifier
1691 # The frame modifier configuration.
1692 # @return
1693 # The frame modifier object (oid)
1694 #
1695 
1696  if { ![ string equal $frameModifier "none" ]} {
1697  # set default parameters
1698  set type ""
1699  set typeFound 0
1700  set minimum 60; set maximum 1514; set step 1; set iteration 1
1701 
1702  # parse parameters
1703  foreach {item value} $frameModifier {
1704  switch -- $item {
1705  -type {
1706  if { ! $typeFound } {
1707  set typeFound 1
1708  set type [string tolower $value]
1709  } else {
1710  error "ByteBlowerHL error: Only 1 type allowed per frame size modifier parameter list"
1711  }
1712  }
1713  -minimum { set minimum $value }
1714  -maximum { set maximum $value }
1715  -step { set step $value }
1716  -iteration { set iteration $value }
1717  default { error "ByteBlowerHL error: Invalid frame size modifier parameter: $item"}
1718  }
1719  }
1720 
1721  if { ! $typeFound} {
1722  error "ByteBlowerHL error: No type found in frame size modifier parameter list"
1723  }
1724 
1725 
1726  # configure the flow
1727  set frameModifierObjects [ list ]
1728  switch -- $type {
1729  random {
1730  set frameModifierObject [ $frame Modifier.Size.Random.Set ]
1731  $frameModifierObject Minimum.Set $minimum
1732  $frameModifierObject Maximum.Set $maximum
1733  }
1734  growing {
1735  set frameModifierObject [ $frame Modifier.Size.Growing.Set ]
1736  $frameModifierObject Minimum.Set $minimum
1737  $frameModifierObject Maximum.Set $maximum
1738  $frameModifierObject Iteration.Set $iteration
1739  $frameModifierObject Step.Set $step
1740  }
1741  default { error "ByteBlowerHL error: Unknown frame size modifier type: $type" }
1742  }
1743  lappend frameModifierObjects $frameModifier
1744 
1745 
1746  # return the frame modifier
1747  return $frameModifierObjects
1748  }
1749 }
1750 
1751 proc x.ExecuteScenario.TxParam.FrameModifier.Parse { stream frameModifier } {
1752 #
1753 # Parses the arguments specific for a framemodifier Tx option and creates a
1754 # frame modifier using that configuration.
1755 #
1756 # @deprecated
1757 #
1758 # @param stream
1759 # The stream object (oid) on which the frame modifier should be
1760 # applied.
1761 # @param frameModifier
1762 # The frame modifier configuration.
1763 # @return
1764 # The frame modifier object (oid)
1765 #
1766  puts "\[DEPRECATED\] Creating a FrameModifier on a stream is deprecated! Please create the SizeModifier on a frame."
1767  foreach frame [ $stream Frame.Get ] {
1769  }
1770  return
1771 }
1772 
1773 proc x.ExecuteScenario.TxParam.TimingModifier.Parse { stream timingModifier } {
1774 #
1775 # Parses the arguments specific for a timingmodifier Tx option and creates a
1776 # timing modifier using that configuration.
1777 #
1778 # @param stream
1779 # The stream object (oid) on which the timing modifier should be
1780 # applied.
1781 # @param frameModifier
1782 # The timing modifier configuration.
1783 # @return
1784 # The timing modifier object (oid)
1785 #
1786 
1787  if { ($timingModifier != "none")} {
1788  # set default parameters
1789  set type "";
1790  set typeFound 0;
1791  set burstSize 100; set interBurstGap 1000000000;
1792 
1793  # parse parameters
1794  foreach {item value} $timingModifier {
1795  switch -- $item {
1796  -type {
1797  if { ! $typeFound } {
1798  set typeFound 1
1799  set type [string tolower $value]
1800  } else {
1801  error "ByteBlowerHL error: Only 1 type allowed per timing modifier parameter list"
1802  }
1803  }
1804  -burstsize { set burstSize $value }
1805  -interburstgap { set interBurstGap $value }
1806  default { error "ByteBlowerHL error: Invalid timing modifier parameter: $item" }
1807  }
1808  }
1809 
1810  if { ! $typeFound} {
1811  error "ByteBlowerHL error: No type found in timing modifier parameter list"
1812  }
1813 
1814  # configure the flow
1815  set timingModifierObject [ $stream Modifier.Timing.Set $type ]
1816  switch -- $type {
1817  multiburst {
1818  $timingModifierObject BurstSize.Set $burstSize
1819  $timingModifierObject InterBurstGap.Set $interBurstGap
1820  }
1821  default { error "ByteBlowerHL error: Unknown timing modifier type: $type" }
1822  }
1823 
1824  # return the timing modifier
1825  return $timingModifierObject
1826  }
1827 }
1828 
1829 proc x.ExecuteScenario.RxTupleFilter.Parse { triggerObject filter } {
1830  set remoteIP ""
1831  set remoteUdpPort ""
1832  set localUdpPort ""
1833 
1834  foreach { field value } $filter {
1835  switch -- [ string tolower $field ] {
1836  "-sourceaddress" { set remoteIP $value }
1837  "-udpdestinationport" { set localUdpPort $value }
1838  "-udpsourceport" { set remoteUdpPort $value }
1839  default {
1840  error "ByteBlowerHL error: filter format $filterFormat does not support $field"
1841  }
1842  }
1843  }
1844 
1845  if { $remoteIP == "" || $remoteUdpPort == "" || $localUdpPort == ""} {
1846  error "ByteBlowerHL error: filter format syntax error: all entries of -sourceaddress, -udpdestinationport and -udpsourceport are required!"
1847  }
1848 
1849  $triggerObject Filter.SourceAddress.Set $remoteIP
1850  $triggerObject Filter.Udp.DestinationPort.Set $localUdpPort
1851  $triggerObject Filter.Udp.SourcePort.Set $remoteUdpPort
1852 
1853 }
1854 
1855 proc x.ExecuteScenario.RxParam.Parse { rxParamList extended } {
1856 #
1857 # @brief Parses the Rx port parameters and configures the specified port with either a
1858 # trigger, a latency or out-of-sequence detector or a capture tool.
1859 #
1860 # Only one such specifier (trigger/latency/outofsequence/capture) is allowed per
1861 # Rx parameter list. Multiple Rx parameter lists on the same port are possible
1862 # however.
1863 #
1864 # @note The receiver will not yet be started; it will not yet listen to incoming
1865 # data.
1866 #
1867 # @param rxParamList
1868 # A declarative RX component configuration.
1869 #
1870 # @param extended
1871 # Boolean defining whether extended results are requested or not.
1872 # The flag only affects default values, and thus can always be overridden by RX parameters.
1873 #
1874 # @return
1875 # The RX component objects that were created using the Rx component configuration.
1876 # This is a list of two elements: the port object and the incoming packet processor object.
1877 #
1878 
1879  # set default rx parameters
1880  set rxPort ""
1881  set portFound 0
1882  set trigger ""; set latency ""; set outofsequence ""; set capture ""
1883  set receiverFound 0
1884 
1885  # parse rx parameters
1886  #puts "rxParamList: $rxParamList"
1887  foreach {item value} $rxParamList {
1888  switch -- $item {
1889  -port {
1890  if { ! $portFound } {
1891  set portFound 1
1892  set rxPort $value
1893  } else {
1894  error "ByteBlowerHL error: Only 1 rx port allowed per rx port parameter list"
1895  }
1896  }
1897  -trigger {
1898  if { ! $receiverFound } {
1899  set receiverFound 1
1900  set trigger $value
1901  } else {
1902  error "ByteBlowerHL error: Only 1 trigger/latency/outofsequence/capture allowed per rx port parameter list"
1903  }
1904  }
1905  -latency {
1906  if { ! $receiverFound } {
1907  set receiverFound 1
1908  set latency $value
1909  } else {
1910  error "ByteBlowerHL error: Only 1 trigger/latency/outofsequence/capture allowed per rx port parameter list"
1911  }
1912  }
1913  -outofsequence {
1914  if { ! $receiverFound } {
1915  set receiverFound 1
1916  set outofsequence $value
1917  } else {
1918  error "ByteBlowerHL error: Only 1 trigger/latency/outofsequence/capture allowed per rx port parameter list"
1919  }
1920  }
1921  -capture {
1922  if { ! $receiverFound } {
1923  set receiverFound 1
1924  set capture $value
1925  } else {
1926  error "ByteBlowerHL error: Only 1 trigger/latency/outofsequence/capture allowed per rx port parameter list"
1927  }
1928  }
1929  default {
1930  error "ByteBlowerHL error: Invalid rx port parameter: $item"
1931  }
1932  }
1933  }
1934 
1935  if { ! $portFound} {
1936  error "ByteBlowerHL error: No rx port found in flow parameter list"
1937  }
1938 
1939  # parse trigger settings, configure trigger object and return it
1940  if { $trigger != ""} {
1941  set filter ""
1942  set filterFormat "display"
1943  set duration 0
1944  if { ! $extended} {
1945  set type "basic"
1946  } else {
1947  set type "sizedistribution"
1948  }
1949  foreach {item value} $trigger {
1950  switch -- $item {
1951  -type { set type $value }
1952  -filterFormat { set filterFormat $value }
1953  -filter { set filter $value }
1954  -duration { set duration $value }
1955  default { error "ByteBlowerHL error: Invalid trigger parameter: $item" }
1956  }
1957  }
1958  if { $filter == ""} {
1959  error "ByteBlowerHL error: Please define a non-empty filter for the trigger option of the rx port"
1960  }
1961  set triggerObject ""
1962  switch -- $type {
1963  "basic" { set triggerObject [ $rxPort Rx.Trigger.Basic.Add ] }
1964  "sizedistribution" {
1965  if { [ $rxPort Info -implements WirelessEndpoint ] } {
1966  error "ByteBlowerHL error: sizedistribution trigger not supported by a WirelessEndpoint!"
1967  }
1968  set triggerObject [ $rxPort Rx.Trigger.SizeDistribution.Add ]
1969  }
1970  default { error "ByteBlowerHL error: Invalid trigger type: $type" }
1971  }
1972  switch -- $filterFormat {
1973  display { $triggerObject Filter.Set [ ::excentis::basic::ParseFilter $filter ] }
1974  bpf { $triggerObject Filter.Set $filter }
1975  tuple {
1976  if { ! [ $rxPort Info -implements WirelessEndpoint ] } {
1977  error "ByteBlowerHL error: filter format $filterFormat not supported by object of type [ $rxPort Get _ClassName ]"
1978  }
1979 
1980  x.ExecuteScenario.RxTupleFilter.Parse $triggerObject $filter
1981 
1982  }
1983  default { error "ByteBlowerHL error: FilterType on rx port must be bpf, display or tuple" }
1984  }
1985 
1986  if { $duration != 0} {
1987  if { [ $rxPort Info -implements WirelessEndpoint ]} {
1988  $triggerObject Duration.Set $duration
1989  } else {
1990  default { error "ByteBlowerHL error: -duration can only be set on Wireless Endpoints!" }
1991  }
1992  }
1993 
1994  return [ list $rxPort $triggerObject ]
1995  }
1996 
1997  # parse latency settings, configure latency object and return it
1998  if { $latency != ""} {
1999  set filter ""
2000  set filterFormat "display"
2001  set duration 0
2002  if { ! $extended} {
2003  set type "basic"
2004  } else {
2005  set type "distribution"
2006  }
2007  foreach {item value} $latency {
2008  switch -- $item {
2009  -type { set type $value }
2010  -filterFormat { set filterFormat $value }
2011  -filter { set filter $value }
2012  -duration { set duration $value }
2013  default { error "ByteBlowerHL error: Invalid latency parameter: $item" }
2014  }
2015  }
2016  if { $filter == ""} {
2017  error "ByteBlowerHL error: Please define a non-empty filter for the latency option of the rx port"
2018  }
2019  switch -- [ string tolower $type ] {
2020  basic -
2021  distribution { set latencyObject [ $rxPort Rx.Latency.[ string totitle $type ].Add ] }
2022  default { error "ByteBlowerHL error: Unsupported latency type '${type}'" }
2023  }
2024 
2025  switch -- $filterFormat {
2026  display { $latencyObject Filter.Set [ ::excentis::basic::ParseFilter $filter ] }
2027  bpf { $latencyObject Filter.Set $filter }
2028  tuple {
2029  if { ! [ $rxPort Info -implements WirelessEndpoint ] } {
2030  error "ByteBlowerHL error: filter format $filterFormat not supported by object of type [ $rxPort Get _ClassName ]"
2031  }
2032 
2033  x.ExecuteScenario.RxTupleFilter.Parse $latencyObject $filter
2034 
2035  }
2036  default { error "ByteBlowerHL error: FilterType on rx port must be bpf, display or tuple" }
2037  }
2038 
2039  if { $duration != 0} {
2040  if { [ $rxPort Info -implements WirelessEndpoint ]} {
2041  $latencyObject Duration.Set $duration
2042  } else {
2043  default { error "ByteBlowerHL error: -duration can only be set on Wireless Endpoints!" }
2044  }
2045  }
2046  return [ list $rxPort $latencyObject ]
2047  }
2048 
2049  # parse outofsequence settings, configure outofsequence object and return it
2050  if { $outofsequence != ""} {
2051  set filter ""
2052  set type "basic"
2053  foreach {item value} $outofsequence {
2054  switch -- $item {
2055  -type { set type $value }
2056  -filter { set filter $value }
2057  default { error "ByteBlowerHL error: Invalid outofsequence parameter: $item" }
2058  }
2059  }
2060  if { $filter == ""} {
2061  error "ByteBlowerHL error: Please define a non-empty filter for the outofsequence option of the rx port"
2062  }
2063  switch -- [ string tolower $type ] {
2064  basic { set outofsequenceObject [ $rxPort Rx.OutOfSequence.[ string totitle $type ].Add ] }
2065  default { error "ByteBlowerHL error: Unsupported out-of-sequence type '${type}'" }
2066  }
2067  $outofsequenceObject Filter.Set [ ::excentis::basic::ParseFilter $filter ]
2068 
2069  return [ list $rxPort $outofsequenceObject ]
2070  }
2071 
2072  # parse capture settings, configure capture object and return it
2073  if { $capture != ""} {
2074  set filter ""
2075  set pcap ""
2076  foreach {item value} $capture {
2077  switch -- $item {
2078  -pcap { set pcap $value }
2079  -filter { set filter $value }
2080  default { error "ByteBlowerHL error: Invalid capture parameter: $item" }
2081  }
2082  }
2083  set captureObject [ $rxPort Rx.Capture.Basic.Add ]
2084  $captureObject Filter.Set [ ::excentis::basic::ParseFilter $filter ]
2085  lappend ::excentis::basic::rxPcapFileNames $pcap
2086 
2087  return [ list $rxPort $captureObject ]
2088  }
2089 
2090  # return 'not applicable' if neither trigger, latency, outofsequence nor capture was provided
2091  return [ list $rxPort "NA" ]
2092 }
2093 
2094 }
2095 
2096 }