All Classes Namespaces Files Functions Pages
flowlossrate.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 Wrapper module for loss measurement scenarios that forces the required TX and RX components to be present and returns only loss values..
18 #
19 # @copyright Excentis nv - www.excentis.com
20 #
21 
22 ##
23 # Calculates the loss rate for the provided @p flowlist according to RFC 1242
24 #
25 # Definition:
26 # Percentage of frames that should have been forwarded
27 # by a network device under steady state (constant)
28 # load that were not forwarded due to lack of
29 # resources.
30 #
31 # @note
32 # A trigger must be defined per receiving flow
33 #
34 # @note
35 # If non-basic triggers are defined in the flows then these triggers are ignored.
36 # E.g.: sizedistribution and rate triggers are ignored
37 # If Latency and Capture options are defined, they will be ignored too.
38 # So if besides tx parameters, rx parameters are defined, and these rx
39 # parameters do not include a basic trigger option, the flow will transmit, but
40 # we will not be able to determine the received frames.
41 #
42 # @note
43 # When for a particular flow only tx parameters are given, this
44 # flow will provide background traffic. This flow will be used
45 # to send traffic, but will not be taken into account for the
46 # calculation of the frame loss rate.
47 #
48 # @param flowlist
49 # The declarative scenario configuration. See the @ref TclApiHLOverview "higher-layer API overview" for more information.
50 #
51 # @param args
52 # Output-level option list in the form of a list of key-value pairs:
53 # @dlist
54 # @dlitem{-return, Defines the output mode
55 # @dlist
56 # @dlitem{percentage, Percentage of frames lost during transmission vs. offered load
57 # as an aggregate over all flows in the @p flowlist}
58 # @dlitem{numbers, Number of transmitted and received frames per flow in the flowlist.}
59 # @dlitem{percentagePerFlow, Percentage of the frames lost during transmission vs offered load.
60 # Result for each flow in the @p flowlist}
61 # @enddlist
62 # @defaultvalue{percentage}
63 # }
64 # @enddlist
65 # @return
66 # Loss percentage or number of transmitted and received frames per flow, depending on @p \-return
67 # @dlist
68 # @dlitem{percentage, 0.02}
69 # @dlitem{numbers, { {-tx 100} {-tx 100 -rx 100} {-tx 100 -rx NA} {-tx 100 -rx 100 -rx 100} }}
70 # @enddlist
71 # 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.
72 # @apiexample
73 # @apisnippet{source IPv4.run.tcl}
74 # @apisnippetretval{ByteBlowerObject_1530880908_2}
75 # @apisnippet{% ByteBlowerObject_1530880908_2 Message.Get}
76 # @apisnippetretval{-server localhost Failed to connect with the ByteBlower server: byteblower-tp-p860.lab.excentis.com:9002}
77 # @endapiexample
78 proc FlowLossRate { flowlist args } {
79 
80  set flowexecutelist [ list ]
81  set newArgs [ list ]
82  set outputmode "percentage"
83  if {$args != ""} {
84  foreach { item value } $args {
85  set item [ string tolower $item ]
86  switch -- $item {
87  -return {
88  set outputmode $value
89  }
90  default {
91  # Pass it on to ExecuteScenario.
92  append newArgs "$item $value"
93  }
94  }
95  }
96  }
97 
98  # parse flowlist to exclude non-basic triggers/latency/capture
99  foreach flow $flowlist {
100  set flowtoexecute [ list ]
101  # parse flow parameters
102  foreach {item value} $flow {
103  switch -- $item {
104  -tx {
105  set txparam $value
106  lappend flowtoexecute "-tx" $txparam
107  }
108  -rx {
109  set rxparam $value
110  # parse rx parameters to exclude non-basic triggers / latency/capture
111  set rxparam [x.RxParam.FlowLoss.Parse $rxparam]
112  lappend flowtoexecute "-rx" $rxparam
113  }
114  default {
115  error "ByteBlowerHL error: Invalid flow parameter: $item"
116  }
117  }
118  }; # end parse flow parameters
119  lappend flowexecutelist $flowtoexecute
120  }; # end parse flowlist
121 
122  set result [ eval ExecuteScenario [ list $flowexecutelist ] $newArgs ]
123  if { [string equal $outputmode "percentage"]} {
124  set resulttx 0; set resultrx 0
125  set errormessage ""
126  set losspercentage [ list ]
127  foreach flow $result {
128  # We only need to count flows that have both tx and rx results
129  set index [lsearch $flow "-rx"]
130  if {$index != -1} {
131  foreach {item value} $flow {
132  switch -- $item {
133  -tx {
134  incr resulttx [x.TxResult.FlowLoss.Parse $value]
135  }
136  -rx {
137  if {$value != "NA"} {
138  incr resultrx [x.RxResult.FlowLoss.Parse $value]
139  }
140  }
141  -error {
142  puts stderr "ByteBlowerHL warning: Flow error detected. Loss percentage may be wrong. Error code: $value"
143  set errormessage $value
144  }
145  }
146  }
147  }
148  }
149  lappend losspercentage [ expr $resulttx != 0 ? (1.0 - (double($resultrx) / $resulttx)) * 100 : 0 ]
150  if { ![ string equal $errormessage "" ]} {
151  lappend losspercentage "-error" $errormessage
152  }
153  return $losspercentage
154  } elseif { [ string equal $outputmode "percentagePerFlow" ]} {
155  set resultList [ list ]
156  foreach flow $result {
157  # We only need to count flows that have both tx and rx results
158  set resulttx 0; set resultrx 0
159  set errormessage ""
160  set losspercentage [ list ]
161  set index [lsearch $flow "-rx"]
162  if {$index != -1} {
163  foreach {item value} $flow {
164  switch -- $item {
165  -tx {
166  incr resulttx [x.TxResult.FlowLoss.Parse $value]
167  }
168  -rx {
169  if {$value != "NA"} {
170  incr resultrx [x.RxResult.FlowLoss.Parse $value]
171  }
172  }
173  -error {
174  puts stderr "ByteBlowerHL warning: Flow error detected. Loss percentage may be wrong. Error code: $value"
175  set errormessage $value
176  }
177  }
178  }
179  }
180  lappend losspercentage [ expr $resulttx != 0 ? (1.0 - (double($resultrx) / $resulttx)) * 100 : 0 ]
181  if { ![ string equal $errormessage "" ]} {
182  lappend losspercentage "-error" $errormessage
183  }
184  # Return the result
185  lappend resultList $losspercentage
186  }
187  return $resultList
188  } else {
189  set numbers [ list ]
190  foreach flow $result {
191  set resulttx 0; set resultrx 0
192  set fresult [ list ]
193  foreach {item value} $flow {
194  switch -- $item {
195  -tx {
196  set resulttx [x.TxResult.FlowLoss.Parse $value]
197  lappend fresult "-tx" $resulttx
198  }
199  -rx {
200  if {$value != "NA"} {
201  set resultrx [x.RxResult.FlowLoss.Parse $value]
202  lappend fresult "-rx" $resultrx
203  } else {
204  lappend fresult "-rx" $value
205  }
206  }
207  -error {
208  puts stderr "ByteBlowerHL warning: Flow error detected. Loss percentage may be wrong. Error code: $value"
209  lappend fresult "-error" $value
210  }
211  }
212  }
213  lappend numbers $fresult
214  }
215  return $numbers
216  }
217 }
218 
219 proc x.RxParam.FlowLoss.Parse { rxparamlist } {
220  # Parses the rx port parameters.
221  # Removes latency and capture options.
222  # Removes non-basic trigger options.
223  #
224  # @return
225  # - list of rx parameters valid for framelosstest
226  # - empty list if no valid rx parameters were found
227 
228  set trigger ""
229  set found 0
230  set result [ list ]
231  foreach {item value} $rxparamlist {
232  switch -- $item {
233  -trigger {
234  if {$found == 0} {
235  set found 1
236  set trigger $value
237  } else {
238  error "Only 1 trigger allowed per rx port parameter list"
239  }
240  }
241  -latency {
242  # do nothing, latency will be ignored
243  }
244  -capture {
245  # do nothing, capture will be ignored
246  }
247  default {
248  lappend result $item $value
249  }
250  }
251  }
252 
253  if { $found == 0} {
254  # if there is no trigger option, the flow will be transmitted, but there is nothing to receive
255  return $result
256  }
257 
258  if { $trigger != ""} {
259  set filter ""; set type "basic"
260  foreach {item value} $trigger {
261  switch -- $item {
262  -type {
263  set type $value
264  if {$type != "basic"} {
265  # if the trigger type is other than basic, the flow will transmit, but not receive
266  return $result
267  }
268  }
269  -filterFormat {
270  set filterFormat $value
271  }
272  -filter {
273  set filter $value
274  }
275  -duration {}
276  default {
277  error "Not a valid trigger parameter: \"$item\""
278  }
279  }
280  }
281  lappend result "-trigger" $trigger
282  }
283 
284  return $result
285 }
286 
287 proc x.TxResult.FlowLoss.Parse {counter} {
288  # Parse the output from Tx.Stream.Counter.Brief.Get.
289  # This output is in the form: { NrOfFramesSent } { value } { FrameOid_1 } { value_1 } {FrameOid_2 } { value_2 } ....
290  # Where - value is the total number of frames sent
291  # - FrameOid_1 is the oid of the first frame
292  # - value_1 is the number of frames sent of the first frame
293  # - FrameOid_2 is the oid of the second frame
294  # - value_2 is the number of frames sent of the second frame
295  # - ...
296  #
297  # @return
298  # number of frames sent
299 
300  return [lindex $counter 1]
301 }
302 
303 proc x.RxResult.FlowLoss.Parse {counter} {
304  # Parse the output from Rx.Trigger.Basic.Counters.Get.
305  # This output is in the form: { NrOfFrames } { value }
306  # Where - value is the total number of frames received
307  #
308  # @return
309  # number of frames received
310 
311  return [lindex $counter 1]
312 }
313 
314 
315 }
316 
317 }