X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=tools%2Fpkt_gen%2Fxena%2Fxena.py;h=449ef5b4f125640266f8640c36338f63646e6e54;hb=1dc40afad832bca427058380a629634aa3cb104c;hp=99da4584eb95984e6adea8a6c99fb89259cb7f9c;hpb=1641271a83022cca9d4548839c0b54debf9c520f;p=vswitchperf.git diff --git a/tools/pkt_gen/xena/xena.py b/tools/pkt_gen/xena/xena.py index 99da4584..449ef5b4 100755 --- a/tools/pkt_gen/xena/xena.py +++ b/tools/pkt_gen/xena/xena.py @@ -25,11 +25,14 @@ Xena Traffic Generator Model # python imports import binascii import logging +import os import subprocess import sys from time import sleep import xml.etree.ElementTree as ET from collections import OrderedDict +# scapy imports +import scapy.layers.inet as inet # VSPerf imports from conf import settings @@ -48,9 +51,6 @@ from tools.pkt_gen.xena.XenaDriver import ( XenaManager, ) -# scapy imports -import scapy.layers.inet as inet - class Xena(ITrafficGenerator): """ @@ -67,6 +67,19 @@ class Xena(ITrafficGenerator): self._duration = None self.tx_stats = None self.rx_stats = None + self._log_handle = None + + user_home = os.path.expanduser('~') + self._log_path = '{}/Xena/Xena2544-2G/Logs/xena2544.log'.format( + user_home) + + # make the folder and log file if they doesn't exist + if not os.path.exists(self._log_path): + os.makedirs(os.path.dirname(self._log_path)) + + # empty the file contents + open(self._log_path, 'w').close() + @property def traffic_defaults(self): @@ -94,12 +107,14 @@ class Xena(ITrafficGenerator): if test_type == 'Throughput': results = OrderedDict() - results[ResultsConstants.THROUGHPUT_RX_FPS] = int( - root[0][1][0][1].get('PortRxPps')) - results[ResultsConstants.THROUGHPUT_RX_MBPS] = int( - root[0][1][0][1].get('PortRxBpsL1')) / 1000000 + results[ResultsConstants.THROUGHPUT_RX_FPS] = float( + root[0][1][0][0].get('PortRxPps')) + float( + root[0][1][0][1].get('PortRxPps')) + results[ResultsConstants.THROUGHPUT_RX_MBPS] = (float( + root[0][1][0][0].get('PortRxBpsL1')) + float( + root[0][1][0][1].get('PortRxBpsL1')))/ 1000000 results[ResultsConstants.THROUGHPUT_RX_PERCENT] = ( - 100 - int(root[0][1][0].get('TotalLossRatioPcnt'))) * float( + 100 - float(root[0][1][0].get('TotalLossRatioPcnt'))) * float( root[0][1][0].get('TotalTxRatePcnt'))/100 results[ResultsConstants.TX_RATE_FPS] = root[0][1][0].get( 'TotalTxRateFps') @@ -260,10 +275,10 @@ class Xena(ITrafficGenerator): return result_dict - def _setup_json_config(self, trials, loss_rate, testtype=None): + def _setup_json_config(self, tests, loss_rate, testtype=None): """ Create a 2bUsed json file that will be used for xena2544.exe execution. - :param trials: Number of trials + :param tests: Number of tests :param loss_rate: The acceptable loss rate as float :param testtype: Either '2544_b2b' or '2544_throughput' as string :return: None @@ -286,14 +301,23 @@ class Xena(ITrafficGenerator): 1, settings.getValue("TRAFFICGEN_XENA_PORT1_IP"), settings.getValue("TRAFFICGEN_XENA_PORT1_CIDR"), settings.getValue("TRAFFICGEN_XENA_PORT1_GATEWAY")) - j_file.set_test_options( - packet_sizes=self._params['traffic']['l2']['framesize'], - iterations=trials, loss_rate=loss_rate, - duration=self._duration, micro_tpld=True if self._params[ - 'traffic']['l2']['framesize'] == 64 else False) + if testtype == '2544_throughput': + j_file.set_test_options_tput( + packet_sizes=self._params['traffic']['l2']['framesize'], + iterations=tests, loss_rate=loss_rate, + duration=self._duration, micro_tpld=True if self._params[ + 'traffic']['l2']['framesize'] == 64 else False) j_file.enable_throughput_test() + elif testtype == '2544_b2b': + j_file.set_test_options_back2back( + packet_sizes=self._params['traffic']['l2']['framesize'], + iterations=tests, duration=self._duration, + startvalue=self._params['traffic']['frame_rate'], + endvalue=self._params['traffic']['frame_rate'], + micro_tpld=True if self._params[ + 'traffic']['l2']['framesize'] == 64 else False) j_file.enable_back2back_test() j_file.set_header_layer2( @@ -442,6 +466,44 @@ class Xena(ITrafficGenerator): self.rx_stats = self.xmanager.ports[1].get_rx_stats() sleep(1) + def _start_xena_2544(self): + """ + Start the xena2544 exe. + :return: None + """ + args = ["mono", "./tools/pkt_gen/xena/Xena2544.exe", "-c", + "./tools/pkt_gen/xena/profiles/2bUsed.x2544", "-e", "-r", + "./tools/pkt_gen/xena", "-u", + settings.getValue('TRAFFICGEN_XENA_USER')] + # Sometimes Xena2544.exe completes, but mono holds the process without + # releasing it, this can cause a deadlock of the main thread. Use the + # xena log file as a way to detect this. + self._log_handle = open(self._log_path, 'r') + # read the contents of the log before we start so the next read in the + # wait method are only looking at the text from this test instance + self._log_handle.read() + self.mono_pipe = subprocess.Popen(args, stdout=sys.stdout) + + def _wait_xena_2544_complete(self): + """ + Wait for Xena2544.exe completion. + :return: None + """ + data = '' + while True: + try: + self.mono_pipe.wait(60) + self._log_handle.close() + break + except subprocess.TimeoutExpired: + # check the log to see if Xena2544 has completed and mono is + # deadlocked. + data += self._log_handle.read() + if 'TestCompletedSuccessfully' in data: + self._log_handle.close() + self.mono_pipe.terminate() + break + def _stop_api_traffic(self): """ Stop traffic through the socket API @@ -483,22 +545,16 @@ class Xena(ITrafficGenerator): def send_burst_traffic(self, traffic=None, numpkts=100, duration=20): """Send a burst of traffic. - Send a ``numpkts`` packets of traffic, using ``traffic`` - configuration, with a timeout of ``time``. - - Attributes: - :param traffic: Detailed "traffic" spec, i.e. IP address, VLAN tags - :param numpkts: Number of packets to send - :param duration: Time to wait to receive packets - - :returns: dictionary of strings with following data: - - List of Tx Frames, - - List of Rx Frames, - - List of Tx Bytes, - - List of List of Rx Bytes, - - Payload Errors and Sequence Errors. + See ITrafficGenerator for description """ - raise NotImplementedError('Xena burst traffic not implemented') + self._duration = duration + self._params.clear() + self._params['traffic'] = self.traffic_defaults.copy() + if traffic: + self._params['traffic'] = merge_spec(self._params['traffic'], + traffic) + self._start_traffic_api(numpkts) + return self._stop_api_traffic() def send_cont_traffic(self, traffic=None, duration=20): """Send a continuous flow of traffic. @@ -512,7 +568,6 @@ class Xena(ITrafficGenerator): if traffic: self._params['traffic'] = merge_spec(self._params['traffic'], traffic) - self._start_traffic_api(-1) return self._stop_api_traffic() @@ -528,7 +583,6 @@ class Xena(ITrafficGenerator): if traffic: self._params['traffic'] = merge_spec(self._params['traffic'], traffic) - self._start_traffic_api(-1) def stop_cont_traffic(self): @@ -536,7 +590,7 @@ class Xena(ITrafficGenerator): """ return self._stop_api_traffic() - def send_rfc2544_throughput(self, traffic=None, trials=3, duration=20, + def send_rfc2544_throughput(self, traffic=None, tests=1, duration=20, lossrate=0.0): """Send traffic per RFC2544 throughput test specifications. @@ -549,19 +603,14 @@ class Xena(ITrafficGenerator): if traffic: self._params['traffic'] = merge_spec(self._params['traffic'], traffic) + self._setup_json_config(tests, lossrate, '2544_throughput') + self._start_xena_2544() + self._wait_xena_2544_complete() - self._setup_json_config(trials, lossrate, '2544_throughput') - - args = ["mono", "./tools/pkt_gen/xena/Xena2544.exe", "-c", - "./tools/pkt_gen/xena/profiles/2bUsed.x2544", "-e", "-r", - "./tools/pkt_gen/xena", "-u", - settings.getValue('TRAFFICGEN_XENA_USER')] - self.mono_pipe = subprocess.Popen(args, stdout=sys.stdout) - self.mono_pipe.communicate() root = ET.parse(r'./tools/pkt_gen/xena/xena2544-report.xml').getroot() return Xena._create_throughput_result(root) - def start_rfc2544_throughput(self, traffic=None, trials=3, duration=20, + def start_rfc2544_throughput(self, traffic=None, tests=1, duration=20, lossrate=0.0): """Non-blocking version of 'send_rfc2544_throughput'. @@ -573,26 +622,19 @@ class Xena(ITrafficGenerator): if traffic: self._params['traffic'] = merge_spec(self._params['traffic'], traffic) - - self._setup_json_config(trials, lossrate, '2544_throughput') - - args = ["mono", "./tools/pkt_gen/xena/Xena2544.exe", "-c", - "./tools/pkt_gen/xena/profiles/2bUsed.x2544", "-e", "-r", - "./tools/pkt_gen/xena", "-u", - settings.getValue('TRAFFICGEN_XENA_USER')] - self.mono_pipe = subprocess.Popen(args, stdout=sys.stdout) + self._setup_json_config(tests, lossrate, '2544_throughput') + self._start_xena_2544() def wait_rfc2544_throughput(self): """Wait for and return results of RFC2544 test. See ITrafficGenerator for description """ - self.mono_pipe.communicate() - sleep(2) + self._wait_xena_2544_complete() root = ET.parse(r'./tools/pkt_gen/xena/xena2544-report.xml').getroot() return Xena._create_throughput_result(root) - def send_rfc2544_back2back(self, traffic=None, trials=1, duration=20, + def send_rfc2544_back2back(self, traffic=None, tests=1, duration=20, lossrate=0.0): """Send traffic per RFC2544 back2back test specifications. @@ -605,47 +647,31 @@ class Xena(ITrafficGenerator): if traffic: self._params['traffic'] = merge_spec(self._params['traffic'], traffic) - - self._setup_json_config(trials, lossrate, '2544_b2b') - - args = ["mono", "./tools/pkt_gen/xena/Xena2544.exe", "-c", - "./tools/pkt_gen/xena/profiles/2bUsed.x2544", "-e", "-r", - "./tools/pkt_gen/xena", "-u", - settings.getValue('TRAFFICGEN_XENA_USER')] - self.mono_pipe = subprocess.Popen( - args, stdout=sys.stdout) - self.mono_pipe.communicate() + self._setup_json_config(tests, lossrate, '2544_b2b') + self._start_xena_2544() + self._wait_xena_2544_complete() root = ET.parse(r'./tools/pkt_gen/xena/xena2544-report.xml').getroot() return Xena._create_throughput_result(root) - def start_rfc2544_back2back(self, traffic=None, trials=1, duration=20, + def start_rfc2544_back2back(self, traffic=None, tests=1, duration=20, lossrate=0.0): """Non-blocking version of 'send_rfc2544_back2back'. See ITrafficGenerator for description """ self._duration = duration - self._params.clear() self._params['traffic'] = self.traffic_defaults.copy() if traffic: self._params['traffic'] = merge_spec(self._params['traffic'], traffic) - - self._setup_json_config(trials, lossrate, '2544_b2b') - - args = ["mono", "./tools/pkt_gen/xena/Xena2544.exe", "-c", - "./tools/pkt_gen/xena/profiles/2bUsed.x2544", "-e", "-r", - "./tools/pkt_gen/xena", "-u", - settings.getValue('TRAFFICGEN_XENA_USER')] - self.mono_pipe = subprocess.Popen( - args, stdout=sys.stdout) + self._setup_json_config(tests, lossrate, '2544_b2b') + self._start_xena_2544() def wait_rfc2544_back2back(self): """Wait and set results of RFC2544 test. """ - self.mono_pipe.communicate() - sleep(2) + self._wait_xena_2544_complete() root = ET.parse(r'./tools/pkt_gen/xena/xena2544-report.xml').getroot() return Xena._create_throughput_result(root)