summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/hugepages.py133
-rw-r--r--tools/namespace.py4
-rw-r--r--tools/networkcard.py2
-rwxr-xr-xtools/pkt_gen/dummy/dummy.py10
-rwxr-xr-xtools/pkt_gen/ixia/ixia.py6
-rwxr-xr-xtools/pkt_gen/ixia/pass_fail.tcl5
-rwxr-xr-xtools/pkt_gen/ixnet/ixnet.py20
-rw-r--r--tools/pkt_gen/ixnet/ixnetrfc2544.tcl11
-rwxr-xr-xtools/pkt_gen/ixnet/ixnetrfc2544v2.tcl11
-rw-r--r--tools/pkt_gen/moongen/moongen.py167
-rw-r--r--tools/pkt_gen/testcenter/testcenter.py4
-rwxr-xr-xtools/pkt_gen/trafficgen/trafficgen.py12
-rw-r--r--tools/pkt_gen/xena/XenaDriver.py16
-rwxr-xr-xtools/pkt_gen/xena/xena.py138
-rw-r--r--tools/pkt_gen/xena/xena_json.py16
-rw-r--r--tools/systeminfo.py41
16 files changed, 403 insertions, 193 deletions
diff --git a/tools/hugepages.py b/tools/hugepages.py
index 3a434d6e..bba40122 100644
--- a/tools/hugepages.py
+++ b/tools/hugepages.py
@@ -20,40 +20,133 @@ import re
import subprocess
import logging
import locale
+import math
from tools import tasks
from conf import settings
_LOGGER = logging.getLogger(__name__)
-
+_allocated_hugepages = False
#
# hugepage management
#
+def get_hugepage_size():
+ """Return the size of the configured hugepages
+ """
+ hugepage_size_re = re.compile(r'^Hugepagesize:\s+(?P<size_hp>\d+)\s+kB',
+ re.IGNORECASE)
+ with open('/proc/meminfo', 'r') as fh:
+ data = fh.readlines()
+ for line in data:
+ match = hugepage_size_re.search(line)
+ if match:
+ _LOGGER.info('Hugepages size: %s', match.group('size_hp'))
+ return int(match.group('size_hp'))
+ else:
+ _LOGGER.error('Could not parse for hugepage size')
+ return 0
+
+
+def allocate_hugepages():
+ """Allocate hugepages on the fly
+ """
+ hp_size = get_hugepage_size()
+ if hp_size > 0:
+ nr_hp = int(math.ceil(settings.getValue('HUGEPAGE_RAM_ALLOCATION')/hp_size))
+ _LOGGER.info('Will allocate %s hugepages.', nr_hp)
+
+ nr_hugepages = 'vm.nr_hugepages=' + str(nr_hp)
+ try:
+ tasks.run_task(['sudo', 'sysctl', nr_hugepages],
+ _LOGGER, 'Trying to allocate hugepages..', True)
+ except subprocess.CalledProcessError:
+ _LOGGER.error('Unable to allocate hugepages.')
+ return False
+ global _allocated_hugepages
+ _allocated_hugepages = True
+ return True
+
+ else:
+ _LOGGER.error('Division by 0 will be supported in next release')
+ return False
+
+def deallocate_hugepages():
+ """De-allocate hugepages that were allocated on the fly
+ """
+ global _allocated_hugepages
+ if _allocated_hugepages:
+ nr_hugepages = 'vm.nr_hugepages= 0'
+ try:
+ tasks.run_task(['sudo', 'sysctl', nr_hugepages],
+ _LOGGER, 'Trying to de-allocate hugepages..', True)
+ except subprocess.CalledProcessError:
+ _LOGGER.error('Unable to de-allocate hugepages.')
+ return False
+ _allocated_hugepages = False
+ return True
+
+
+def get_free_hugepages(socket=None):
+ """Get the free hugepage totals on the system.
+
+ :param socket: optional socket param to get free hugepages on a socket. To
+ be passed a string.
+ :returns: hugepage amount as int
+ """
+ hugepage_free_re = re.compile(r'HugePages_Free:\s+(?P<free_hp>\d+)$')
+ if socket:
+ if os.path.exists(
+ '/sys/devices/system/node/node{}/meminfo'.format(socket)):
+ meminfo_path = '/sys/devices/system/node/node{}/meminfo'.format(
+ socket)
+ else:
+ _LOGGER.info('No hugepage info found for socket {}'.format(socket))
+ return 0
+ else:
+ meminfo_path = '/proc/meminfo'
+
+ with open(meminfo_path, 'r') as fh:
+ data = fh.readlines()
+ for line in data:
+ match = hugepage_free_re.search(line)
+ if match:
+ _LOGGER.info('Hugepages free: %s %s', match.group('free_hp'),
+ 'on socket {}'.format(socket) if socket else '')
+ return int(match.group('free_hp'))
+ else:
+ _LOGGER.info('Could not parse for hugepage size')
+ return 0
+
+
def is_hugepage_available():
- """Check if hugepages are available on the system.
+ """Check if hugepages are configured/available on the system.
"""
- hugepage_re = re.compile(r'^HugePages_Free:\s+(?P<num_hp>\d+)$')
+ hugepage_size_re = re.compile(r'^Hugepagesize:\s+(?P<size_hp>\d+)\s+kB',
+ re.IGNORECASE)
# read in meminfo
with open('/proc/meminfo') as mem_file:
mem_info = mem_file.readlines()
- # first check if module is loaded
+ # see if the hugepage size is the recommended value
for line in mem_info:
- result = hugepage_re.match(line)
- if not result:
- continue
-
- num_huge = result.group('num_hp')
- if not num_huge:
- _LOGGER.info('No free hugepages.')
- else:
- _LOGGER.info('Found \'%s\' free hugepage(s).', num_huge)
- return True
-
- return False
+ match_size = hugepage_size_re.match(line)
+ if match_size:
+ if match_size.group('size_hp') != '1048576':
+ _LOGGER.info(
+ '%s%s%s kB',
+ 'Hugepages not configured for recommend 1GB size. ',
+ 'Currently set at ', match_size.group('size_hp'))
+ num_huge = get_free_hugepages()
+ if num_huge == 0:
+ _LOGGER.info('No free hugepages.')
+ if not allocate_hugepages():
+ return False
+ else:
+ _LOGGER.info('Found \'%s\' free hugepage(s).', num_huge)
+ return True
def is_hugepage_mounted():
@@ -69,10 +162,11 @@ def is_hugepage_mounted():
def mount_hugepages():
- """Ensure hugepages are mounted.
+ """Ensure hugepages are mounted. Raises RuntimeError if no configured
+ hugepages are available.
"""
if not is_hugepage_available():
- return
+ raise RuntimeError('No Hugepages configured.')
if is_hugepage_mounted():
return
@@ -100,4 +194,5 @@ def umount_hugepages():
except subprocess.CalledProcessError:
_LOGGER.error('Unable to umount hugepages.')
-
+ if not deallocate_hugepages():
+ _LOGGER.error('Unable to deallocate previously allocated hugepages.')
diff --git a/tools/namespace.py b/tools/namespace.py
index e6bcd819..9131398f 100644
--- a/tools/namespace.py
+++ b/tools/namespace.py
@@ -108,8 +108,8 @@ def get_system_namespace_list():
Return tuple of strings for namespaces on the system
:return: tuple of namespaces as string
"""
- return tuple(os.listdir('/var/run/netns'))
-
+ return tuple(os.listdir('/var/run/netns')) if os.path.exists(
+ '/var/run/netns') else tuple()
def get_vsperf_namespace_list():
"""
diff --git a/tools/networkcard.py b/tools/networkcard.py
index c31be691..8d704fd5 100644
--- a/tools/networkcard.py
+++ b/tools/networkcard.py
@@ -249,7 +249,7 @@ def reinit_vfs(pf_pci_handle):
:param pf_pci_handle: PCI slot identifier of PF with domain part.
"""
- rte_pci_tool = os.path.join(settings.getValue('RTE_SDK'), 'tools', 'dpdk_nic_bind.py')
+ rte_pci_tool = glob.glob(os.path.join(settings.getValue('RTE_SDK'), 'tools', 'dpdk*bind.py'))[0]
for vf_nic in get_sriov_vfs_list(pf_pci_handle):
nic_driver = get_driver(vf_nic)
diff --git a/tools/pkt_gen/dummy/dummy.py b/tools/pkt_gen/dummy/dummy.py
index d3d79974..3324824c 100755
--- a/tools/pkt_gen/dummy/dummy.py
+++ b/tools/pkt_gen/dummy/dummy.py
@@ -146,8 +146,8 @@ class Dummy(trafficgen.ITrafficGenerator):
results = get_user_traffic(
'continuous',
'%dmpps, multistream %s, duration %d' % (traffic['frame_rate'],
- traffic['multistream'],
- duration), traffic_,
+ traffic['multistream'],
+ duration), traffic_,
('frames tx', 'frames rx', 'tx rate %', 'rx rate %', 'min latency',
'max latency', 'avg latency', 'frameloss %'))
@@ -169,7 +169,7 @@ class Dummy(trafficgen.ITrafficGenerator):
result[ResultsConstants.FRAME_LOSS_PERCENT] = float(results[7])
return result
- 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.
@@ -182,8 +182,8 @@ class Dummy(trafficgen.ITrafficGenerator):
results = get_user_traffic(
'throughput',
- '%d trials, %d seconds iterations, %f packet loss, multistream '
- '%s' % (trials, duration, lossrate, traffic['multistream']),
+ '%d tests, %d seconds iterations, %f packet loss, multistream '
+ '%s' % (tests, duration, lossrate, traffic['multistream']),
traffic_,
('frames tx', 'frames rx', 'tx rate %', 'rx rate %', 'min latency',
'max latency', 'avg latency', 'frameloss %'))
diff --git a/tools/pkt_gen/ixia/ixia.py b/tools/pkt_gen/ixia/ixia.py
index ae5da6d2..cd14a2a7 100755
--- a/tools/pkt_gen/ixia/ixia.py
+++ b/tools/pkt_gen/ixia/ixia.py
@@ -38,9 +38,9 @@ import tkinter
import logging
import os
+from collections import OrderedDict
from tools.pkt_gen import trafficgen
from conf import settings
-from collections import OrderedDict
from core.results.results_constants import ResultsConstants
_ROOT_DIR = os.path.dirname(os.path.realpath(__file__))
@@ -252,13 +252,13 @@ class Ixia(trafficgen.ITrafficGenerator):
"""
return self.run_tcl('stopTraffic')
- def send_rfc2544_throughput(self, traffic=None, trials=3, duration=20, lossrate=0.0):
+ def send_rfc2544_throughput(self, traffic=None, tests=1, duration=20, lossrate=0.0):
"""See ITrafficGenerator for description
"""
params = {}
params['config'] = {
- 'trials': trials,
+ 'tests': tests,
'duration': duration,
'lossrate': lossrate,
'multipleStreams': traffic['multistream'],
diff --git a/tools/pkt_gen/ixia/pass_fail.tcl b/tools/pkt_gen/ixia/pass_fail.tcl
index acb4443f..79b7f10d 100755
--- a/tools/pkt_gen/ixia/pass_fail.tcl
+++ b/tools/pkt_gen/ixia/pass_fail.tcl
@@ -675,7 +675,10 @@ proc rfcThroughputTest { testSpec trafficSpec } {
# testSpec
- set numTrials [dict get $testSpec trials] ;# we don't use this yet
+ # RFC2544 to IXIA terminology mapping (it affects Ixia configuration below):
+ # Test => Trial
+ # Trial => Iteration
+ set numTrials [dict get $testSpec tests] ;# we don't use this yet
set duration [dict get $testSpec duration]
set lossRate [dict get $testSpec lossrate]
set multipleStream [dict get $testSpec multipleStreams] ;# we don't use this yet
diff --git a/tools/pkt_gen/ixnet/ixnet.py b/tools/pkt_gen/ixnet/ixnet.py
index aadadf94..5e4ae569 100755
--- a/tools/pkt_gen/ixnet/ixnet.py
+++ b/tools/pkt_gen/ixnet/ixnet.py
@@ -19,8 +19,6 @@ This requires the following settings in your config file:
* TRAFFICGEN_IXNET_LIB_PATH
IxNetwork libraries path
-* TRAFFICGEN_IXNET_HOST
- IxNetwork host IP address
* TRAFFICGEN_IXNET_PORT
IxNetwork host port number
* TRAFFICGEN_IXNET_USER
@@ -32,7 +30,7 @@ This requires the following settings in your config file:
as the previous one
The following settings are also required. These can likely be shared
-an 'Ixia' traffic generator instance:
+with an 'Ixia' traffic generator instance:
* TRAFFICGEN_IXIA_HOST
IXIA chassis IP address
@@ -255,15 +253,15 @@ class IxNet(trafficgen.ITrafficGenerator):
"""
return self._wait_result()
- 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):
"""See ITrafficGenerator for description
"""
- self.start_rfc2544_throughput(traffic, trials, duration, lossrate)
+ self.start_rfc2544_throughput(traffic, tests, duration, lossrate)
return self.wait_rfc2544_throughput()
- 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):
"""Start transmission.
"""
@@ -272,7 +270,7 @@ class IxNet(trafficgen.ITrafficGenerator):
self._params['config'] = {
'binary': True,
- 'trials': trials,
+ 'tests': tests,
'duration': duration,
'lossrate': lossrate,
'multipleStreams': traffic['multistream'],
@@ -389,18 +387,18 @@ class IxNet(trafficgen.ITrafficGenerator):
# the results file
return parse_ixnet_rfc_results(parse_result_string(output[0]))
- def send_rfc2544_back2back(self, traffic=None, trials=50, duration=2,
+ def send_rfc2544_back2back(self, traffic=None, tests=1, duration=2,
lossrate=0.0):
"""See ITrafficGenerator for description
"""
# NOTE 2 seconds is the recommended duration for a back 2 back
# test in RFC2544. 50 trials is the recommended number from the
# RFC also.
- self.start_rfc2544_back2back(traffic, trials, duration, lossrate)
+ self.start_rfc2544_back2back(traffic, tests, duration, lossrate)
return self.wait_rfc2544_back2back()
- def start_rfc2544_back2back(self, traffic=None, trials=50, duration=2,
+ def start_rfc2544_back2back(self, traffic=None, tests=1, duration=2,
lossrate=0.0):
"""Start transmission.
"""
@@ -409,7 +407,7 @@ class IxNet(trafficgen.ITrafficGenerator):
self._params['config'] = {
'binary': True,
- 'trials': trials,
+ 'tests': tests,
'duration': duration,
'lossrate': lossrate,
'multipleStreams': traffic['multistream'],
diff --git a/tools/pkt_gen/ixnet/ixnetrfc2544.tcl b/tools/pkt_gen/ixnet/ixnetrfc2544.tcl
index 233db040..e70ca874 100644
--- a/tools/pkt_gen/ixnet/ixnetrfc2544.tcl
+++ b/tools/pkt_gen/ixnet/ixnetrfc2544.tcl
@@ -83,13 +83,16 @@ proc startRfc2544Test { testSpec trafficSpec } {
set duration [dict get $testSpec duration]
+ # RFC2544 to IXIA terminology mapping (it affects Ixia configuration inside this script):
+ # Test => Trial
+ # Trial => Iteration
if {$binary} {
- set numTrials [dict get $testSpec trials]
+ set numTests [dict get $testSpec tests]
set frameRate 100
set tolerance [dict get $testSpec lossrate]
set loadType binary
} else {
- set numTrials 1
+ set numTests 1
set frameRate [dict get $testSpec framerate]
set tolerance 0.0
set loadType custom
@@ -7778,7 +7781,7 @@ proc startRfc2544Test { testSpec trafficSpec } {
-framesize $frameSize \
-reportTputRateUnit mbps \
-duration $duration \
- -numtrials $numTrials \
+ -numtrials $numTests \
-trafficType constantLoading \
-burstSize 1 \
-framesPerBurstGap 1 \
@@ -7951,7 +7954,7 @@ proc startRfc2544Test { testSpec trafficSpec } {
-rfc2889ordering noOrdering \
-floodedFramesEnabled False \
-duration $duration \
- -numtrials $numTrials \
+ -numtrials $numTests \
-trafficType constantLoading \
-burstSize 1 \
-framesPerBurstGap 1 \
diff --git a/tools/pkt_gen/ixnet/ixnetrfc2544v2.tcl b/tools/pkt_gen/ixnet/ixnetrfc2544v2.tcl
index 0bdba9cd..539c5a5b 100755
--- a/tools/pkt_gen/ixnet/ixnetrfc2544v2.tcl
+++ b/tools/pkt_gen/ixnet/ixnetrfc2544v2.tcl
@@ -83,13 +83,16 @@ proc startRfc2544Test { testSpec trafficSpec } {
set duration [dict get $testSpec duration]
+ # RFC2544 to IXIA terminology mapping (it affects Ixia configuration inside this script):
+ # Test => Trial
+ # Trial => Iteration
if {$binary} {
- set numTrials [dict get $testSpec trials]
+ set numTests [dict get $testSpec tests]
set frameRate 100
set tolerance [dict get $testSpec lossrate]
set loadType binary
} else {
- set numTrials 1
+ set numTests 1
set frameRate [dict get $testSpec framerate]
set tolerance 0.0
set loadType custom
@@ -3218,7 +3221,7 @@ proc startRfc2544Test { testSpec trafficSpec } {
-framesize $frameSize \
-reportTputRateUnit mbps \
-duration $duration \
- -numtrials $numTrials \
+ -numtrials $numTests \
-trafficType constantLoading \
-burstSize 1 \
-framesPerBurstGap 1 \
@@ -3391,7 +3394,7 @@ proc startRfc2544Test { testSpec trafficSpec } {
-rfc2889ordering noOrdering \
-floodedFramesEnabled False \
-duration $duration \
- -numtrials $numTrials \
+ -numtrials $numTests \
-trafficType constantLoading \
-burstSize 1 \
-framesPerBurstGap 1 \
diff --git a/tools/pkt_gen/moongen/moongen.py b/tools/pkt_gen/moongen/moongen.py
index d6c09e5d..790286d8 100644
--- a/tools/pkt_gen/moongen/moongen.py
+++ b/tools/pkt_gen/moongen/moongen.py
@@ -20,10 +20,11 @@ Moongen Traffic Generator Model
"""
# python imports
-import logging
from collections import OrderedDict
-import subprocess
+import logging
+import math
import re
+import subprocess
# VSPerf imports
from conf import settings
@@ -49,6 +50,13 @@ class Moongen(ITrafficGenerator):
self._moongen_user = settings.getValue('TRAFFICGEN_MOONGEN_USER')
self._moongen_ports = settings.getValue('TRAFFICGEN_MOONGEN_PORTS')
+ if settings.getValue('TRAFFICGEN_MOONGEN_LINE_SPEED_GBPS') == '10':
+ self._moongen_line_speed = math.pow(10, 10)
+ else:
+ raise RuntimeError(
+ 'MOONGEN: Invalid line speed in configuration ' + \
+ 'file (today 10Gbps supported)')
+
@property
def traffic_defaults(self):
"""Default traffic values.
@@ -58,12 +66,12 @@ class Moongen(ITrafficGenerator):
will likely break traffic generator implementations or tests
respectively.
"""
- self._logger.info("In moongen traffic_defaults method")
+ self._logger.info("In Moongen traffic_defaults method")
return self._traffic_defaults
def create_moongen_cfg_file(self, traffic, duration=60,
acceptable_loss_pct=1, one_shot=0):
- """Create the MoonGen configuration file from VSPERF's traffic profile
+ """Create the Moongen configuration file from VSPERF's traffic profile
:param traffic: Detailed "traffic" spec, i.e. IP address, VLAN tags
:param duration: The length of time to generate packet throughput
:param acceptable_loss: Maximum packet loss acceptable
@@ -138,8 +146,9 @@ class Moongen(ITrafficGenerator):
out_file.write("dstIp = \"" + \
str(traffic['l3']['dstip']) + "\",\n")
- out_file.write("vlanId = " + \
- str(traffic['vlan']['id']) + ",\n")
+ if traffic['vlan']['enabled']:
+ out_file.write("vlanId = " + \
+ str(traffic['vlan']['id']) + ",\n")
out_file.write("searchRunTime = " + \
str(duration) + ",\n")
@@ -156,10 +165,17 @@ class Moongen(ITrafficGenerator):
if one_shot:
out_file.write("oneShot = true,\n")
- # Assume 10G line rates at the moment. Need to convert VSPERF
- # frame_rate (percentage of line rate) to Mpps for MoonGen
+ # Need to convert VSPERF frame_rate (percentage of line rate)
+ # to Mpps for Moongen
+ start_rate = str(
+ (traffic['frame_rate'] / 100) * (self._moongen_line_speed / \
+ (8 * (traffic['l2']['framesize'] + 20)) / math.pow(10, 6)))
+
+ logging.debug("startRate = " + start_rate)
+
+ out_file.write("startRate = " + \
+ start_rate + "\n")
- out_file.write("startRate = " + str((traffic['frame_rate'] / 100) * 14.88) + "\n")
out_file.write("}" + "\n")
out_file.close()
@@ -181,17 +197,17 @@ class Moongen(ITrafficGenerator):
raise RuntimeError('MOONGEN: Error copying configuration file')
def connect(self):
- """Connect to MoonGen traffic generator
+ """Connect to Moongen traffic generator
- Verify that MoonGen is on the system indicated by
+ Verify that Moongen is on the system indicated by
the configuration file
"""
- self._logger.info("MOONGEN: In MoonGen connect method...")
+ self._logger.info("MOONGEN: In Moongen connect method...")
if self._moongen_host_ip_addr:
cmd_ping = "ping -c1 " + self._moongen_host_ip_addr
else:
- raise RuntimeError('MOONGEN: MoonGen host not defined')
+ raise RuntimeError('MOONGEN: Moongen host not defined')
ping = subprocess.Popen(cmd_ping, shell=True, stderr=subprocess.PIPE)
output, error = ping.communicate()
@@ -199,7 +215,7 @@ class Moongen(ITrafficGenerator):
if ping.returncode:
self._logger.error(error)
self._logger.error(output)
- raise RuntimeError('MOONGEN: Cannot ping MoonGen host at ' + \
+ raise RuntimeError('MOONGEN: Cannot ping Moongen host at ' + \
self._moongen_host_ip_addr)
connect_moongen = "ssh " + self._moongen_user + \
@@ -218,10 +234,10 @@ class Moongen(ITrafficGenerator):
self._logger.error(error)
self._logger.error(output)
raise RuntimeError(
- 'MOONGEN: Cannot locate MoonGen program at %s within %s' \
+ 'MOONGEN: Cannot locate Moongen program at %s within %s' \
% (self._moongen_host_ip_addr, self._moongen_base_dir))
- self._logger.info("MOONGEN: MoonGen host successfully found...")
+ self._logger.info("MOONGEN: Moongen host successfully found...")
def disconnect(self):
"""Disconnect from the traffic generator.
@@ -252,7 +268,7 @@ class Moongen(ITrafficGenerator):
- List of List of Rx Bytes,
- Payload Errors and Sequence Errors.
"""
- self._logger.info("In moongen send_burst_traffic method")
+ self._logger.info("In Moongen send_burst_traffic method")
return NotImplementedError('Moongen Burst traffic not implemented')
def send_cont_traffic(self, traffic=None, duration=20):
@@ -274,7 +290,7 @@ class Moongen(ITrafficGenerator):
- Max Latency (ns),
- Avg Latency (ns)
"""
- self._logger.info("In moongen send_cont_traffic method")
+ self._logger.info("In Moongen send_cont_traffic method")
self._params.clear()
self._params['traffic'] = self.traffic_defaults.copy()
@@ -316,31 +332,31 @@ class Moongen(ITrafficGenerator):
results = OrderedDict()
results[ResultsConstants.THROUGHPUT_RX_FPS] = (
- '{:,.6f}'.format(total_throughput_rx_fps))
+ '{:.6f}'.format(total_throughput_rx_fps))
results[ResultsConstants.THROUGHPUT_RX_MBPS] = (
- '{:,.3f}'.format(total_throughput_rx_mbps))
+ '{:.3f}'.format(total_throughput_rx_mbps))
results[ResultsConstants.THROUGHPUT_RX_PERCENT] = (
- '{:,.3f}'.format(total_throughput_rx_pct))
+ '{:.3f}'.format(total_throughput_rx_pct))
results[ResultsConstants.TX_RATE_FPS] = (
- '{:,.6f}'.format(total_throughput_tx_fps))
+ '{:.6f}'.format(total_throughput_tx_fps))
results[ResultsConstants.TX_RATE_MBPS] = (
- '{:,.3f}'.format(total_throughput_tx_mbps))
+ '{:.3f}'.format(total_throughput_tx_mbps))
results[ResultsConstants.TX_RATE_PERCENT] = (
- '{:,.3f}'.format(total_throughput_tx_pct))
+ '{:.3f}'.format(total_throughput_tx_pct))
results[ResultsConstants.MIN_LATENCY_NS] = (
- '{:,.3f}'.format(total_min_latency_ns))
+ '{:.3f}'.format(total_min_latency_ns))
results[ResultsConstants.MAX_LATENCY_NS] = (
- '{:,.3f}'.format(total_max_latency_ns))
+ '{:.3f}'.format(total_max_latency_ns))
results[ResultsConstants.AVG_LATENCY_NS] = (
- '{:,.3f}'.format(total_avg_latency_ns))
+ '{:.3f}'.format(total_avg_latency_ns))
return results
@@ -352,18 +368,18 @@ class Moongen(ITrafficGenerator):
:param traffic: Detailed "traffic" spec, i.e. IP address, VLAN tags
:param duration: Time to wait to receive packets (secs)
"""
- self._logger.info("In moongen start_cont_traffic method")
- return NotImplementedError('Moongen continuous traffic not implemented')
+ self._logger.info("In Moongen start_cont_traffic method")
+ return NotImplementedError('moongen continuous traffic not implemented')
def stop_cont_traffic(self):
# Stop continuous transmission and return results.
- self._logger.info("In moongen stop_cont_traffic method")
+ self._logger.info("In Moongen stop_cont_traffic method")
def run_moongen_and_collect_results(self, test_run=1):
- """Execute MoonGen and transform results into VSPERF format
+ """Execute Moongen and transform results into VSPERF format
:param test_run: The number of tests to run
"""
- # Start MoonGen and create logfile of the run
+ # Start Moongen and create logfile of the run
connect_moongen = "ssh " + self._moongen_user + "@" + \
self._moongen_host_ip_addr
@@ -381,7 +397,7 @@ class Moongen(ITrafficGenerator):
logging.debug(error)
logging.debug(output)
raise RuntimeError(
- 'MOONGEN: Error starting MoonGen program at %s within %s' \
+ 'MOONGEN: Error starting Moongen program at %s within %s' \
% (self._moongen_host_ip_addr, self._moongen_base_dir))
cmd_moongen = "mkdir -p /tmp/moongen/" + str(test_run)
@@ -396,7 +412,7 @@ class Moongen(ITrafficGenerator):
logging.debug(error)
logging.debug(output)
raise RuntimeError(
- 'MOONGEN: Error obtaining MoonGen log from %s within %s' \
+ 'MOONGEN: Error obtaining Moongen log from %s within %s' \
% (self._moongen_host_ip_addr, self._moongen_base_dir))
cmd_moongen = " scp " + self._moongen_user + "@" + \
@@ -414,7 +430,7 @@ class Moongen(ITrafficGenerator):
logging.debug(error)
logging.debug(output)
raise RuntimeError(
- 'MOONGEN: Error obtaining MoonGen log from %s within %s' \
+ 'MOONGEN: Error obtaining Moongen log from %s within %s' \
% (self._moongen_host_ip_addr, self._moongen_base_dir))
log_file = "/tmp/moongen/" + str(test_run) + "/moongen-run.log"
@@ -443,7 +459,7 @@ class Moongen(ITrafficGenerator):
if not results_match:
logging.error('There was a problem parsing ' +\
- 'MoonGen REPORT section of MoonGen log file')
+ 'Moongen REPORT section of Moongen log file')
moongen_results = OrderedDict()
moongen_results[ResultsConstants.THROUGHPUT_RX_FPS] = 0
@@ -468,14 +484,25 @@ class Moongen(ITrafficGenerator):
if parameters_match:
frame_size = int(parameters_match.group(1))
else:
- logging.error('There was a problem parsing MoonGen ' +\
- 'PARAMETERS section of MoonGen log file')
+ logging.error('There was a problem parsing Moongen ' +\
+ 'PARAMETERS section of Moongen log file')
frame_size = 0
- if results_match and parameters_match:
+ # Each packet stream in the MoonGen report is prefaced with the
+ # words '[REPORT]Device'. Count the instances of this string to
+ # get the total aggregrate throughput. For example:
+ #
+ # - If num_traffic_streams = 1, there is a single
+ # unidirectional stream
+ #
+ # - If num_traffic_streams = 2, there is a bidirectional
+ # traffic stream
+ num_traffic_streams = mytext.count('[REPORT]Device')
+
+ if results_match and parameters_match and num_traffic_streams:
# Assume for now 10G link speed
- max_theoretical_mfps = (
- (10000000000 / 8) / (frame_size + 20))
+ max_theoretical_fps = (
+ num_traffic_streams * (self._moongen_line_speed / 8) / (frame_size + 20))
moongen_results[ResultsConstants.THROUGHPUT_RX_FPS] = (
float(results_match.group(6)) * 1000000)
@@ -484,8 +511,7 @@ class Moongen(ITrafficGenerator):
(float(results_match.group(6)) * frame_size + 20) * 8)
moongen_results[ResultsConstants.THROUGHPUT_RX_PERCENT] = (
- float(results_match.group(6)) * \
- 1000000 / max_theoretical_mfps * 100)
+ (100 * float(results_match.group(6)) * 1000000) / max_theoretical_fps)
moongen_results[ResultsConstants.TX_RATE_FPS] = (
float(results_match.group(5)) * 1000000)
@@ -494,8 +520,7 @@ class Moongen(ITrafficGenerator):
float(results_match.group(5)) * (frame_size + 20) * 8)
moongen_results[ResultsConstants.TX_RATE_PERCENT] = (
- float(results_match.group(5)) *
- 1000000 / max_theoretical_mfps * 100)
+ (100 * float(results_match.group(5)) * 1000000) / max_theoretical_fps)
moongen_results[ResultsConstants.B2B_TX_COUNT] = (
float(results_match.group(1)))
@@ -512,7 +537,7 @@ class Moongen(ITrafficGenerator):
return moongen_results
def send_rfc2544_throughput(self, traffic=None, duration=20,
- lossrate=0.0, trials=1):
+ lossrate=0.0, tests=1):
#
# Send traffic per RFC2544 throughput test specifications.
#
@@ -521,7 +546,7 @@ class Moongen(ITrafficGenerator):
# detected is found.
#
# :param traffic: Detailed "traffic" spec, see design docs for details
- # :param trials: Number of trials to execute
+ # :param tests: Number of tests to execute
# :param duration: Per iteration duration
# :param lossrate: Acceptable lossrate percentage
# :returns: dictionary of strings with following data:
@@ -557,7 +582,7 @@ class Moongen(ITrafficGenerator):
total_max_latency_ns = 0
total_avg_latency_ns = 0
- for test_run in range(1, trials+1):
+ for test_run in range(1, tests+1):
collected_results = (
Moongen.run_moongen_and_collect_results(self, test_run=test_run))
@@ -586,35 +611,35 @@ class Moongen(ITrafficGenerator):
results = OrderedDict()
results[ResultsConstants.THROUGHPUT_RX_FPS] = (
- '{:,.6f}'.format(total_throughput_rx_fps / trials))
+ '{:.6f}'.format(total_throughput_rx_fps / tests))
results[ResultsConstants.THROUGHPUT_RX_MBPS] = (
- '{:,.3f}'.format(total_throughput_rx_mbps / trials))
+ '{:.3f}'.format(total_throughput_rx_mbps / tests))
results[ResultsConstants.THROUGHPUT_RX_PERCENT] = (
- '{:,.3f}'.format(total_throughput_rx_pct / trials))
+ '{:.3f}'.format(total_throughput_rx_pct / tests))
results[ResultsConstants.TX_RATE_FPS] = (
- '{:,.6f}'.format(total_throughput_tx_fps / trials))
+ '{:.6f}'.format(total_throughput_tx_fps / tests))
results[ResultsConstants.TX_RATE_MBPS] = (
- '{:,.3f}'.format(total_throughput_tx_mbps / trials))
+ '{:.3f}'.format(total_throughput_tx_mbps / tests))
results[ResultsConstants.TX_RATE_PERCENT] = (
- '{:,.3f}'.format(total_throughput_tx_pct / trials))
+ '{:.3f}'.format(total_throughput_tx_pct / tests))
results[ResultsConstants.MIN_LATENCY_NS] = (
- '{:,.3f}'.format(total_min_latency_ns / trials))
+ '{:.3f}'.format(total_min_latency_ns / tests))
results[ResultsConstants.MAX_LATENCY_NS] = (
- '{:,.3f}'.format(total_max_latency_ns / trials))
+ '{:.3f}'.format(total_max_latency_ns / tests))
results[ResultsConstants.AVG_LATENCY_NS] = (
- '{:,.3f}'.format(total_avg_latency_ns / trials))
+ '{:.3f}'.format(total_avg_latency_ns / tests))
return results
- 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'.
@@ -630,14 +655,14 @@ class Moongen(ITrafficGenerator):
self._logger.info('In moongen wait_rfc2544_throughput')
def send_rfc2544_back2back(self, traffic=None, duration=60,
- lossrate=0.0, trials=1):
+ lossrate=0.0, tests=1):
"""Send traffic per RFC2544 back2back test specifications.
Send packets at a fixed rate, using ``traffic``
configuration, for duration seconds.
:param traffic: Detailed "traffic" spec, see design docs for details
- :param trials: Number of trials to execute
+ :param tests: Number of tests to execute
:param duration: Per iteration duration
:param lossrate: Acceptable loss percentage
@@ -671,7 +696,7 @@ class Moongen(ITrafficGenerator):
results[ResultsConstants.SCAL_STREAM_TYPE] = 0
results[ResultsConstants.SCAL_PRE_INSTALLED_FLOWS] = 0
- for test_run in range(1, trials+1):
+ for test_run in range(1, tests+1):
collected_results = (
Moongen.run_moongen_and_collect_results(self, test_run=test_run))
@@ -701,28 +726,28 @@ class Moongen(ITrafficGenerator):
# Calculate average results
results[ResultsConstants.B2B_RX_FPS] = (
- results[ResultsConstants.B2B_RX_FPS] / trials)
+ results[ResultsConstants.B2B_RX_FPS] / tests)
results[ResultsConstants.B2B_RX_PERCENT] = (
- results[ResultsConstants.B2B_RX_PERCENT] / trials)
+ results[ResultsConstants.B2B_RX_PERCENT] / tests)
results[ResultsConstants.B2B_TX_FPS] = (
- results[ResultsConstants.B2B_TX_FPS] / trials)
+ results[ResultsConstants.B2B_TX_FPS] / tests)
results[ResultsConstants.B2B_TX_PERCENT] = (
- results[ResultsConstants.B2B_TX_PERCENT] / trials)
+ results[ResultsConstants.B2B_TX_PERCENT] / tests)
results[ResultsConstants.B2B_TX_COUNT] = (
- results[ResultsConstants.B2B_TX_COUNT] / trials)
+ results[ResultsConstants.B2B_TX_COUNT] / tests)
results[ResultsConstants.B2B_FRAMES] = (
- results[ResultsConstants.B2B_FRAMES] / trials)
+ results[ResultsConstants.B2B_FRAMES] / tests)
results[ResultsConstants.B2B_FRAME_LOSS_FRAMES] = (
- results[ResultsConstants.B2B_FRAME_LOSS_FRAMES] / trials)
+ results[ResultsConstants.B2B_FRAME_LOSS_FRAMES] / tests)
results[ResultsConstants.B2B_FRAME_LOSS_PERCENT] = (
- results[ResultsConstants.B2B_FRAME_LOSS_PERCENT] / trials)
+ results[ResultsConstants.B2B_FRAME_LOSS_PERCENT] / tests)
results[ResultsConstants.SCAL_STREAM_COUNT] = 0
results[ResultsConstants.SCAL_STREAM_TYPE] = 0
@@ -730,14 +755,14 @@ class Moongen(ITrafficGenerator):
return results
- 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'.
#
# Start transmission and immediately return. Do not wait for results.
#
- self._logger.info("In moongen start_rfc2544_back2back method")
+ self._logger.info("In Moongen start_rfc2544_back2back method")
return NotImplementedError(
'Moongen start back2back traffic not implemented')
diff --git a/tools/pkt_gen/testcenter/testcenter.py b/tools/pkt_gen/testcenter/testcenter.py
index a1f38d8b..c242269a 100644
--- a/tools/pkt_gen/testcenter/testcenter.py
+++ b/tools/pkt_gen/testcenter/testcenter.py
@@ -211,7 +211,7 @@ class TestCenter(trafficgen.ITrafficGenerator):
return self.get_rfc2544_results(filec)
- 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.
@@ -243,7 +243,7 @@ class TestCenter(trafficgen.ITrafficGenerator):
return self.get_rfc2544_results(filec)
- 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 BacktoBack test specifications.
diff --git a/tools/pkt_gen/trafficgen/trafficgen.py b/tools/pkt_gen/trafficgen/trafficgen.py
index 3953bbb1..fb40cd92 100755
--- a/tools/pkt_gen/trafficgen/trafficgen.py
+++ b/tools/pkt_gen/trafficgen/trafficgen.py
@@ -133,7 +133,7 @@ class ITrafficGenerator(object):
"""
raise NotImplementedError('Please call an implementation.')
- 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.
@@ -142,7 +142,7 @@ class ITrafficGenerator(object):
detected is found.
:param traffic: Detailed "traffic" spec, see design docs for details
- :param trials: Number of trials to execute
+ :param tests: Number of tests to execute
:param duration: Per iteration duration
:param lossrate: Acceptable lossrate percentage
:returns: dictionary of strings with following data:
@@ -158,7 +158,7 @@ class ITrafficGenerator(object):
"""
raise NotImplementedError('Please call an implementation.')
- 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'.
@@ -172,7 +172,7 @@ class ITrafficGenerator(object):
"""
raise NotImplementedError('Please call an implementation.')
- 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.
@@ -180,7 +180,7 @@ class ITrafficGenerator(object):
configuration, for duration seconds.
:param traffic: Detailed "traffic" spec, see design docs for details
- :param trials: Number of trials to execute
+ :param tests: Number of tests to execute
:param duration: Per iteration duration
:param lossrate: Acceptable loss percentage
@@ -191,7 +191,7 @@ class ITrafficGenerator(object):
"""
raise NotImplementedError('Please call an implementation.')
- 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'.
diff --git a/tools/pkt_gen/xena/XenaDriver.py b/tools/pkt_gen/xena/XenaDriver.py
index aa8443c9..d3862312 100644
--- a/tools/pkt_gen/xena/XenaDriver.py
+++ b/tools/pkt_gen/xena/XenaDriver.py
@@ -1001,9 +1001,21 @@ class XenaTXStats(object):
mydict = statdict
return mydict
-
def aggregate_stats(stat1, stat2):
"""
+ Judge whether stat1 and stat2 both have same key, if both have same key,
+ call the aggregate fuction, else use the stat1's value
+ """
+ newstat = dict()
+ for keys in stat1.keys():
+ if keys in stat2 and isinstance(stat1[keys], dict):
+ newstat[keys] = aggregate(stat1[keys], stat2[keys])
+ else:
+ newstat[keys] = stat1[keys]
+ return newstat
+
+def aggregate(stat1, stat2):
+ """
Recursive function to aggregate two sets of statistics. This is used when
bi directional traffic is done and statistics need to be calculated based
on two sets of statistics.
@@ -1014,7 +1026,7 @@ def aggregate_stats(stat1, stat2):
newstat = dict()
for (keys1, keys2) in zip(stat1.keys(), stat2.keys()):
if isinstance(stat1[keys1], dict):
- newstat[keys1] = aggregate_stats(stat1[keys1], stat2[keys2])
+ newstat[keys1] = aggregate(stat1[keys1], stat2[keys2])
else:
if not isinstance(stat1[keys1], int) and not isinstance(
[keys1], float):
diff --git a/tools/pkt_gen/xena/xena.py b/tools/pkt_gen/xena/xena.py
index 7dd4b90b..8d45053e 100755
--- a/tools/pkt_gen/xena/xena.py
+++ b/tools/pkt_gen/xena/xena.py
@@ -25,6 +25,7 @@ Xena Traffic Generator Model
# python imports
import binascii
import logging
+import os
import subprocess
import sys
from time import sleep
@@ -50,6 +51,7 @@ from tools.pkt_gen.xena.XenaDriver import (
XenaManager,
)
+
class Xena(ITrafficGenerator):
"""
Xena Traffic generator wrapper class
@@ -65,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):
@@ -99,7 +114,7 @@ class Xena(ITrafficGenerator):
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
@@ -290,15 +305,26 @@ class Xena(ITrafficGenerator):
if testtype == '2544_throughput':
j_file.set_test_options_tput(
packet_sizes=self._params['traffic']['l2']['framesize'],
- iterations=trials, loss_rate=loss_rate,
+ 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()
+ j_file.modify_2544_tput_options(
+ settings.getValue('TRAFFICGEN_XENA_2544_TPUT_INIT_VALUE'),
+ settings.getValue('TRAFFICGEN_XENA_2544_TPUT_MIN_VALUE'),
+ settings.getValue('TRAFFICGEN_XENA_2544_TPUT_MAX_VALUE'),
+ settings.getValue(
+ 'TRAFFICGEN_XENA_2544_TPUT_VALUE_RESOLUTION'),
+ settings.getValue(
+ 'TRAFFICGEN_XENA_2544_TPUT_USEPASS_THRESHHOLD'),
+ settings.getValue(
+ 'TRAFFICGEN_XENA_2544_TPUT_PASS_THRESHHOLD')
+ )
elif testtype == '2544_b2b':
j_file.set_test_options_back2back(
packet_sizes=self._params['traffic']['l2']['framesize'],
- iterations=trials, duration=self._duration,
+ iterations=tests, duration=self._duration,
startvalue=self._params['traffic']['frame_rate'],
endvalue=self._params['traffic']['frame_rate'],
micro_tpld=True if self._params[
@@ -451,6 +477,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
@@ -495,13 +559,11 @@ class Xena(ITrafficGenerator):
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()
@@ -517,7 +579,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()
@@ -533,7 +594,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):
@@ -541,7 +601,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.
@@ -554,19 +614,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'.
@@ -578,26 +633,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.
@@ -610,47 +658,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)
diff --git a/tools/pkt_gen/xena/xena_json.py b/tools/pkt_gen/xena/xena_json.py
index 2a15a932..1ce7b46f 100644
--- a/tools/pkt_gen/xena/xena_json.py
+++ b/tools/pkt_gen/xena/xena_json.py
@@ -233,6 +233,22 @@ class XenaJSON(object):
self.json_data['TestOptions']['TestTypeOptionMap']['Throughput'][
'Enabled'] = 'true'
+ def modify_2544_tput_options(self, initial_value, minimum_value,
+ maximum_value, value_resolution,
+ use_pass_threshhold, pass_threshhold):
+ self.json_data['TestOptions']['TestTypeOptionMap']['Throughput'][
+ 'RateIterationOptions']['InitialValue'] = initial_value
+ self.json_data['TestOptions']['TestTypeOptionMap']['Throughput'][
+ 'RateIterationOptions']['MinimumValue'] = minimum_value
+ self.json_data['TestOptions']['TestTypeOptionMap']['Throughput'][
+ 'RateIterationOptions']['MaximumValue'] = maximum_value
+ self.json_data['TestOptions']['TestTypeOptionMap']['Throughput'][
+ 'RateIterationOptions']['ValueResolution'] = value_resolution
+ self.json_data['TestOptions']['TestTypeOptionMap']['Throughput'][
+ 'RateIterationOptions']['UsePassThreshold'] = use_pass_threshhold
+ self.json_data['TestOptions']['TestTypeOptionMap']['Throughput'][
+ 'RateIterationOptions']['PassThreshold'] = pass_threshhold
+
def set_chassis_info(self, hostname, pwd):
"""
Set the chassis info
diff --git a/tools/systeminfo.py b/tools/systeminfo.py
index 9d8eb5cb..50dc17e0 100644
--- a/tools/systeminfo.py
+++ b/tools/systeminfo.py
@@ -223,22 +223,45 @@ def get_version(app_name):
app_git_tag = get_git_tag(S.getValue('OVS_DIR'))
elif app_name.lower() in ['dpdk', 'testpmd']:
tmp_ver = ['', '', '']
- found = False
+ dpdk_16 = False
with open(app_version_file['dpdk']) as file_:
for line in file_:
if not line.strip():
continue
+ # DPDK version < 16
if line.startswith('#define RTE_VER_MAJOR'):
- found = True
tmp_ver[0] = line.rstrip('\n').split(' ')[2]
- if line.startswith('#define RTE_VER_MINOR'):
- found = True
- tmp_ver[1] = line.rstrip('\n').split(' ')[2]
- if line.startswith('#define RTE_VER_PATCH_LEVEL'):
- found = True
+ # DPDK version < 16
+ elif line.startswith('#define RTE_VER_PATCH_LEVEL'):
tmp_ver[2] = line.rstrip('\n').split(' ')[2]
-
- if found:
+ # DPDK version < 16
+ elif line.startswith('#define RTE_VER_PATCH_RELEASE'):
+ release = line.rstrip('\n').split(' ')[2]
+ if not '16' in release:
+ tmp_ver[2] += line.rstrip('\n').split(' ')[2]
+ # DPDK all versions
+ elif line.startswith('#define RTE_VER_MINOR'):
+ if dpdk_16:
+ tmp_ver[2] = line.rstrip('\n').split(' ')[2]
+ else:
+ tmp_ver[1] = line.rstrip('\n').split(' ')[2]
+ # DPDK all versions
+ elif line.startswith('#define RTE_VER_SUFFIX'):
+ tmp_ver[2] += line.rstrip('\n').split('"')[1]
+ # DPDK version >= 16
+ elif line.startswith('#define RTE_VER_YEAR'):
+ dpdk_16 = True
+ tmp_ver[0] = line.rstrip('\n').split(' ')[2]
+ # DPDK version >= 16
+ elif line.startswith('#define RTE_VER_MONTH'):
+ tmp_ver[1] = '{:0>2}'.format(line.rstrip('\n').split(' ')[2])
+ # DPDK version >= 16
+ elif line.startswith('#define RTE_VER_RELEASE'):
+ release = line.rstrip('\n').split(' ')[2]
+ if not '16' in release:
+ tmp_ver[2] += line.rstrip('\n').split(' ')[2]
+
+ if len(tmp_ver[0]):
app_version = '.'.join(tmp_ver)
app_git_tag = get_git_tag(S.getValue('RTE_SDK'))
elif app_name.lower().startswith('qemu'):