summaryrefslogtreecommitdiffstats
path: root/tools/pkt_gen/xena/xena.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/pkt_gen/xena/xena.py')
-rwxr-xr-xtools/pkt_gen/xena/xena.py660
1 files changed, 660 insertions, 0 deletions
diff --git a/tools/pkt_gen/xena/xena.py b/tools/pkt_gen/xena/xena.py
new file mode 100755
index 00000000..7dd4b90b
--- /dev/null
+++ b/tools/pkt_gen/xena/xena.py
@@ -0,0 +1,660 @@
+# Copyright 2016 Red Hat Inc & Xena Networks.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Contributors:
+# Rick Alongi, Red Hat Inc.
+# Amit Supugade, Red Hat Inc.
+# Dan Amzulescu, Xena Networks
+# Christian Trautman, Red Hat Inc.
+
+"""
+Xena Traffic Generator Model
+"""
+
+# python imports
+import binascii
+import logging
+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
+from core.results.results_constants import ResultsConstants
+from tools.pkt_gen.trafficgen.trafficgenhelper import (
+ TRAFFIC_DEFAULTS,
+ merge_spec)
+from tools.pkt_gen.trafficgen.trafficgen import ITrafficGenerator
+
+# Xena module imports
+from tools.pkt_gen.xena.xena_json import XenaJSON
+from tools.pkt_gen.xena.XenaDriver import (
+ aggregate_stats,
+ line_percentage,
+ XenaSocketDriver,
+ XenaManager,
+ )
+
+class Xena(ITrafficGenerator):
+ """
+ Xena Traffic generator wrapper class
+ """
+ _traffic_defaults = TRAFFIC_DEFAULTS.copy()
+ _logger = logging.getLogger(__name__)
+
+ def __init__(self):
+ self.mono_pipe = None
+ self.xmanager = None
+ self._params = {}
+ self._xsocket = None
+ self._duration = None
+ self.tx_stats = None
+ self.rx_stats = None
+
+ @property
+ def traffic_defaults(self):
+ """Default traffic values.
+
+ These can be expected to be constant across traffic generators,
+ so no setter is provided. Changes to the structure or contents
+ will likely break traffic generator implementations or tests
+ respectively.
+ """
+ return self._traffic_defaults
+
+ @staticmethod
+ def _create_throughput_result(root):
+ """
+ Create the results based off the output xml file from the Xena2544.exe
+ execution
+ :param root: root dictionary from xml import
+ :return: Results Ordered dictionary based off ResultsConstants
+ """
+ # get the test type from the report file
+ test_type = root[0][1].get('TestType')
+ # set the version from the report file
+ settings.setValue('XENA_VERSION', root[0][0][1].get('GeneratedBy'))
+
+ if test_type == 'Throughput':
+ results = OrderedDict()
+ 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(
+ root[0][1][0].get('TotalTxRatePcnt'))/100
+ results[ResultsConstants.TX_RATE_FPS] = root[0][1][0].get(
+ 'TotalTxRateFps')
+ results[ResultsConstants.TX_RATE_MBPS] = float(
+ root[0][1][0].get('TotalTxRateBpsL1')) / 1000000
+ results[ResultsConstants.TX_RATE_PERCENT] = root[0][1][0].get(
+ 'TotalTxRatePcnt')
+ try:
+ results[ResultsConstants.MIN_LATENCY_NS] = float(
+ root[0][1][0][0].get('MinLatency')) * 1000
+ except ValueError:
+ # Stats for latency returned as N/A so just post them
+ results[ResultsConstants.MIN_LATENCY_NS] = root[0][1][0][0].get(
+ 'MinLatency')
+ try:
+ results[ResultsConstants.MAX_LATENCY_NS] = float(
+ root[0][1][0][0].get('MaxLatency')) * 1000
+ except ValueError:
+ # Stats for latency returned as N/A so just post them
+ results[ResultsConstants.MAX_LATENCY_NS] = root[0][1][0][0].get(
+ 'MaxLatency')
+ try:
+ results[ResultsConstants.AVG_LATENCY_NS] = float(
+ root[0][1][0][0].get('AvgLatency')) * 1000
+ except ValueError:
+ # Stats for latency returned as N/A so just post them
+ results[ResultsConstants.AVG_LATENCY_NS] = root[0][1][0][0].get(
+ 'AvgLatency')
+ elif test_type == 'Back2Back':
+ results = OrderedDict()
+
+ # Just mimic what Ixia does and only return the b2b frame count.
+ # This may change later once its decided the common results stats
+ # to be returned should be.
+ results[ResultsConstants.B2B_FRAMES] = root[0][1][0][0].get(
+ 'TotalTxBurstFrames')
+ else:
+ raise NotImplementedError('Unknown test type in report file.')
+
+ return results
+
+ def _build_packet_header(self, reverse=False):
+ """
+ Build a packet header based on traffic profile using scapy external
+ libraries.
+ :param reverse: Swap source and destination info when building header
+ :return: packet header in hex
+ """
+ srcmac = self._params['traffic']['l2'][
+ 'srcmac'] if not reverse else self._params['traffic']['l2'][
+ 'dstmac']
+ dstmac = self._params['traffic']['l2'][
+ 'dstmac'] if not reverse else self._params['traffic']['l2'][
+ 'srcmac']
+ srcip = self._params['traffic']['l3'][
+ 'srcip'] if not reverse else self._params['traffic']['l3']['dstip']
+ dstip = self._params['traffic']['l3'][
+ 'dstip'] if not reverse else self._params['traffic']['l3']['srcip']
+ layer2 = inet.Ether(src=srcmac, dst=dstmac)
+ layer3 = inet.IP(src=srcip, dst=dstip,
+ proto=self._params['traffic']['l3']['proto'])
+ layer4 = inet.UDP(sport=self._params['traffic']['l4']['srcport'],
+ dport=self._params['traffic']['l4']['dstport'])
+ if self._params['traffic']['vlan']['enabled']:
+ vlan = inet.Dot1Q(vlan=self._params['traffic']['vlan']['id'],
+ prio=self._params['traffic']['vlan']['priority'],
+ id=self._params['traffic']['vlan']['cfi'])
+ else:
+ vlan = None
+ packet = layer2/vlan/layer3/layer4 if vlan else layer2/layer3/layer4
+ packet_bytes = bytes(packet)
+ packet_hex = '0x' + binascii.hexlify(packet_bytes).decode('utf-8')
+ return packet_hex
+
+ def _create_api_result(self):
+ """
+ Create result dictionary per trafficgen specifications from socket API
+ stats. If stats are not available return values of 0.
+ :return: ResultsConstants as dictionary
+ """
+ # Handle each case of statistics based on if the data is available.
+ # This prevents uncaught exceptions when the stats aren't available.
+ result_dict = OrderedDict()
+ if self.tx_stats.data.get(self.tx_stats.pt_stream_keys[0]):
+ result_dict[ResultsConstants.TX_FRAMES] = self.tx_stats.data[
+ self.tx_stats.pt_stream_keys[0]]['packets']
+ result_dict[ResultsConstants.TX_RATE_FPS] = self.tx_stats.data[
+ self.tx_stats.pt_stream_keys[0]]['pps']
+ result_dict[ResultsConstants.TX_RATE_MBPS] = self.tx_stats.data[
+ self.tx_stats.pt_stream_keys[0]]['bps'] / 1000000
+ result_dict[ResultsConstants.TX_BYTES] = self.tx_stats.data[
+ self.tx_stats.pt_stream_keys[0]]['bytes']
+ # tx rate percent may need to be halved if bi directional
+ result_dict[ResultsConstants.TX_RATE_PERCENT] = line_percentage(
+ self.xmanager.ports[0], self.tx_stats, self._duration,
+ self._params['traffic']['l2']['framesize']) if \
+ self._params['traffic']['bidir'] == 'False' else\
+ line_percentage(
+ self.xmanager.ports[0], self.tx_stats, self._duration,
+ self._params['traffic']['l2']['framesize']) / 2
+ else:
+ self._logger.error('Transmit stats not available.')
+ result_dict[ResultsConstants.TX_FRAMES] = 0
+ result_dict[ResultsConstants.TX_RATE_FPS] = 0
+ result_dict[ResultsConstants.TX_RATE_MBPS] = 0
+ result_dict[ResultsConstants.TX_BYTES] = 0
+ result_dict[ResultsConstants.TX_RATE_PERCENT] = 0
+
+ if self.rx_stats.data.get('pr_tpldstraffic'):
+ result_dict[ResultsConstants.RX_FRAMES] = self.rx_stats.data[
+ 'pr_tpldstraffic']['0']['packets']
+ result_dict[
+ ResultsConstants.THROUGHPUT_RX_FPS] = self.rx_stats.data[
+ 'pr_tpldstraffic']['0']['pps']
+ result_dict[
+ ResultsConstants.THROUGHPUT_RX_MBPS] = self.rx_stats.data[
+ 'pr_tpldstraffic']['0']['bps'] / 1000000
+ result_dict[ResultsConstants.RX_BYTES] = self.rx_stats.data[
+ 'pr_tpldstraffic']['0']['bytes']
+ # throughput percent may need to be halved if bi directional
+ result_dict[
+ ResultsConstants.THROUGHPUT_RX_PERCENT] = line_percentage(
+ self.xmanager.ports[1], self.rx_stats, self._duration,
+ self._params['traffic']['l2']['framesize']) if \
+ self._params['traffic']['bidir'] == 'False' else \
+ line_percentage(
+ self.xmanager.ports[1], self.rx_stats, self._duration,
+ self._params['traffic']['l2']['framesize']) / 2
+
+ else:
+ self._logger.error('Receive stats not available.')
+ result_dict[ResultsConstants.RX_FRAMES] = 0
+ result_dict[ResultsConstants.THROUGHPUT_RX_FPS] = 0
+ result_dict[ResultsConstants.THROUGHPUT_RX_MBPS] = 0
+ result_dict[ResultsConstants.RX_BYTES] = 0
+ result_dict[ResultsConstants.THROUGHPUT_RX_PERCENT] = 0
+
+ if self.rx_stats.data.get('pr_tplderrors'):
+ result_dict[ResultsConstants.PAYLOAD_ERR] = self.rx_stats.data[
+ 'pr_tplderrors']['0']['pld']
+ result_dict[ResultsConstants.SEQ_ERR] = self.rx_stats.data[
+ 'pr_tplderrors']['0']['seq']
+ else:
+ result_dict[ResultsConstants.PAYLOAD_ERR] = 0
+ result_dict[ResultsConstants.SEQ_ERR] = 0
+
+ if self.rx_stats.data.get('pr_tpldlatency'):
+ result_dict[ResultsConstants.MIN_LATENCY_NS] = self.rx_stats.data[
+ 'pr_tpldlatency']['0']['min']
+ result_dict[ResultsConstants.MAX_LATENCY_NS] = self.rx_stats.data[
+ 'pr_tpldlatency']['0']['max']
+ result_dict[ResultsConstants.AVG_LATENCY_NS] = self.rx_stats.data[
+ 'pr_tpldlatency']['0']['avg']
+ else:
+ result_dict[ResultsConstants.MIN_LATENCY_NS] = 0
+ result_dict[ResultsConstants.MAX_LATENCY_NS] = 0
+ result_dict[ResultsConstants.AVG_LATENCY_NS] = 0
+
+ return result_dict
+
+ def _setup_json_config(self, trials, loss_rate, testtype=None):
+ """
+ Create a 2bUsed json file that will be used for xena2544.exe execution.
+ :param trials: Number of trials
+ :param loss_rate: The acceptable loss rate as float
+ :param testtype: Either '2544_b2b' or '2544_throughput' as string
+ :return: None
+ """
+ try:
+ j_file = XenaJSON('./tools/pkt_gen/xena/profiles/baseconfig.x2544')
+ j_file.set_chassis_info(
+ settings.getValue('TRAFFICGEN_XENA_IP'),
+ settings.getValue('TRAFFICGEN_XENA_PASSWORD')
+ )
+ j_file.set_port(0, settings.getValue('TRAFFICGEN_XENA_MODULE1'),
+ settings.getValue('TRAFFICGEN_XENA_PORT1'))
+ j_file.set_port(1, settings.getValue('TRAFFICGEN_XENA_MODULE2'),
+ settings.getValue('TRAFFICGEN_XENA_PORT2'))
+ j_file.set_port_ip_v4(
+ 0, settings.getValue("TRAFFICGEN_XENA_PORT0_IP"),
+ settings.getValue("TRAFFICGEN_XENA_PORT0_CIDR"),
+ settings.getValue("TRAFFICGEN_XENA_PORT0_GATEWAY"))
+ j_file.set_port_ip_v4(
+ 1, settings.getValue("TRAFFICGEN_XENA_PORT1_IP"),
+ settings.getValue("TRAFFICGEN_XENA_PORT1_CIDR"),
+ settings.getValue("TRAFFICGEN_XENA_PORT1_GATEWAY"))
+
+ if testtype == '2544_throughput':
+ j_file.set_test_options_tput(
+ 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)
+ j_file.enable_throughput_test()
+
+ elif testtype == '2544_b2b':
+ j_file.set_test_options_back2back(
+ packet_sizes=self._params['traffic']['l2']['framesize'],
+ iterations=trials, 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(
+ dst_mac=self._params['traffic']['l2']['dstmac'],
+ src_mac=self._params['traffic']['l2']['srcmac'])
+ j_file.set_header_layer3(
+ src_ip=self._params['traffic']['l3']['srcip'],
+ dst_ip=self._params['traffic']['l3']['dstip'],
+ protocol=self._params['traffic']['l3']['proto'])
+ j_file.set_header_layer4_udp(
+ source_port=self._params['traffic']['l4']['srcport'],
+ destination_port=self._params['traffic']['l4']['dstport'])
+ if self._params['traffic']['vlan']['enabled']:
+ j_file.set_header_vlan(
+ vlan_id=self._params['traffic']['vlan']['id'],
+ id=self._params['traffic']['vlan']['cfi'],
+ prio=self._params['traffic']['vlan']['priority'])
+ j_file.add_header_segments(
+ flows=self._params['traffic']['multistream'],
+ multistream_layer=self._params['traffic']['stream_type'])
+ # set duplex mode
+ if self._params['traffic']['bidir'] == "True":
+ j_file.set_topology_mesh()
+ else:
+ j_file.set_topology_blocks()
+
+ j_file.write_config('./tools/pkt_gen/xena/profiles/2bUsed.x2544')
+ except Exception as exc:
+ self._logger.exception("Error during Xena JSON setup: %s", exc)
+ raise
+
+ def _start_traffic_api(self, packet_limit):
+ """
+ Start the Xena traffic using the socket API driver
+ :param packet_limit: packet limit for stream, set to -1 for no limit
+ :return: None
+ """
+ if not self.xmanager:
+ self._xsocket = XenaSocketDriver(
+ settings.getValue('TRAFFICGEN_XENA_IP'))
+ self.xmanager = XenaManager(
+ self._xsocket, settings.getValue('TRAFFICGEN_XENA_USER'),
+ settings.getValue('TRAFFICGEN_XENA_PASSWORD'))
+
+ # for the report file version info ask the chassis directly for its
+ # software versions
+ settings.setValue('XENA_VERSION', 'XENA Socket API - {}'.format(
+ self.xmanager.get_version()))
+
+ if not len(self.xmanager.ports):
+ self.xmanager.ports[0] = self.xmanager.add_module_port(
+ settings.getValue('TRAFFICGEN_XENA_MODULE1'),
+ settings.getValue('TRAFFICGEN_XENA_PORT1'))
+ if not self.xmanager.ports[0].reserve_port():
+ self._logger.error(
+ 'Unable to reserve port 0. Please release Xena Port')
+
+ if len(self.xmanager.ports) < 2:
+ self.xmanager.ports[1] = self.xmanager.add_module_port(
+ settings.getValue('TRAFFICGEN_XENA_MODULE2'),
+ settings.getValue('TRAFFICGEN_XENA_PORT2'))
+ if not self.xmanager.ports[1].reserve_port():
+ self._logger.error(
+ 'Unable to reserve port 1. Please release Xena Port')
+
+ # Clear port configuration for a clean start
+ self.xmanager.ports[0].reset_port()
+ self.xmanager.ports[1].reset_port()
+ self.xmanager.ports[0].clear_stats()
+ self.xmanager.ports[1].clear_stats()
+
+ # set the port IP from the conf file
+ self.xmanager.ports[0].set_port_ip(
+ settings.getValue('TRAFFICGEN_XENA_PORT0_IP'),
+ settings.getValue('TRAFFICGEN_XENA_PORT0_CIDR'),
+ settings.getValue('TRAFFICGEN_XENA_PORT0_GATEWAY'))
+ self.xmanager.ports[1].set_port_ip(
+ settings.getValue('TRAFFICGEN_XENA_PORT1_IP'),
+ settings.getValue('TRAFFICGEN_XENA_PORT1_CIDR'),
+ settings.getValue('TRAFFICGEN_XENA_PORT1_GATEWAY'))
+
+ def setup_stream(stream, port, payload_id, flip_addr=False):
+ """
+ Helper function to configure streams.
+ :param stream: Stream object from XenaDriver module
+ :param port: Port object from XenaDriver module
+ :param payload_id: payload ID as int
+ :param flip_addr: Boolean if the source and destination addresses
+ should be flipped.
+ :return: None
+ """
+ stream.set_on()
+ stream.set_packet_limit(packet_limit)
+
+ stream.set_rate_fraction(
+ 10000 * self._params['traffic']['frame_rate'])
+ stream.set_packet_header(self._build_packet_header(
+ reverse=flip_addr))
+ stream.set_header_protocol(
+ 'ETHERNET VLAN IP UDP' if self._params['traffic']['vlan'][
+ 'enabled'] else 'ETHERNET IP UDP')
+ stream.set_packet_length(
+ 'fixed', self._params['traffic']['l2']['framesize'], 16383)
+ stream.set_packet_payload('incrementing', '0x00')
+ stream.set_payload_id(payload_id)
+ port.set_port_time_limit(self._duration * 1000000)
+
+ if self._params['traffic']['l2']['framesize'] == 64:
+ # set micro tpld
+ port.micro_tpld_enable()
+
+ if self._params['traffic']['multistream']:
+ stream.enable_multistream(
+ flows=self._params['traffic']['multistream'],
+ layer=self._params['traffic']['stream_type'])
+
+ s1_p0 = self.xmanager.ports[0].add_stream()
+ setup_stream(s1_p0, self.xmanager.ports[0], 0)
+
+ if self._params['traffic']['bidir'] == 'True':
+ s1_p1 = self.xmanager.ports[1].add_stream()
+ setup_stream(s1_p1, self.xmanager.ports[1], 1, flip_addr=True)
+
+ if not self.xmanager.ports[0].traffic_on():
+ self._logger.error(
+ "Failure to start port 0. Check settings and retry.")
+ if self._params['traffic']['bidir'] == 'True':
+ if not self.xmanager.ports[1].traffic_on():
+ self._logger.error(
+ "Failure to start port 1. Check settings and retry.")
+ sleep(self._duration)
+ # getting results
+ if self._params['traffic']['bidir'] == 'True':
+ # need to aggregate out both ports stats and assign that data
+ self.rx_stats = self.xmanager.ports[1].get_rx_stats()
+ self.tx_stats = self.xmanager.ports[0].get_tx_stats()
+ self.tx_stats.data = aggregate_stats(
+ self.tx_stats.data,
+ self.xmanager.ports[1].get_tx_stats().data)
+ self.rx_stats.data = aggregate_stats(
+ self.rx_stats.data,
+ self.xmanager.ports[0].get_rx_stats().data)
+ else:
+ # no need to aggregate, just grab the appropriate port stats
+ self.tx_stats = self.xmanager.ports[0].get_tx_stats()
+ self.rx_stats = self.xmanager.ports[1].get_rx_stats()
+ sleep(1)
+
+ def _stop_api_traffic(self):
+ """
+ Stop traffic through the socket API
+ :return: Return results from _create_api_result method
+ """
+ self.xmanager.ports[0].traffic_off()
+ if self._params['traffic']['bidir'] == 'True':
+ self.xmanager.ports[1].traffic_off()
+ sleep(5)
+
+ stat = self._create_api_result()
+ self.disconnect()
+ return stat
+
+ def connect(self):
+ self._logger.debug('Connect')
+ return self
+
+ def disconnect(self):
+ """Disconnect from the traffic generator.
+
+ As with :func:`connect`, this function is optional.
+
+
+ Where implemented, this function should raise an exception on
+ failure.
+
+ :returns: None
+ """
+ self._logger.debug('disconnect')
+ if self.xmanager:
+ self.xmanager.disconnect()
+ self.xmanager = None
+
+ if self._xsocket:
+ self._xsocket.disconnect()
+ self._xsocket = None
+
+ def send_burst_traffic(self, traffic=None, numpkts=100, duration=20):
+ """Send a burst of traffic.
+
+ 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._start_traffic_api(numpkts)
+ return self._stop_api_traffic()
+
+ def send_cont_traffic(self, traffic=None, duration=20):
+ """Send a continuous flow of traffic.
+
+ 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._start_traffic_api(-1)
+ return self._stop_api_traffic()
+
+ def start_cont_traffic(self, traffic=None, duration=20):
+ """Non-blocking version of 'send_cont_traffic'.
+
+ 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._start_traffic_api(-1)
+
+ def stop_cont_traffic(self):
+ """Stop continuous transmission and return results.
+ """
+ return self._stop_api_traffic()
+
+ def send_rfc2544_throughput(self, traffic=None, trials=3, duration=20,
+ lossrate=0.0):
+ """Send traffic per RFC2544 throughput test specifications.
+
+ 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_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,
+ lossrate=0.0):
+ """Non-blocking version of 'send_rfc2544_throughput'.
+
+ 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_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)
+
+ def wait_rfc2544_throughput(self):
+ """Wait for and return results of RFC2544 test.
+
+ See ITrafficGenerator for description
+ """
+ self.mono_pipe.communicate()
+ sleep(2)
+ 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,
+ lossrate=0.0):
+ """Send traffic per RFC2544 back2back test specifications.
+
+ 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.mono_pipe.communicate()
+ 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,
+ 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)
+
+ def wait_rfc2544_back2back(self):
+ """Wait and set results of RFC2544 test.
+ """
+ self.mono_pipe.communicate()
+ sleep(2)
+ root = ET.parse(r'./tools/pkt_gen/xena/xena2544-report.xml').getroot()
+ return Xena._create_throughput_result(root)
+
+
+if __name__ == "__main__":
+ pass
+