summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/trex_faq.asciidoc32
-rwxr-xr-xscripts/automation/regression/cfg/global_regression_cfg.yaml19
-rw-r--r--scripts/automation/regression/trex.py421
-rwxr-xr-xscripts/automation/regression/trex_unit_test.py23
4 files changed, 72 insertions, 423 deletions
diff --git a/doc/trex_faq.asciidoc b/doc/trex_faq.asciidoc
index eb6938a1..6558ba38 100644
--- a/doc/trex_faq.asciidoc
+++ b/doc/trex_faq.asciidoc
@@ -195,6 +195,38 @@ We are planning to add MACs to `./dpdk_setup_ports.py -s`
==== TRex traffic does not show up on Wireshark, so I can not capture the traffic from the TRex port
TRex uses DPDK which takes ownership of the ports, so using Wireshark is not possible. You can use switch with port mirroring to capture the traffic.
+==== Running first time, igb_uio.ko problems
+
+Q::
+Command: +
+sudo ./t-rex-64 -f cap2/dns.yaml -c 4 -m 1 -d 10 -1 1000 +
+ +
+Output: +
+Loading kernel drivers for the first time +
+ERROR: We don't have precompiled igb_uio.ko module for your kernel version +
+Will try compiling automatically. +
+Automatic compilation failed. +
+You can try compiling yourself, using the following commands: +
+$cd ko/src +
+$make +
+$make install +
+$cd - +
+Then try to run TRex again
+
+A::
+Usually we have pre-compiled igb_uio.ko for common Kernels of supported OS. +
+If you have different Kernel (due to update of packages or slightly different OS version), you will need to compile that module. +
+Simply follow the instructions printed above. +
+Note: you might need additional Linux packages for that:
+* Fedora/CentOS:
+** sudo yum install kernel-devel-\`uname -r`
+** sudo yum group install "Development tools"
+* Ubuntu:
+** sudo apt install linux-headers-\`uname -r`
+** sudo apt install build-essential
+
+
+
=== Stateful
==== How do I start using the stateful mode?
diff --git a/scripts/automation/regression/cfg/global_regression_cfg.yaml b/scripts/automation/regression/cfg/global_regression_cfg.yaml
new file mode 100755
index 00000000..4bb9fb54
--- /dev/null
+++ b/scripts/automation/regression/cfg/global_regression_cfg.yaml
@@ -0,0 +1,19 @@
+#-------------------------------------------
+# Various global parameters of regression
+#-------------------------------------------
+
+
+########## Reporting results #########
+
+elk:
+ server: sceasr-b20
+ port: 9200
+
+google:
+ id: UA-75220362-3
+ queue_size: 100
+ timeout: 5
+ blocking: 0
+
+
+
diff --git a/scripts/automation/regression/trex.py b/scripts/automation/regression/trex.py
index 4f5eba60..36e204af 100644
--- a/scripts/automation/regression/trex.py
+++ b/scripts/automation/regression/trex.py
@@ -11,6 +11,8 @@ from CProgressDisp import TimedProgressBar
from stateful_tests.tests_exceptions import TRexInUseError
import datetime
import copy
+import outer_packages
+import yaml
class CTRexScenario:
modes = set() # list of modes of this setup: loopback, virtual etc.
@@ -44,6 +46,7 @@ class CTRexScenario:
json_verbose = False
elk = None
elk_info = None
+ global_cfg = None
def copy_elk_info ():
assert(CTRexScenario.elk_info)
@@ -53,420 +56,12 @@ def copy_elk_info ():
d['timestamp']=timestamp.strftime("%Y-%m-%d %H:%M:%S")
return(d)
-
+global_cfg = 'cfg/global_regression_cfg.yaml'
+if not os.path.exists(global_cfg):
+ raise Exception('Global configuration file %s is missing' % global_cfg)
+with open(global_cfg) as f:
+ CTRexScenario.global_cfg = yaml.safe_load(f.read())
-class CTRexRunner:
- """This is an instance for generating a CTRexRunner"""
- def __init__ (self, config_dict, yaml):
- self.trex_config = config_dict#misc_methods.load_config_file(config_file)
- self.yaml = yaml
-
-
- def get_config (self):
- """ get_config() -> dict
-
- Returns the stored configuration of the TRex server of the CTRexRunner instance as a dictionary
- """
- return self.trex_config
-
- def set_yaml_file (self, yaml_path):
- """ update_yaml_file (self, yaml_path) -> None
-
- Defines the yaml file to be used by the TRex.
- """
- self.yaml = yaml_path
-
-
- def generate_run_cmd (self, multiplier, cores, duration, nc = True, export_path="/tmp/trex.txt", **kwargs):
- """ generate_run_cmd(self, multiplier, duration, export_path) -> str
-
- Generates a custom running command for the kick-off of the TRex traffic generator.
- Returns a command (string) to be issued on the trex server
-
- Parameters
- ----------
- multiplier : float
- Defines the TRex multiplier factor (platform dependant)
- duration : int
- Defines the duration of the test
- export_path : str
- a full system path to which the results of the trex-run will be logged.
-
- """
- fileName, fileExtension = os.path.splitext(self.yaml)
- if self.yaml == None:
- raise ValueError('TRex yaml file is not defined')
- elif fileExtension != '.yaml':
- raise TypeError('yaml path is not referencing a .yaml file')
-
- if 'results_file_path' in kwargs:
- export_path = kwargs['results_file_path']
-
- trex_cmd_str = './t-rex-64 -c %d -m %f -d %d -f %s '
-
- if nc:
- trex_cmd_str = trex_cmd_str + ' --nc '
-
- trex_cmd = trex_cmd_str % (cores,
- multiplier,
- duration,
- self.yaml)
- # self.trex_config['trex_latency'])
-
- for key, value in kwargs.items():
- tmp_key = key.replace('_','-')
- dash = ' -' if (len(key)==1) else ' --'
- if value == True:
- trex_cmd += (dash + tmp_key)
- else:
- trex_cmd += (dash + '{k} {val}'.format( k = tmp_key, val = value ))
-
- print("\nTRex COMMAND: ", trex_cmd)
-
- cmd = 'sshpass.exp %s %s root "cd %s; %s > %s"' % (self.trex_config['trex_password'],
- self.trex_config['trex_name'],
- self.trex_config['trex_version_path'],
- trex_cmd,
- export_path)
-
- return cmd;
-
- def generate_fetch_cmd (self, result_file_full_path="/tmp/trex.txt"):
- """ generate_fetch_cmd(self, result_file_full_path) -> str
-
- Generates a custom command for which will enable to fetch the resutls of the TRex run.
- Returns a command (string) to be issued on the trex server.
-
- Example use: fetch_trex_results() - command that will fetch the content from the default log file- /tmp/trex.txt
- fetch_trex_results("/tmp/trex_secondary_file.txt") - command that will fetch the content from a custom log file- /tmp/trex_secondary_file.txt
- """
- #dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
- script_running_dir = os.path.dirname(os.path.realpath(__file__)) # get the current script working directory so that the sshpass could be accessed.
- cmd = script_running_dir + '/sshpass.exp %s %s root "cat %s"' % (self.trex_config['trex_password'],
- self.trex_config['trex_name'],
- result_file_full_path);
- return cmd;
-
-
-
- def run (self, multiplier, cores, duration, **kwargs):
- """ run(self, multiplier, duration, results_file_path) -> CTRexResults
-
- Running the TRex server based on the config file.
- Returns a CTRexResults object containing the results of the run.
-
- Parameters
- ----------
- multiplier : float
- Defines the TRex multiplier factor (platform dependant)
- duration : int
- Defines the duration of the test
- results_file_path : str
- a full system path to which the results of the trex-run will be logged and fetched from.
-
- """
- tmp_path = None
- # print kwargs
- if 'export_path' in kwargs:
- tmp_path = kwargs['export_path']
- del kwargs['export_path']
- cmd = self.generate_run_cmd(multiplier, cores, duration, tmp_path, **kwargs)
- else:
- cmd = self.generate_run_cmd(multiplier, cores, duration, **kwargs)
-
-# print 'TRex complete command to be used:'
-# print cmd
- # print kwargs
-
- progress_thread = TimedProgressBar(duration)
- progress_thread.start()
- interrupted = False
- try:
- start_time = time.time()
- start = datetime.datetime.now()
- results = subprocess.call(cmd, shell = True, stdout = open(os.devnull, 'wb'))
- end_time = time.time()
- fin = datetime.datetime.now()
- # print "Time difference : ", fin-start
- runtime_deviation = abs(( (end_time - start_time)/ (duration+15) ) - 1)
- print("runtime_deviation: %2.0f %%" % ( runtime_deviation*100.0))
- if ( runtime_deviation > 0.6 ) :
- # If the run stopped immediately - classify as Trex in use or reachability issue
- interrupted = True
- if ((end_time - start_time) < 2):
- raise TRexInUseError ('TRex run failed since TRex is used by another process, or due to reachability issues')
- else:
- CTRexScenario.trex_crashed = True
- # results = subprocess.Popen(cmd, stdout = open(os.devnull, 'wb'),
- # shell=True, preexec_fn=os.setsid)
- except KeyboardInterrupt:
- print("\nTRex test interrupted by user during traffic generation!!")
- results.killpg(results.pid, signal.SIGTERM) # Send the kill signal to all the process groups
- interrupted = True
- raise RuntimeError
- finally:
- progress_thread.join(isPlannedStop = (not interrupted) )
-
- if results!=0:
- sys.stderr.write("TRex run failed. Please Contact trex-dev mailer for further details")
- sys.stderr.flush()
- return None
- elif interrupted:
- sys.stderr.write("TRex run failed due user-interruption.")
- sys.stderr.flush()
- return None
- else:
-
- if tmp_path:
- cmd = self.generate_fetch_cmd( tmp_path )#**kwargs)#results_file_path)
- else:
- cmd = self.generate_fetch_cmd()
-
- try:
- run_log = subprocess.check_output(cmd, shell = True)
- trex_result = CTRexResult(None, run_log)
- trex_result.load_file_lines()
- trex_result.parse()
-
- return trex_result
-
- except subprocess.CalledProcessError:
- sys.stderr.write("TRex result fetching failed. Please Contact trex-dev mailer for further details")
- sys.stderr.flush()
- return None
-
-class CTRexResult():
- """This is an instance for generating a CTRexResult"""
- def __init__ (self, file, buffer = None):
- self.file = file
- self.buffer = buffer
- self.result = {}
-
-
- def load_file_lines (self):
- """ load_file_lines(self) -> None
-
- Loads into the self.lines the content of self.file
- """
- if self.buffer:
- self.lines = self.buffer.split("\n")
- else:
- f = open(self.file,'r')
- self.lines = f.readlines()
- f.close()
-
-
- def dump (self):
- """ dump(self) -> None
-
- Prints nicely the content of self.result dictionary into the screen
- """
- for key, value in self.result.items():
- print("{0:20} : \t{1}".format(key, float(value)))
-
- def update (self, key, val, _str):
- """ update (self, key, val, _str) -> None
-
- Updates the self.result[key] with a possibly new value representation of val
- Example: 15K might be updated into 15000.0
-
- Parameters
- ----------
- key :
- Key of the self.result dictionary of the TRexResult instance
- val : float
- Key of the self.result dictionary of the TRexResult instance
- _str : str
- a represntation of the BW (.
-
- """
-
- s = _str.strip()
-
- if s[0]=="G":
- val = val*1E9
- elif s[0]=="M":
- val = val*1E6
- elif s[0]=="K":
- val = val*1E3
-
- if key in self.result:
- if self.result[key] > 0:
- if (val/self.result[key] > 0.97 ):
- self.result[key]= val
- else:
- self.result[key] = val
- else:
- self.result[key] = val
-
-
-
- def parse (self):
- """ parse(self) -> None
-
- Parse the content of the result file from the TRex test and upload the data into
- """
- stop_read = False
- d = {
- 'total-tx' : 0,
- 'total-rx' : 0,
- 'total-pps' : 0,
- 'total-cps' : 0,
-
- 'expected-pps' : 0,
- 'expected-cps' : 0,
- 'expected-bps' : 0,
- 'active-flows' : 0,
- 'open-flows' : 0
- }
-
- self.error = ""
-
- # Parse the output of the test, line by line (each line matches another RegEx and as such
- # different rules apply
- for line in self.lines:
- match = re.match(".*/var/run/.rte_config.*", line)
- if match:
- stop_read = True
- continue
-
- #Total-Tx : 462.42 Mbps Nat_time_out : 0 ==> we try to parse the next decimal in this case Nat_time_out
-# match = re.match("\W*(\w(\w|[-])+)\W*([:]|[=])\W*(\d+[.]\d+)\W*\w+\W+(\w+)\W*([:]|[=])\W*(\d+)(.*)", line);
-# if match:
-# key = misc_methods.mix_string(match.group(5))
-# val = float(match.group(7))
-# # continue to parse !! we try the second
-# self.result[key] = val #update latest
-
- # check if we need to stop reading
- match = re.match(".*latency daemon has stopped.*", line)
- if match:
- stop_read = True
- continue
-
- match = re.match("\W*(\w(\w|[-])+)\W*([:]|[=])\W*(\d+[.]\d+)(.*ps)\s+(\w+)\W*([:]|[=])\W*(\d+)", line)
- if match:
- key = misc_methods.mix_string(match.group(1))
- val = float(match.group(4))
- if key in d:
- if stop_read == False:
- self.update (key, val, match.group(5))
- else:
- self.result[key] = val # update latest
- key2 = misc_methods.mix_string(match.group(6))
- val2 = int(match.group(8))
- self.result[key2] = val2 # always take latest
-
-
- match = re.match("\W*(\w(\w|[-])+)\W*([:]|[=])\W*(\d+[.]\d+)(.*)", line)
- if match:
- key = misc_methods.mix_string(match.group(1))
- val = float(match.group(4))
- if key in d:
- if stop_read == False:
- self.update (key, val, match.group(5))
- else:
- self.result[key] = val # update latest
- continue
-
- match = re.match("\W*(\w(\w|[-])+)\W*([:]|[=])\W*(\d+)(.*)", line)
- if match:
- key = misc_methods.mix_string(match.group(1))
- val = float(match.group(4))
- self.result[key] = val #update latest
- continue
-
- match = re.match("\W*(\w(\w|[-])+)\W*([:]|[=])\W*(OK)(.*)", line)
- if match:
- key = misc_methods.mix_string(match.group(1))
- val = 0 # valid
- self.result[key] = val #update latest
- continue
-
- match = re.match("\W*(Cpu Utilization)\W*([:]|[=])\W*(\d+[.]\d+) %(.*)", line)
- if match:
- key = misc_methods.mix_string(match.group(1))
- val = float(match.group(3))
- if key in self.result:
- if (self.result[key] < val): # update only if larger than previous value
- self.result[key] = val
- else:
- self.result[key] = val
- continue
-
- match = re.match(".*(rx_check\s.*)\s+:\s+(\w+)", line)
- if match:
- key = misc_methods.mix_string(match.group(1))
- try:
- val = int(match.group(2))
- except ValueError: # corresponds with rx_check validation case
- val = match.group(2)
- finally:
- self.result[key] = val
- continue
-
-
- def get_status (self, drop_expected = False):
- if (self.error != ""):
- print(self.error)
- return (self.STATUS_ERR_FATAL)
-
- d = self.result
-
- # test for latency
- latency_limit = 5000
- if ( d['maximum-latency'] > latency_limit ):
- self.reason="Abnormal latency measured (higher than %s" % latency_limit
- return self.STATUS_ERR_LATENCY
-
- # test for drops
- if drop_expected == False:
- if ( d['total-pkt-drop'] > 0 ):
- self.reason=" At least one packet dropped "
- return self.STATUS_ERR_DROP
-
- # test for rx/tx distance
- rcv_vs_tx = d['total-tx']/d['total-rx']
- if ( (rcv_vs_tx >1.2) or (rcv_vs_tx <0.9) ):
- self.reason="rx and tx should be close"
- return self.STATUS_ERR_RX_TX_DISTANCE
-
- # expected measurement
- expect_vs_measued=d['total-tx']/d['expected-bps']
- if ( (expect_vs_measued >1.1) or (expect_vs_measued < 0.9) ) :
- print(expect_vs_measued)
- print(d['total-tx'])
- print(d['expected-bps'])
- self.reason="measure is not as expected"
- return self.STATUS_ERR_BAD_EXPECTED_MEASUREMENT
-
- if ( d['latency-any-error'] !=0 ):
- self.reason=" latency-any-error has error"
- return self.STATUS_ERR_LATENCY_ANY_ERROR
-
- return self.STATUS_OK
-
- # return types
- STATUS_OK = 0
- STATUS_ERR_FATAL = 1
- STATUS_ERR_LATENCY = 2
- STATUS_ERR_DROP = 3
- STATUS_ERR_RX_TX_DISTANCE = 4
- STATUS_ERR_BAD_EXPECTED_MEASUREMENT = 5,
- STATUS_ERR_LATENCY_ANY_ERROR = 6
-
-def test_TRex_result_parser():
- t=CTRexResult('trex.txt');
- t.load_file_lines()
- t.parse()
- print(t.result)
-
-
-
-
-if __name__ == "__main__":
- #test_TRex_result_parser();
- pass
diff --git a/scripts/automation/regression/trex_unit_test.py b/scripts/automation/regression/trex_unit_test.py
index 39984c7d..2a544711 100755
--- a/scripts/automation/regression/trex_unit_test.py
+++ b/scripts/automation/regression/trex_unit_test.py
@@ -399,16 +399,19 @@ class CTRexTestConfiguringPlugin(Plugin):
if not CTRexScenario.trex.check_master_connectivity():
fatal('Could not connect to master daemon')
if options.ga and CTRexScenario.setup_name:
- CTRexScenario.GAManager = GAmanager_Regression(GoogleID = 'UA-75220362-3',
- AnalyticsUserID = CTRexScenario.setup_name,
- QueueSize = 100,
- Timeout = 3, # seconds
- UserPermission = 1,
- BlockingMode = 0,
- appName = 'TRex',
- appVer = CTRexScenario.trex_version)
-
- CTRexScenario.elk = trex_elk.TRexEs('sceasr-b20',9200);
+ CTRexScenario.GAManager = GAmanager_Regression(
+ GoogleID = CTRexScenario.global_cfg['google']['id'],
+ AnalyticsUserID = CTRexScenario.setup_name,
+ QueueSize = CTRexScenario.global_cfg['google']['queue_size'],
+ Timeout = CTRexScenario.global_cfg['google']['timeout'], # seconds
+ UserPermission = 1,
+ BlockingMode = CTRexScenario.global_cfg['google']['blocking'],
+ appName = 'TRex',
+ appVer = CTRexScenario.trex_version)
+
+ CTRexScenario.elk = trex_elk.TRexEs(
+ CTRexScenario.global_cfg['elk']['server'],
+ CTRexScenario.global_cfg['elk']['port']);
self.set_cont_elk_info ()
def set_cont_elk_info (self):