Merge "Namespace_veth: Add funtionality for network namespace, veth ports"
[vswitchperf.git] / tools / pkt_gen / xena / xena.py
1 # Copyright 2016 Red Hat Inc & Xena Networks.
2 #
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
6 #
7 #   http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14 #
15 # Contributors:
16 #   Rick Alongi, Red Hat Inc.
17 #   Amit Supugade, Red Hat Inc.
18 #   Dan Amzulescu, Xena Networks
19 #   Christian Trautman, Red Hat Inc.
20
21 """
22 Xena Traffic Generator Model
23 """
24
25 # python imports
26 import binascii
27 import logging
28 import subprocess
29 import sys
30 from time import sleep
31 import xml.etree.ElementTree as ET
32 from collections import OrderedDict
33 # scapy imports
34 import scapy.layers.inet as inet
35
36 # VSPerf imports
37 from conf import settings
38 from core.results.results_constants import ResultsConstants
39 from tools.pkt_gen.trafficgen.trafficgenhelper import (
40     TRAFFIC_DEFAULTS,
41     merge_spec)
42 from tools.pkt_gen.trafficgen.trafficgen import ITrafficGenerator
43
44 # Xena module imports
45 from tools.pkt_gen.xena.xena_json import XenaJSON
46 from tools.pkt_gen.xena.XenaDriver import (
47     aggregate_stats,
48     line_percentage,
49     XenaSocketDriver,
50     XenaManager,
51     )
52
53 class Xena(ITrafficGenerator):
54     """
55     Xena Traffic generator wrapper class
56     """
57     _traffic_defaults = TRAFFIC_DEFAULTS.copy()
58     _logger = logging.getLogger(__name__)
59
60     def __init__(self):
61         self.mono_pipe = None
62         self.xmanager = None
63         self._params = {}
64         self._xsocket = None
65         self._duration = None
66         self.tx_stats = None
67         self.rx_stats = None
68
69     @property
70     def traffic_defaults(self):
71         """Default traffic values.
72
73         These can be expected to be constant across traffic generators,
74         so no setter is provided. Changes to the structure or contents
75         will likely break traffic generator implementations or tests
76         respectively.
77         """
78         return self._traffic_defaults
79
80     @staticmethod
81     def _create_throughput_result(root):
82         """
83         Create the results based off the output xml file from the Xena2544.exe
84         execution
85         :param root: root dictionary from xml import
86         :return: Results Ordered dictionary based off ResultsConstants
87         """
88         # get the test type from the report file
89         test_type = root[0][1].get('TestType')
90         # set the version from the report file
91         settings.setValue('XENA_VERSION', root[0][0][1].get('GeneratedBy'))
92
93         if test_type == 'Throughput':
94             results = OrderedDict()
95             results[ResultsConstants.THROUGHPUT_RX_FPS] = float(
96                 root[0][1][0][0].get('PortRxPps')) + float(
97                     root[0][1][0][1].get('PortRxPps'))
98             results[ResultsConstants.THROUGHPUT_RX_MBPS] = (float(
99                 root[0][1][0][0].get('PortRxBpsL1')) + float(
100                     root[0][1][0][1].get('PortRxBpsL1')))/ 1000000
101             results[ResultsConstants.THROUGHPUT_RX_PERCENT] = (
102                 100 - int(root[0][1][0].get('TotalLossRatioPcnt'))) * float(
103                     root[0][1][0].get('TotalTxRatePcnt'))/100
104             results[ResultsConstants.TX_RATE_FPS] = root[0][1][0].get(
105                 'TotalTxRateFps')
106             results[ResultsConstants.TX_RATE_MBPS] = float(
107                 root[0][1][0].get('TotalTxRateBpsL1')) / 1000000
108             results[ResultsConstants.TX_RATE_PERCENT] = root[0][1][0].get(
109                 'TotalTxRatePcnt')
110             try:
111                 results[ResultsConstants.MIN_LATENCY_NS] = float(
112                     root[0][1][0][0].get('MinLatency')) * 1000
113             except ValueError:
114                 # Stats for latency returned as N/A so just post them
115                 results[ResultsConstants.MIN_LATENCY_NS] = root[0][1][0][0].get(
116                     'MinLatency')
117             try:
118                 results[ResultsConstants.MAX_LATENCY_NS] = float(
119                     root[0][1][0][0].get('MaxLatency')) * 1000
120             except ValueError:
121                 # Stats for latency returned as N/A so just post them
122                 results[ResultsConstants.MAX_LATENCY_NS] = root[0][1][0][0].get(
123                     'MaxLatency')
124             try:
125                 results[ResultsConstants.AVG_LATENCY_NS] = float(
126                     root[0][1][0][0].get('AvgLatency')) * 1000
127             except ValueError:
128                 # Stats for latency returned as N/A so just post them
129                 results[ResultsConstants.AVG_LATENCY_NS] = root[0][1][0][0].get(
130                     'AvgLatency')
131         elif test_type == 'Back2Back':
132             results = OrderedDict()
133
134             # Just mimic what Ixia does and only return the b2b frame count.
135             # This may change later once its decided the common results stats
136             # to be returned should be.
137             results[ResultsConstants.B2B_FRAMES] = root[0][1][0][0].get(
138                 'TotalTxBurstFrames')
139         else:
140             raise NotImplementedError('Unknown test type in report file.')
141
142         return results
143
144     def _build_packet_header(self, reverse=False):
145         """
146         Build a packet header based on traffic profile using scapy external
147         libraries.
148         :param reverse: Swap source and destination info when building header
149         :return: packet header in hex
150         """
151         srcmac = self._params['traffic']['l2'][
152             'srcmac'] if not reverse else self._params['traffic']['l2'][
153                 'dstmac']
154         dstmac = self._params['traffic']['l2'][
155             'dstmac'] if not reverse else self._params['traffic']['l2'][
156                 'srcmac']
157         srcip = self._params['traffic']['l3'][
158             'srcip'] if not reverse else self._params['traffic']['l3']['dstip']
159         dstip = self._params['traffic']['l3'][
160             'dstip'] if not reverse else self._params['traffic']['l3']['srcip']
161         layer2 = inet.Ether(src=srcmac, dst=dstmac)
162         layer3 = inet.IP(src=srcip, dst=dstip,
163                          proto=self._params['traffic']['l3']['proto'])
164         layer4 = inet.UDP(sport=self._params['traffic']['l4']['srcport'],
165                           dport=self._params['traffic']['l4']['dstport'])
166         if self._params['traffic']['vlan']['enabled']:
167             vlan = inet.Dot1Q(vlan=self._params['traffic']['vlan']['id'],
168                               prio=self._params['traffic']['vlan']['priority'],
169                               id=self._params['traffic']['vlan']['cfi'])
170         else:
171             vlan = None
172         packet = layer2/vlan/layer3/layer4 if vlan else layer2/layer3/layer4
173         packet_bytes = bytes(packet)
174         packet_hex = '0x' + binascii.hexlify(packet_bytes).decode('utf-8')
175         return packet_hex
176
177     def _create_api_result(self):
178         """
179         Create result dictionary per trafficgen specifications from socket API
180         stats. If stats are not available return values of 0.
181         :return: ResultsConstants as dictionary
182         """
183         # Handle each case of statistics based on if the data is available.
184         # This prevents uncaught exceptions when the stats aren't available.
185         result_dict = OrderedDict()
186         if self.tx_stats.data.get(self.tx_stats.pt_stream_keys[0]):
187             result_dict[ResultsConstants.TX_FRAMES] = self.tx_stats.data[
188                 self.tx_stats.pt_stream_keys[0]]['packets']
189             result_dict[ResultsConstants.TX_RATE_FPS] = self.tx_stats.data[
190                 self.tx_stats.pt_stream_keys[0]]['pps']
191             result_dict[ResultsConstants.TX_RATE_MBPS] = self.tx_stats.data[
192                 self.tx_stats.pt_stream_keys[0]]['bps'] / 1000000
193             result_dict[ResultsConstants.TX_BYTES] = self.tx_stats.data[
194                 self.tx_stats.pt_stream_keys[0]]['bytes']
195             # tx rate percent may need to be halved if bi directional
196             result_dict[ResultsConstants.TX_RATE_PERCENT] = line_percentage(
197                 self.xmanager.ports[0], self.tx_stats, self._duration,
198                 self._params['traffic']['l2']['framesize']) if \
199                 self._params['traffic']['bidir'] == 'False' else\
200                 line_percentage(
201                     self.xmanager.ports[0], self.tx_stats, self._duration,
202                     self._params['traffic']['l2']['framesize']) / 2
203         else:
204             self._logger.error('Transmit stats not available.')
205             result_dict[ResultsConstants.TX_FRAMES] = 0
206             result_dict[ResultsConstants.TX_RATE_FPS] = 0
207             result_dict[ResultsConstants.TX_RATE_MBPS] = 0
208             result_dict[ResultsConstants.TX_BYTES] = 0
209             result_dict[ResultsConstants.TX_RATE_PERCENT] = 0
210
211         if self.rx_stats.data.get('pr_tpldstraffic'):
212             result_dict[ResultsConstants.RX_FRAMES] = self.rx_stats.data[
213                 'pr_tpldstraffic']['0']['packets']
214             result_dict[
215                 ResultsConstants.THROUGHPUT_RX_FPS] = self.rx_stats.data[
216                     'pr_tpldstraffic']['0']['pps']
217             result_dict[
218                 ResultsConstants.THROUGHPUT_RX_MBPS] = self.rx_stats.data[
219                     'pr_tpldstraffic']['0']['bps'] / 1000000
220             result_dict[ResultsConstants.RX_BYTES] = self.rx_stats.data[
221                 'pr_tpldstraffic']['0']['bytes']
222             # throughput percent may need to be halved if bi directional
223             result_dict[
224                 ResultsConstants.THROUGHPUT_RX_PERCENT] = line_percentage(
225                     self.xmanager.ports[1], self.rx_stats, self._duration,
226                     self._params['traffic']['l2']['framesize']) if \
227                 self._params['traffic']['bidir'] == 'False' else \
228                 line_percentage(
229                     self.xmanager.ports[1], self.rx_stats, self._duration,
230                     self._params['traffic']['l2']['framesize']) / 2
231
232         else:
233             self._logger.error('Receive stats not available.')
234             result_dict[ResultsConstants.RX_FRAMES] = 0
235             result_dict[ResultsConstants.THROUGHPUT_RX_FPS] = 0
236             result_dict[ResultsConstants.THROUGHPUT_RX_MBPS] = 0
237             result_dict[ResultsConstants.RX_BYTES] = 0
238             result_dict[ResultsConstants.THROUGHPUT_RX_PERCENT] = 0
239
240         if self.rx_stats.data.get('pr_tplderrors'):
241             result_dict[ResultsConstants.PAYLOAD_ERR] = self.rx_stats.data[
242                 'pr_tplderrors']['0']['pld']
243             result_dict[ResultsConstants.SEQ_ERR] = self.rx_stats.data[
244                 'pr_tplderrors']['0']['seq']
245         else:
246             result_dict[ResultsConstants.PAYLOAD_ERR] = 0
247             result_dict[ResultsConstants.SEQ_ERR] = 0
248
249         if self.rx_stats.data.get('pr_tpldlatency'):
250             result_dict[ResultsConstants.MIN_LATENCY_NS] = self.rx_stats.data[
251                 'pr_tpldlatency']['0']['min']
252             result_dict[ResultsConstants.MAX_LATENCY_NS] = self.rx_stats.data[
253                 'pr_tpldlatency']['0']['max']
254             result_dict[ResultsConstants.AVG_LATENCY_NS] = self.rx_stats.data[
255                 'pr_tpldlatency']['0']['avg']
256         else:
257             result_dict[ResultsConstants.MIN_LATENCY_NS] = 0
258             result_dict[ResultsConstants.MAX_LATENCY_NS] = 0
259             result_dict[ResultsConstants.AVG_LATENCY_NS] = 0
260
261         return result_dict
262
263     def _setup_json_config(self, trials, loss_rate, testtype=None):
264         """
265         Create a 2bUsed json file that will be used for xena2544.exe execution.
266         :param trials: Number of trials
267         :param loss_rate: The acceptable loss rate as float
268         :param testtype: Either '2544_b2b' or '2544_throughput' as string
269         :return: None
270         """
271         try:
272             j_file = XenaJSON('./tools/pkt_gen/xena/profiles/baseconfig.x2544')
273             j_file.set_chassis_info(
274                 settings.getValue('TRAFFICGEN_XENA_IP'),
275                 settings.getValue('TRAFFICGEN_XENA_PASSWORD')
276             )
277             j_file.set_port(0, settings.getValue('TRAFFICGEN_XENA_MODULE1'),
278                             settings.getValue('TRAFFICGEN_XENA_PORT1'))
279             j_file.set_port(1, settings.getValue('TRAFFICGEN_XENA_MODULE2'),
280                             settings.getValue('TRAFFICGEN_XENA_PORT2'))
281             j_file.set_port_ip_v4(
282                 0, settings.getValue("TRAFFICGEN_XENA_PORT0_IP"),
283                 settings.getValue("TRAFFICGEN_XENA_PORT0_CIDR"),
284                 settings.getValue("TRAFFICGEN_XENA_PORT0_GATEWAY"))
285             j_file.set_port_ip_v4(
286                 1, settings.getValue("TRAFFICGEN_XENA_PORT1_IP"),
287                 settings.getValue("TRAFFICGEN_XENA_PORT1_CIDR"),
288                 settings.getValue("TRAFFICGEN_XENA_PORT1_GATEWAY"))
289
290             if testtype == '2544_throughput':
291                 j_file.set_test_options_tput(
292                     packet_sizes=self._params['traffic']['l2']['framesize'],
293                     iterations=trials, loss_rate=loss_rate,
294                     duration=self._duration, micro_tpld=True if self._params[
295                         'traffic']['l2']['framesize'] == 64 else False)
296                 j_file.enable_throughput_test()
297
298             elif testtype == '2544_b2b':
299                 j_file.set_test_options_back2back(
300                     packet_sizes=self._params['traffic']['l2']['framesize'],
301                     iterations=trials, duration=self._duration,
302                     startvalue=self._params['traffic']['frame_rate'],
303                     endvalue=self._params['traffic']['frame_rate'],
304                     micro_tpld=True if self._params[
305                         'traffic']['l2']['framesize'] == 64 else False)
306                 j_file.enable_back2back_test()
307
308             j_file.set_header_layer2(
309                 dst_mac=self._params['traffic']['l2']['dstmac'],
310                 src_mac=self._params['traffic']['l2']['srcmac'])
311             j_file.set_header_layer3(
312                 src_ip=self._params['traffic']['l3']['srcip'],
313                 dst_ip=self._params['traffic']['l3']['dstip'],
314                 protocol=self._params['traffic']['l3']['proto'])
315             j_file.set_header_layer4_udp(
316                 source_port=self._params['traffic']['l4']['srcport'],
317                 destination_port=self._params['traffic']['l4']['dstport'])
318             if self._params['traffic']['vlan']['enabled']:
319                 j_file.set_header_vlan(
320                     vlan_id=self._params['traffic']['vlan']['id'],
321                     id=self._params['traffic']['vlan']['cfi'],
322                     prio=self._params['traffic']['vlan']['priority'])
323             j_file.add_header_segments(
324                 flows=self._params['traffic']['multistream'],
325                 multistream_layer=self._params['traffic']['stream_type'])
326             # set duplex mode
327             if self._params['traffic']['bidir'] == "True":
328                 j_file.set_topology_mesh()
329             else:
330                 j_file.set_topology_blocks()
331
332             j_file.write_config('./tools/pkt_gen/xena/profiles/2bUsed.x2544')
333         except Exception as exc:
334             self._logger.exception("Error during Xena JSON setup: %s", exc)
335             raise
336
337     def _start_traffic_api(self, packet_limit):
338         """
339         Start the Xena traffic using the socket API driver
340         :param packet_limit: packet limit for stream, set to -1 for no limit
341         :return: None
342         """
343         if not self.xmanager:
344             self._xsocket = XenaSocketDriver(
345                 settings.getValue('TRAFFICGEN_XENA_IP'))
346             self.xmanager = XenaManager(
347                 self._xsocket, settings.getValue('TRAFFICGEN_XENA_USER'),
348                 settings.getValue('TRAFFICGEN_XENA_PASSWORD'))
349
350         # for the report file version info ask the chassis directly for its
351         # software versions
352         settings.setValue('XENA_VERSION', 'XENA Socket API - {}'.format(
353             self.xmanager.get_version()))
354
355         if not len(self.xmanager.ports):
356             self.xmanager.ports[0] = self.xmanager.add_module_port(
357                 settings.getValue('TRAFFICGEN_XENA_MODULE1'),
358                 settings.getValue('TRAFFICGEN_XENA_PORT1'))
359             if not self.xmanager.ports[0].reserve_port():
360                 self._logger.error(
361                     'Unable to reserve port 0. Please release Xena Port')
362
363         if len(self.xmanager.ports) < 2:
364             self.xmanager.ports[1] = self.xmanager.add_module_port(
365                 settings.getValue('TRAFFICGEN_XENA_MODULE2'),
366                 settings.getValue('TRAFFICGEN_XENA_PORT2'))
367             if not self.xmanager.ports[1].reserve_port():
368                 self._logger.error(
369                     'Unable to reserve port 1. Please release Xena Port')
370
371         # Clear port configuration for a clean start
372         self.xmanager.ports[0].reset_port()
373         self.xmanager.ports[1].reset_port()
374         self.xmanager.ports[0].clear_stats()
375         self.xmanager.ports[1].clear_stats()
376
377         # set the port IP from the conf file
378         self.xmanager.ports[0].set_port_ip(
379             settings.getValue('TRAFFICGEN_XENA_PORT0_IP'),
380             settings.getValue('TRAFFICGEN_XENA_PORT0_CIDR'),
381             settings.getValue('TRAFFICGEN_XENA_PORT0_GATEWAY'))
382         self.xmanager.ports[1].set_port_ip(
383             settings.getValue('TRAFFICGEN_XENA_PORT1_IP'),
384             settings.getValue('TRAFFICGEN_XENA_PORT1_CIDR'),
385             settings.getValue('TRAFFICGEN_XENA_PORT1_GATEWAY'))
386
387         def setup_stream(stream, port, payload_id, flip_addr=False):
388             """
389             Helper function to configure streams.
390             :param stream: Stream object from XenaDriver module
391             :param port: Port object from XenaDriver module
392             :param payload_id: payload ID as int
393             :param flip_addr: Boolean if the source and destination addresses
394             should be flipped.
395             :return: None
396             """
397             stream.set_on()
398             stream.set_packet_limit(packet_limit)
399
400             stream.set_rate_fraction(
401                 10000 * self._params['traffic']['frame_rate'])
402             stream.set_packet_header(self._build_packet_header(
403                 reverse=flip_addr))
404             stream.set_header_protocol(
405                 'ETHERNET VLAN IP UDP' if self._params['traffic']['vlan'][
406                     'enabled'] else 'ETHERNET IP UDP')
407             stream.set_packet_length(
408                 'fixed', self._params['traffic']['l2']['framesize'], 16383)
409             stream.set_packet_payload('incrementing', '0x00')
410             stream.set_payload_id(payload_id)
411             port.set_port_time_limit(self._duration * 1000000)
412
413             if self._params['traffic']['l2']['framesize'] == 64:
414                 # set micro tpld
415                 port.micro_tpld_enable()
416
417             if self._params['traffic']['multistream']:
418                 stream.enable_multistream(
419                     flows=self._params['traffic']['multistream'],
420                     layer=self._params['traffic']['stream_type'])
421
422         s1_p0 = self.xmanager.ports[0].add_stream()
423         setup_stream(s1_p0, self.xmanager.ports[0], 0)
424
425         if self._params['traffic']['bidir'] == 'True':
426             s1_p1 = self.xmanager.ports[1].add_stream()
427             setup_stream(s1_p1, self.xmanager.ports[1], 1, flip_addr=True)
428
429         if not self.xmanager.ports[0].traffic_on():
430             self._logger.error(
431                 "Failure to start port 0. Check settings and retry.")
432         if self._params['traffic']['bidir'] == 'True':
433             if not self.xmanager.ports[1].traffic_on():
434                 self._logger.error(
435                     "Failure to start port 1. Check settings and retry.")
436         sleep(self._duration)
437         # getting results
438         if self._params['traffic']['bidir'] == 'True':
439             # need to aggregate out both ports stats and assign that data
440             self.rx_stats = self.xmanager.ports[1].get_rx_stats()
441             self.tx_stats = self.xmanager.ports[0].get_tx_stats()
442             self.tx_stats.data = aggregate_stats(
443                 self.tx_stats.data,
444                 self.xmanager.ports[1].get_tx_stats().data)
445             self.rx_stats.data = aggregate_stats(
446                 self.rx_stats.data,
447                 self.xmanager.ports[0].get_rx_stats().data)
448         else:
449             # no need to aggregate, just grab the appropriate port stats
450             self.tx_stats = self.xmanager.ports[0].get_tx_stats()
451             self.rx_stats = self.xmanager.ports[1].get_rx_stats()
452         sleep(1)
453
454     def _stop_api_traffic(self):
455         """
456         Stop traffic through the socket API
457         :return: Return results from _create_api_result method
458         """
459         self.xmanager.ports[0].traffic_off()
460         if self._params['traffic']['bidir'] == 'True':
461             self.xmanager.ports[1].traffic_off()
462         sleep(5)
463
464         stat = self._create_api_result()
465         self.disconnect()
466         return stat
467
468     def connect(self):
469         self._logger.debug('Connect')
470         return self
471
472     def disconnect(self):
473         """Disconnect from the traffic generator.
474
475         As with :func:`connect`, this function is optional.
476
477
478         Where implemented, this function should raise an exception on
479         failure.
480
481         :returns: None
482         """
483         self._logger.debug('disconnect')
484         if self.xmanager:
485             self.xmanager.disconnect()
486             self.xmanager = None
487
488         if self._xsocket:
489             self._xsocket.disconnect()
490             self._xsocket = None
491
492     def send_burst_traffic(self, traffic=None, numpkts=100, duration=20):
493         """Send a burst of traffic.
494
495         See ITrafficGenerator for description
496         """
497         self._duration = duration
498
499         self._params.clear()
500         self._params['traffic'] = self.traffic_defaults.copy()
501         if traffic:
502             self._params['traffic'] = merge_spec(self._params['traffic'],
503                                                  traffic)
504
505         self._start_traffic_api(numpkts)
506         return self._stop_api_traffic()
507
508     def send_cont_traffic(self, traffic=None, duration=20):
509         """Send a continuous flow of traffic.
510
511         See ITrafficGenerator for description
512         """
513         self._duration = duration
514
515         self._params.clear()
516         self._params['traffic'] = self.traffic_defaults.copy()
517         if traffic:
518             self._params['traffic'] = merge_spec(self._params['traffic'],
519                                                  traffic)
520
521         self._start_traffic_api(-1)
522         return self._stop_api_traffic()
523
524     def start_cont_traffic(self, traffic=None, duration=20):
525         """Non-blocking version of 'send_cont_traffic'.
526
527         See ITrafficGenerator for description
528         """
529         self._duration = duration
530
531         self._params.clear()
532         self._params['traffic'] = self.traffic_defaults.copy()
533         if traffic:
534             self._params['traffic'] = merge_spec(self._params['traffic'],
535                                                  traffic)
536
537         self._start_traffic_api(-1)
538
539     def stop_cont_traffic(self):
540         """Stop continuous transmission and return results.
541         """
542         return self._stop_api_traffic()
543
544     def send_rfc2544_throughput(self, traffic=None, trials=3, duration=20,
545                                 lossrate=0.0):
546         """Send traffic per RFC2544 throughput test specifications.
547
548         See ITrafficGenerator for description
549         """
550         self._duration = duration
551
552         self._params.clear()
553         self._params['traffic'] = self.traffic_defaults.copy()
554         if traffic:
555             self._params['traffic'] = merge_spec(self._params['traffic'],
556                                                  traffic)
557
558         self._setup_json_config(trials, lossrate, '2544_throughput')
559
560         args = ["mono", "./tools/pkt_gen/xena/Xena2544.exe", "-c",
561                 "./tools/pkt_gen/xena/profiles/2bUsed.x2544", "-e", "-r",
562                 "./tools/pkt_gen/xena", "-u",
563                 settings.getValue('TRAFFICGEN_XENA_USER')]
564         self.mono_pipe = subprocess.Popen(args, stdout=sys.stdout)
565         self.mono_pipe.communicate()
566         root = ET.parse(r'./tools/pkt_gen/xena/xena2544-report.xml').getroot()
567         return Xena._create_throughput_result(root)
568
569     def start_rfc2544_throughput(self, traffic=None, trials=3, duration=20,
570                                  lossrate=0.0):
571         """Non-blocking version of 'send_rfc2544_throughput'.
572
573         See ITrafficGenerator for description
574         """
575         self._duration = duration
576         self._params.clear()
577         self._params['traffic'] = self.traffic_defaults.copy()
578         if traffic:
579             self._params['traffic'] = merge_spec(self._params['traffic'],
580                                                  traffic)
581
582         self._setup_json_config(trials, lossrate, '2544_throughput')
583
584         args = ["mono", "./tools/pkt_gen/xena/Xena2544.exe", "-c",
585                 "./tools/pkt_gen/xena/profiles/2bUsed.x2544", "-e", "-r",
586                 "./tools/pkt_gen/xena", "-u",
587                 settings.getValue('TRAFFICGEN_XENA_USER')]
588         self.mono_pipe = subprocess.Popen(args, stdout=sys.stdout)
589
590     def wait_rfc2544_throughput(self):
591         """Wait for and return results of RFC2544 test.
592
593         See ITrafficGenerator for description
594         """
595         self.mono_pipe.communicate()
596         sleep(2)
597         root = ET.parse(r'./tools/pkt_gen/xena/xena2544-report.xml').getroot()
598         return Xena._create_throughput_result(root)
599
600     def send_rfc2544_back2back(self, traffic=None, trials=1, duration=20,
601                                lossrate=0.0):
602         """Send traffic per RFC2544 back2back test specifications.
603
604         See ITrafficGenerator for description
605         """
606         self._duration = duration
607
608         self._params.clear()
609         self._params['traffic'] = self.traffic_defaults.copy()
610         if traffic:
611             self._params['traffic'] = merge_spec(self._params['traffic'],
612                                                  traffic)
613
614         self._setup_json_config(trials, lossrate, '2544_b2b')
615
616         args = ["mono", "./tools/pkt_gen/xena/Xena2544.exe", "-c",
617                 "./tools/pkt_gen/xena/profiles/2bUsed.x2544", "-e", "-r",
618                 "./tools/pkt_gen/xena", "-u",
619                 settings.getValue('TRAFFICGEN_XENA_USER')]
620         self.mono_pipe = subprocess.Popen(
621             args, stdout=sys.stdout)
622         self.mono_pipe.communicate()
623         root = ET.parse(r'./tools/pkt_gen/xena/xena2544-report.xml').getroot()
624         return Xena._create_throughput_result(root)
625
626     def start_rfc2544_back2back(self, traffic=None, trials=1, duration=20,
627                                 lossrate=0.0):
628         """Non-blocking version of 'send_rfc2544_back2back'.
629
630         See ITrafficGenerator for description
631         """
632         self._duration = duration
633
634         self._params.clear()
635         self._params['traffic'] = self.traffic_defaults.copy()
636         if traffic:
637             self._params['traffic'] = merge_spec(self._params['traffic'],
638                                                  traffic)
639
640         self._setup_json_config(trials, lossrate, '2544_b2b')
641
642         args = ["mono", "./tools/pkt_gen/xena/Xena2544.exe", "-c",
643                 "./tools/pkt_gen/xena/profiles/2bUsed.x2544", "-e", "-r",
644                 "./tools/pkt_gen/xena", "-u",
645                 settings.getValue('TRAFFICGEN_XENA_USER')]
646         self.mono_pipe = subprocess.Popen(
647             args, stdout=sys.stdout)
648
649     def wait_rfc2544_back2back(self):
650         """Wait and set results of RFC2544 test.
651         """
652         self.mono_pipe.communicate()
653         sleep(2)
654         root = ET.parse(r'./tools/pkt_gen/xena/xena2544-report.xml').getroot()
655         return Xena._create_throughput_result(root)
656
657
658 if __name__ == "__main__":
659     pass
660