1 # Copyright 2016 Red Hat Inc & Xena Networks.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
16 # Rick Alongi, Red Hat Inc.
17 # Amit Supugade, Red Hat Inc.
18 # Dan Amzulescu, Xena Networks
19 # Christian Trautman, Red Hat Inc.
22 Xena Traffic Generator Model
31 from time import sleep
32 import xml.etree.ElementTree as ET
33 from collections import OrderedDict
35 import scapy.layers.inet as inet
38 from conf import settings
39 from core.results.results_constants import ResultsConstants
40 from tools.pkt_gen.trafficgen.trafficgenhelper import (
43 from tools.pkt_gen.trafficgen.trafficgen import ITrafficGenerator
46 from tools.pkt_gen.xena.xena_json import XenaJSON
47 from tools.pkt_gen.xena.XenaDriver import (
55 class Xena(ITrafficGenerator):
57 Xena Traffic generator wrapper class
59 _traffic_defaults = TRAFFIC_DEFAULTS.copy()
60 _logger = logging.getLogger(__name__)
70 self._log_handle = None
72 user_home = os.path.expanduser('~')
73 self._log_path = '{}/Xena/Xena2544-2G/Logs/xena2544.log'.format(
76 # make the folder and log file if they doesn't exist
77 if not os.path.exists(self._log_path):
78 os.makedirs(os.path.dirname(self._log_path))
80 # empty the file contents
81 open(self._log_path, 'w').close()
85 def traffic_defaults(self):
86 """Default traffic values.
88 These can be expected to be constant across traffic generators,
89 so no setter is provided. Changes to the structure or contents
90 will likely break traffic generator implementations or tests
93 return self._traffic_defaults
96 def _create_throughput_result(root):
98 Create the results based off the output xml file from the Xena2544.exe
100 :param root: root dictionary from xml import
101 :return: Results Ordered dictionary based off ResultsConstants
103 # get the test type from the report file
104 test_type = root[0][1].get('TestType')
105 # set the version from the report file
106 settings.setValue('XENA_VERSION', root[0][0][1].get('GeneratedBy'))
108 if test_type == 'Throughput':
109 results = OrderedDict()
110 results[ResultsConstants.THROUGHPUT_RX_FPS] = float(
111 root[0][1][0][0].get('PortRxPps')) + float(
112 root[0][1][0][1].get('PortRxPps'))
113 results[ResultsConstants.THROUGHPUT_RX_MBPS] = (float(
114 root[0][1][0][0].get('PortRxBpsL1')) + float(
115 root[0][1][0][1].get('PortRxBpsL1')))/ 1000000
116 results[ResultsConstants.THROUGHPUT_RX_PERCENT] = (
117 100 - float(root[0][1][0].get('TotalLossRatioPcnt'))) * float(
118 root[0][1][0].get('TotalTxRatePcnt'))/100
119 results[ResultsConstants.TX_RATE_FPS] = root[0][1][0].get(
121 results[ResultsConstants.TX_RATE_MBPS] = float(
122 root[0][1][0].get('TotalTxRateBpsL1')) / 1000000
123 results[ResultsConstants.TX_RATE_PERCENT] = root[0][1][0].get(
126 results[ResultsConstants.MIN_LATENCY_NS] = float(
127 root[0][1][0][0].get('MinLatency')) * 1000
129 # Stats for latency returned as N/A so just post them
130 results[ResultsConstants.MIN_LATENCY_NS] = root[0][1][0][0].get(
133 results[ResultsConstants.MAX_LATENCY_NS] = float(
134 root[0][1][0][0].get('MaxLatency')) * 1000
136 # Stats for latency returned as N/A so just post them
137 results[ResultsConstants.MAX_LATENCY_NS] = root[0][1][0][0].get(
140 results[ResultsConstants.AVG_LATENCY_NS] = float(
141 root[0][1][0][0].get('AvgLatency')) * 1000
143 # Stats for latency returned as N/A so just post them
144 results[ResultsConstants.AVG_LATENCY_NS] = root[0][1][0][0].get(
146 elif test_type == 'Back2Back':
147 results = OrderedDict()
149 # Just mimic what Ixia does and only return the b2b frame count.
150 # This may change later once its decided the common results stats
151 # to be returned should be.
152 results[ResultsConstants.B2B_FRAMES] = root[0][1][0][0].get(
153 'TotalTxBurstFrames')
155 raise NotImplementedError('Unknown test type in report file.')
159 def _build_packet_header(self, reverse=False):
161 Build a packet header based on traffic profile using scapy external
163 :param reverse: Swap source and destination info when building header
164 :return: packet header in hex
166 srcmac = self._params['traffic']['l2'][
167 'srcmac'] if not reverse else self._params['traffic']['l2'][
169 dstmac = self._params['traffic']['l2'][
170 'dstmac'] if not reverse else self._params['traffic']['l2'][
172 srcip = self._params['traffic']['l3'][
173 'srcip'] if not reverse else self._params['traffic']['l3']['dstip']
174 dstip = self._params['traffic']['l3'][
175 'dstip'] if not reverse else self._params['traffic']['l3']['srcip']
176 layer2 = inet.Ether(src=srcmac, dst=dstmac)
177 layer3 = inet.IP(src=srcip, dst=dstip,
178 proto=self._params['traffic']['l3']['proto'])
179 layer4 = inet.UDP(sport=self._params['traffic']['l4']['srcport'],
180 dport=self._params['traffic']['l4']['dstport'])
181 if self._params['traffic']['vlan']['enabled']:
182 vlan = inet.Dot1Q(vlan=self._params['traffic']['vlan']['id'],
183 prio=self._params['traffic']['vlan']['priority'],
184 id=self._params['traffic']['vlan']['cfi'])
187 packet = layer2/vlan/layer3/layer4 if vlan else layer2/layer3/layer4
188 packet_bytes = bytes(packet)
189 packet_hex = '0x' + binascii.hexlify(packet_bytes).decode('utf-8')
192 def _create_api_result(self):
194 Create result dictionary per trafficgen specifications from socket API
195 stats. If stats are not available return values of 0.
196 :return: ResultsConstants as dictionary
198 # Handle each case of statistics based on if the data is available.
199 # This prevents uncaught exceptions when the stats aren't available.
200 result_dict = OrderedDict()
201 if self.tx_stats.data.get(self.tx_stats.pt_stream_keys[0]):
202 result_dict[ResultsConstants.TX_FRAMES] = self.tx_stats.data[
203 self.tx_stats.pt_stream_keys[0]]['packets']
204 result_dict[ResultsConstants.TX_RATE_FPS] = self.tx_stats.data[
205 self.tx_stats.pt_stream_keys[0]]['pps']
206 result_dict[ResultsConstants.TX_RATE_MBPS] = self.tx_stats.data[
207 self.tx_stats.pt_stream_keys[0]]['bps'] / 1000000
208 result_dict[ResultsConstants.TX_BYTES] = self.tx_stats.data[
209 self.tx_stats.pt_stream_keys[0]]['bytes']
210 # tx rate percent may need to be halved if bi directional
211 result_dict[ResultsConstants.TX_RATE_PERCENT] = line_percentage(
212 self.xmanager.ports[0], self.tx_stats, self._duration,
213 self._params['traffic']['l2']['framesize']) if \
214 self._params['traffic']['bidir'] == 'False' else\
216 self.xmanager.ports[0], self.tx_stats, self._duration,
217 self._params['traffic']['l2']['framesize']) / 2
219 self._logger.error('Transmit stats not available.')
220 result_dict[ResultsConstants.TX_FRAMES] = 0
221 result_dict[ResultsConstants.TX_RATE_FPS] = 0
222 result_dict[ResultsConstants.TX_RATE_MBPS] = 0
223 result_dict[ResultsConstants.TX_BYTES] = 0
224 result_dict[ResultsConstants.TX_RATE_PERCENT] = 0
226 if self.rx_stats.data.get('pr_tpldstraffic'):
227 result_dict[ResultsConstants.RX_FRAMES] = self.rx_stats.data[
228 'pr_tpldstraffic']['0']['packets']
230 ResultsConstants.THROUGHPUT_RX_FPS] = self.rx_stats.data[
231 'pr_tpldstraffic']['0']['pps']
233 ResultsConstants.THROUGHPUT_RX_MBPS] = self.rx_stats.data[
234 'pr_tpldstraffic']['0']['bps'] / 1000000
235 result_dict[ResultsConstants.RX_BYTES] = self.rx_stats.data[
236 'pr_tpldstraffic']['0']['bytes']
237 # throughput percent may need to be halved if bi directional
239 ResultsConstants.THROUGHPUT_RX_PERCENT] = line_percentage(
240 self.xmanager.ports[1], self.rx_stats, self._duration,
241 self._params['traffic']['l2']['framesize']) if \
242 self._params['traffic']['bidir'] == 'False' else \
244 self.xmanager.ports[1], self.rx_stats, self._duration,
245 self._params['traffic']['l2']['framesize']) / 2
248 self._logger.error('Receive stats not available.')
249 result_dict[ResultsConstants.RX_FRAMES] = 0
250 result_dict[ResultsConstants.THROUGHPUT_RX_FPS] = 0
251 result_dict[ResultsConstants.THROUGHPUT_RX_MBPS] = 0
252 result_dict[ResultsConstants.RX_BYTES] = 0
253 result_dict[ResultsConstants.THROUGHPUT_RX_PERCENT] = 0
255 if self.rx_stats.data.get('pr_tplderrors'):
256 result_dict[ResultsConstants.PAYLOAD_ERR] = self.rx_stats.data[
257 'pr_tplderrors']['0']['pld']
258 result_dict[ResultsConstants.SEQ_ERR] = self.rx_stats.data[
259 'pr_tplderrors']['0']['seq']
261 result_dict[ResultsConstants.PAYLOAD_ERR] = 0
262 result_dict[ResultsConstants.SEQ_ERR] = 0
264 if self.rx_stats.data.get('pr_tpldlatency'):
265 result_dict[ResultsConstants.MIN_LATENCY_NS] = self.rx_stats.data[
266 'pr_tpldlatency']['0']['min']
267 result_dict[ResultsConstants.MAX_LATENCY_NS] = self.rx_stats.data[
268 'pr_tpldlatency']['0']['max']
269 result_dict[ResultsConstants.AVG_LATENCY_NS] = self.rx_stats.data[
270 'pr_tpldlatency']['0']['avg']
272 result_dict[ResultsConstants.MIN_LATENCY_NS] = 0
273 result_dict[ResultsConstants.MAX_LATENCY_NS] = 0
274 result_dict[ResultsConstants.AVG_LATENCY_NS] = 0
278 def _setup_json_config(self, tests, loss_rate, testtype=None):
280 Create a 2bUsed json file that will be used for xena2544.exe execution.
281 :param tests: Number of tests
282 :param loss_rate: The acceptable loss rate as float
283 :param testtype: Either '2544_b2b' or '2544_throughput' as string
287 j_file = XenaJSON('./tools/pkt_gen/xena/profiles/baseconfig.x2544')
288 j_file.set_chassis_info(
289 settings.getValue('TRAFFICGEN_XENA_IP'),
290 settings.getValue('TRAFFICGEN_XENA_PASSWORD')
292 j_file.set_port(0, settings.getValue('TRAFFICGEN_XENA_MODULE1'),
293 settings.getValue('TRAFFICGEN_XENA_PORT1'))
294 j_file.set_port(1, settings.getValue('TRAFFICGEN_XENA_MODULE2'),
295 settings.getValue('TRAFFICGEN_XENA_PORT2'))
296 j_file.set_port_ip_v4(
297 0, settings.getValue("TRAFFICGEN_XENA_PORT0_IP"),
298 settings.getValue("TRAFFICGEN_XENA_PORT0_CIDR"),
299 settings.getValue("TRAFFICGEN_XENA_PORT0_GATEWAY"))
300 j_file.set_port_ip_v4(
301 1, settings.getValue("TRAFFICGEN_XENA_PORT1_IP"),
302 settings.getValue("TRAFFICGEN_XENA_PORT1_CIDR"),
303 settings.getValue("TRAFFICGEN_XENA_PORT1_GATEWAY"))
305 if testtype == '2544_throughput':
306 j_file.set_test_options_tput(
307 packet_sizes=self._params['traffic']['l2']['framesize'],
308 iterations=tests, loss_rate=loss_rate,
309 duration=self._duration, micro_tpld=True if self._params[
310 'traffic']['l2']['framesize'] == 64 else False)
311 j_file.enable_throughput_test()
312 j_file.modify_2544_tput_options(
313 settings.getValue('TRAFFICGEN_XENA_2544_TPUT_INIT_VALUE'),
314 settings.getValue('TRAFFICGEN_XENA_2544_TPUT_MIN_VALUE'),
315 settings.getValue('TRAFFICGEN_XENA_2544_TPUT_MAX_VALUE'),
317 'TRAFFICGEN_XENA_2544_TPUT_VALUE_RESOLUTION'),
319 'TRAFFICGEN_XENA_2544_TPUT_USEPASS_THRESHHOLD'),
321 'TRAFFICGEN_XENA_2544_TPUT_PASS_THRESHHOLD')
324 elif testtype == '2544_b2b':
325 j_file.set_test_options_back2back(
326 packet_sizes=self._params['traffic']['l2']['framesize'],
327 iterations=tests, duration=self._duration,
328 startvalue=self._params['traffic']['frame_rate'],
329 endvalue=self._params['traffic']['frame_rate'],
330 micro_tpld=True if self._params[
331 'traffic']['l2']['framesize'] == 64 else False)
332 j_file.enable_back2back_test()
334 j_file.set_header_layer2(
335 dst_mac=self._params['traffic']['l2']['dstmac'],
336 src_mac=self._params['traffic']['l2']['srcmac'])
337 j_file.set_header_layer3(
338 src_ip=self._params['traffic']['l3']['srcip'],
339 dst_ip=self._params['traffic']['l3']['dstip'],
340 protocol=self._params['traffic']['l3']['proto'])
341 j_file.set_header_layer4_udp(
342 source_port=self._params['traffic']['l4']['srcport'],
343 destination_port=self._params['traffic']['l4']['dstport'])
344 if self._params['traffic']['vlan']['enabled']:
345 j_file.set_header_vlan(
346 vlan_id=self._params['traffic']['vlan']['id'],
347 id=self._params['traffic']['vlan']['cfi'],
348 prio=self._params['traffic']['vlan']['priority'])
349 j_file.add_header_segments(
350 flows=self._params['traffic']['multistream'],
351 multistream_layer=self._params['traffic']['stream_type'])
353 if self._params['traffic']['bidir'] == "True":
354 j_file.set_topology_mesh()
356 j_file.set_topology_blocks()
358 j_file.write_config('./tools/pkt_gen/xena/profiles/2bUsed.x2544')
359 except Exception as exc:
360 self._logger.exception("Error during Xena JSON setup: %s", exc)
363 def _start_traffic_api(self, packet_limit):
365 Start the Xena traffic using the socket API driver
366 :param packet_limit: packet limit for stream, set to -1 for no limit
369 if not self.xmanager:
370 self._xsocket = XenaSocketDriver(
371 settings.getValue('TRAFFICGEN_XENA_IP'))
372 self.xmanager = XenaManager(
373 self._xsocket, settings.getValue('TRAFFICGEN_XENA_USER'),
374 settings.getValue('TRAFFICGEN_XENA_PASSWORD'))
376 # for the report file version info ask the chassis directly for its
378 settings.setValue('XENA_VERSION', 'XENA Socket API - {}'.format(
379 self.xmanager.get_version()))
381 if not len(self.xmanager.ports):
382 self.xmanager.ports[0] = self.xmanager.add_module_port(
383 settings.getValue('TRAFFICGEN_XENA_MODULE1'),
384 settings.getValue('TRAFFICGEN_XENA_PORT1'))
385 if not self.xmanager.ports[0].reserve_port():
387 'Unable to reserve port 0. Please release Xena Port')
389 if len(self.xmanager.ports) < 2:
390 self.xmanager.ports[1] = self.xmanager.add_module_port(
391 settings.getValue('TRAFFICGEN_XENA_MODULE2'),
392 settings.getValue('TRAFFICGEN_XENA_PORT2'))
393 if not self.xmanager.ports[1].reserve_port():
395 'Unable to reserve port 1. Please release Xena Port')
397 # Clear port configuration for a clean start
398 self.xmanager.ports[0].reset_port()
399 self.xmanager.ports[1].reset_port()
400 self.xmanager.ports[0].clear_stats()
401 self.xmanager.ports[1].clear_stats()
403 # set the port IP from the conf file
404 self.xmanager.ports[0].set_port_ip(
405 settings.getValue('TRAFFICGEN_XENA_PORT0_IP'),
406 settings.getValue('TRAFFICGEN_XENA_PORT0_CIDR'),
407 settings.getValue('TRAFFICGEN_XENA_PORT0_GATEWAY'))
408 self.xmanager.ports[1].set_port_ip(
409 settings.getValue('TRAFFICGEN_XENA_PORT1_IP'),
410 settings.getValue('TRAFFICGEN_XENA_PORT1_CIDR'),
411 settings.getValue('TRAFFICGEN_XENA_PORT1_GATEWAY'))
413 def setup_stream(stream, port, payload_id, flip_addr=False):
415 Helper function to configure streams.
416 :param stream: Stream object from XenaDriver module
417 :param port: Port object from XenaDriver module
418 :param payload_id: payload ID as int
419 :param flip_addr: Boolean if the source and destination addresses
424 if packet_limit != -1:
425 stream.set_packet_limit(packet_limit)
427 speed = port.get_port_speed() / 8 # convert to bytes
428 gap = port.get_inter_frame_gap()
429 pkt_size = self._params['traffic']['l2']['framesize']
430 packets = int(((speed / (pkt_size + gap)) * self._duration) *
431 (self._params['traffic']['frame_rate'] / 100))
432 stream.set_packet_limit(packets)
434 port.set_port_arp_reply(on=True)
435 port.set_port_arp_reply(on=True, v6=True)
436 port.set_port_ping_reply(on=True)
437 port.set_port_ping_reply(on=True, v6=True)
439 stream.set_rate_fraction(
440 10000 * self._params['traffic']['frame_rate'])
441 stream.set_packet_header(self._build_packet_header(
443 stream.set_header_protocol(
444 'ETHERNET VLAN IP UDP' if self._params['traffic']['vlan'][
445 'enabled'] else 'ETHERNET IP UDP')
446 stream.set_packet_length(
447 'fixed', self._params['traffic']['l2']['framesize'],
448 self._params['traffic']['l2']['framesize'])
449 stream.set_packet_payload('incrementing', '0x00')
450 stream.set_payload_id(payload_id)
451 port.set_port_time_limit(0)
453 if self._params['traffic']['l2']['framesize'] == 64:
455 port.micro_tpld_enable()
457 if self._params['traffic']['multistream']:
458 stream.enable_multistream(
459 flows=self._params['traffic']['multistream'],
460 layer=self._params['traffic']['stream_type'])
462 s1_p0 = self.xmanager.ports[0].add_stream()
463 setup_stream(s1_p0, self.xmanager.ports[0], 0)
465 if self._params['traffic']['bidir'] == 'True':
466 s1_p1 = self.xmanager.ports[1].add_stream()
467 setup_stream(s1_p1, self.xmanager.ports[1], 1, flip_addr=True)
469 if not self.xmanager.ports[0].traffic_on():
471 "Failure to start port 0. Check settings and retry.")
472 if self._params['traffic']['bidir'] == 'True':
473 if not self.xmanager.ports[1].traffic_on():
475 "Failure to start port 1. Check settings and retry.")
476 sleep(self._duration + 1)
478 if self._params['traffic']['bidir'] == 'True':
479 # need to aggregate out both ports stats and assign that data
480 self.rx_stats = self.xmanager.ports[1].get_rx_stats()
481 self.tx_stats = self.xmanager.ports[0].get_tx_stats()
482 self.tx_stats.data = aggregate_stats(
484 self.xmanager.ports[1].get_tx_stats().data)
485 self.rx_stats.data = aggregate_stats(
487 self.xmanager.ports[0].get_rx_stats().data)
489 # no need to aggregate, just grab the appropriate port stats
490 self.tx_stats = self.xmanager.ports[0].get_tx_stats()
491 self.rx_stats = self.xmanager.ports[1].get_rx_stats()
494 def _start_xena_2544(self):
496 Start the xena2544 exe.
499 args = ["mono", "./tools/pkt_gen/xena/Xena2544.exe", "-c",
500 "./tools/pkt_gen/xena/profiles/2bUsed.x2544", "-e", "-r",
501 "./tools/pkt_gen/xena", "-u",
502 settings.getValue('TRAFFICGEN_XENA_USER')]
503 # Sometimes Xena2544.exe completes, but mono holds the process without
504 # releasing it, this can cause a deadlock of the main thread. Use the
505 # xena log file as a way to detect this.
506 self._log_handle = open(self._log_path, 'r')
507 # read the contents of the log before we start so the next read in the
508 # wait method are only looking at the text from this test instance
509 self._log_handle.read()
510 self.mono_pipe = subprocess.Popen(args, stdout=sys.stdout)
512 def _wait_xena_2544_complete(self):
514 Wait for Xena2544.exe completion.
520 self.mono_pipe.wait(60)
521 self._log_handle.close()
523 except subprocess.TimeoutExpired:
524 # check the log to see if Xena2544 has completed and mono is
526 data += self._log_handle.read()
527 if 'TestCompletedSuccessfully' in data:
528 self._log_handle.close()
529 self.mono_pipe.terminate()
532 def _stop_api_traffic(self):
534 Stop traffic through the socket API
535 :return: Return results from _create_api_result method
537 self.xmanager.ports[0].traffic_off()
538 if self._params['traffic']['bidir'] == 'True':
539 self.xmanager.ports[1].traffic_off()
542 stat = self._create_api_result()
547 self._logger.debug('Connect')
550 def disconnect(self):
551 """Disconnect from the traffic generator.
553 As with :func:`connect`, this function is optional.
556 Where implemented, this function should raise an exception on
561 self._logger.debug('disconnect')
563 self.xmanager.disconnect()
567 self._xsocket.disconnect()
570 def send_burst_traffic(self, traffic=None, numpkts=100, duration=20):
571 """Send a burst of traffic.
573 See ITrafficGenerator for description
575 self._duration = duration
577 self._params['traffic'] = self.traffic_defaults.copy()
579 self._params['traffic'] = merge_spec(self._params['traffic'],
581 self._start_traffic_api(numpkts)
582 return self._stop_api_traffic()
584 def send_cont_traffic(self, traffic=None, duration=20):
585 """Send a continuous flow of traffic.
587 See ITrafficGenerator for description
589 self._duration = duration
592 self._params['traffic'] = self.traffic_defaults.copy()
594 self._params['traffic'] = merge_spec(self._params['traffic'],
596 self._start_traffic_api(-1)
597 return self._stop_api_traffic()
599 def start_cont_traffic(self, traffic=None, duration=20):
600 """Non-blocking version of 'send_cont_traffic'.
602 See ITrafficGenerator for description
604 self._duration = duration
607 self._params['traffic'] = self.traffic_defaults.copy()
609 self._params['traffic'] = merge_spec(self._params['traffic'],
611 self._start_traffic_api(-1)
613 def stop_cont_traffic(self):
614 """Stop continuous transmission and return results.
616 return self._stop_api_traffic()
618 def send_rfc2544_throughput(self, traffic=None, tests=1, duration=20,
620 """Send traffic per RFC2544 throughput test specifications.
622 See ITrafficGenerator for description
624 self._duration = duration
627 self._params['traffic'] = self.traffic_defaults.copy()
629 self._params['traffic'] = merge_spec(self._params['traffic'],
631 self._setup_json_config(tests, lossrate, '2544_throughput')
632 self._start_xena_2544()
633 self._wait_xena_2544_complete()
635 root = ET.parse(r'./tools/pkt_gen/xena/xena2544-report.xml').getroot()
636 return Xena._create_throughput_result(root)
638 def start_rfc2544_throughput(self, traffic=None, tests=1, duration=20,
640 """Non-blocking version of 'send_rfc2544_throughput'.
642 See ITrafficGenerator for description
644 self._duration = duration
646 self._params['traffic'] = self.traffic_defaults.copy()
648 self._params['traffic'] = merge_spec(self._params['traffic'],
650 self._setup_json_config(tests, lossrate, '2544_throughput')
651 self._start_xena_2544()
653 def wait_rfc2544_throughput(self):
654 """Wait for and return results of RFC2544 test.
656 See ITrafficGenerator for description
658 self._wait_xena_2544_complete()
659 root = ET.parse(r'./tools/pkt_gen/xena/xena2544-report.xml').getroot()
660 return Xena._create_throughput_result(root)
662 def send_rfc2544_back2back(self, traffic=None, tests=1, duration=20,
664 """Send traffic per RFC2544 back2back test specifications.
666 See ITrafficGenerator for description
668 self._duration = duration
671 self._params['traffic'] = self.traffic_defaults.copy()
673 self._params['traffic'] = merge_spec(self._params['traffic'],
675 self._setup_json_config(tests, lossrate, '2544_b2b')
676 self._start_xena_2544()
677 self._wait_xena_2544_complete()
678 root = ET.parse(r'./tools/pkt_gen/xena/xena2544-report.xml').getroot()
679 return Xena._create_throughput_result(root)
681 def start_rfc2544_back2back(self, traffic=None, tests=1, duration=20,
683 """Non-blocking version of 'send_rfc2544_back2back'.
685 See ITrafficGenerator for description
687 self._duration = duration
689 self._params['traffic'] = self.traffic_defaults.copy()
691 self._params['traffic'] = merge_spec(self._params['traffic'],
693 self._setup_json_config(tests, lossrate, '2544_b2b')
694 self._start_xena_2544()
696 def wait_rfc2544_back2back(self):
697 """Wait and set results of RFC2544 test.
699 self._wait_xena_2544_complete()
700 root = ET.parse(r'./tools/pkt_gen/xena/xena2544-report.xml').getroot()
701 return Xena._create_throughput_result(root)
704 if __name__ == "__main__":