summaryrefslogtreecommitdiffstats
path: root/VNFs/DPPD-PROX/helper-scripts/dpi
diff options
context:
space:
mode:
Diffstat (limited to 'VNFs/DPPD-PROX/helper-scripts/dpi')
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/README41
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/config.py178
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/csvreader.py78
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/csvwriter.py35
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/dpi1.py243
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/dpi2.py229
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/maketable.py140
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/progress.py67
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/prox.py253
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/proxdpisut.py61
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/proxdpitester.py258
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/proxmaxssprobe.py34
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/proxsocket.py54
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/ratedistribution.py69
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/remotesystem.py58
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/resultprocessor.py210
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/statsconsfile.py84
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/sutstatsconsfile.py61
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/systemconfig.py73
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/testerset.py176
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/timeseriespoint.py39
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/dpi/tsstatsconsfile.py60
22 files changed, 2501 insertions, 0 deletions
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/README b/VNFs/DPPD-PROX/helper-scripts/dpi/README
new file mode 100644
index 00000000..f1100757
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/README
@@ -0,0 +1,41 @@
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+The scripts in this directory characterize flow a DPI-enabled VNF. The
+characeterization is split up into two steps. The first step (dpi1.py)
+searches for the traffic profile parameter boundaries. The second step
+(dpi2.py) takes as input the output of the first step and searches for
+the maximum sustainable throughput of a DPI-enabled VNF.
+
+To run the first script, use:
+
+ python2.7 ./dpi1.py -t TEST_SYSTEM_DESCRIPTIONS -o OUTPUT1
+
+TEST_SYSTEM_DESCRIPTIONS is a comma-separated list of systems where
+the syntax of defining each system is shown below:
+
+ user@ip:proxDir:cfgDir
+
+To run the second script, use:
+
+ python2.7 ./dpi2.py -t TEST_SYSTEM_DESCRIPTIONS \
+ -s SYSTEM_UNDER_TEST_DESCRIPTIONS \
+ -o OUTPUT2 -d \
+ -i OUTPUT1
+
+Finally, the results can be processed using the following command:
+
+ python2.7 ./maketable.py -i OUTPUT1 -j OUTPUT2 -o FINAL_TABLE
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/config.py b/VNFs/DPPD-PROX/helper-scripts/dpi/config.py
new file mode 100644
index 00000000..ee3f04c6
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/config.py
@@ -0,0 +1,178 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+import getopt
+import sys
+from systemconfig import *
+
+class Config:
+ _debug = False;
+ _test_systems = [];
+ _output_file_name = None;
+ _input_file_name = None
+ _input_file_name2 = None
+ _max_port_rate = 0.85
+ _sut = None
+ _accuracy = 2;
+ _threshold = 0.95
+ _once = None
+ _skipTime = 10
+ _testLength = 120
+ _dpiCoreList = range(1, 5)
+ _checkConditions = False;
+ _interCheckDuration = float(1)
+
+ def getInputFileName(self):
+ return self._input_file_name
+
+ def getInputFileName2(self):
+ return self._input_file_name2
+
+ def toString(self):
+ ret = ""
+ ret += "Test systems: \n"
+ for ts in self._test_systems:
+ ret += ts.toString();
+
+ if (self._sut is not None):
+ ret += "SUT: \n"
+ ret += self._sut.toString();
+
+ ret += "Output file name: " + str(self._output_file_name) + "\n"
+ ret += "Max port rate: " + str(self._max_port_rate) + "\n"
+ ret += "Accuracy: " + str(self._accuracy) + " digits after point"
+ return ret
+
+ def getErrorTestOne(self):
+ if (len(self._test_systems) == 0):
+ return "Missing test systems";
+ if (self._output_file_name is None):
+ return "No output file or input file defined";
+ return None
+
+ def getErrorTestTwo(self):
+ if (self._input_file_name is None):
+ return "Input file is missing"
+ if (self._input_file_name == self._output_file_name):
+ return "Input file and output file are the same"
+ return self.getErrorTestOne();
+
+ def getErrorMakeTable(self):
+ if (self._input_file_name is None):
+ return "Missing input file"
+ if (self._input_file_name2 is None):
+ return "Missing file with performance resuilts"
+ if (self._output_file_name is None):
+ return "No output file or input file defined";
+ if (self._input_file_name2 == self._input_file_name):
+ return "Input file used multiple times"
+ if (self._input_file_name == self._output_file_name):
+ return "output file is the same as the input file"
+ if (self._input_file_name2 == self._output_file_name):
+ return "output file is the same as the input file 2"
+
+ return None
+
+ def usageAndExit(self, argv0):
+ print "Usage: " + str(argv0)
+ print "-t Add a test system, syntax: " + SystemConfig.expectedSyntax()
+ print "-s Add SUT, syntax: " + SystemConfig.expectedSyntax()
+ print "-o Ouput file name"
+ print "-a Accuracy, number of digits after point"
+ print "-i Input file"
+ print "-j File with performance results"
+ print "-m Maximum per port rate, by default 0.85 (85%)"
+ print "-d Enable debugging"
+ print "-w Fraction of connections to reach, by default is 0.95 (95%)"
+ print "-h Show help"
+ print "-q Run a single test iteration, syntax of argument "
+ print "-b Skip time, by default 10 sec"
+ print "-l Test length, by default 120 sec"
+ print "-n Maximum number of DPI cores to test"
+ print "-k Period between checking conditions, 1 second by default"
+ print "-c Check conditions during 10 second period after convergence"
+ print " is msr,conn,ss (i.e. -q 4000,100000,38.91)"
+ exit(-1);
+
+ def parse(self, programName, args):
+ try:
+ opts, args = getopt.getopt(args, "t:s:o:a:i:q:m:dhw:j:b:l:n:k:c")
+ except getopt.GetoptError as err:
+ print str(err)
+ return;
+ for option, arg in opts:
+ if(option == "-t"):
+ for ts in arg.split(","):
+ syntaxErr = SystemConfig.checkSyntax(ts)
+ if (syntaxErr != ""):
+ print syntaxErr
+ exit(-1);
+ self._test_systems.append(SystemConfig(ts));
+ elif(option == "-s"):
+ syntaxErr = SystemConfig.checkSyntax(ts)
+ if (syntaxErr != ""):
+ print syntaxErr
+ exit(-1);
+ self._sut = SystemConfig(arg);
+ elif(option == "-w"):
+ self._threshold = float(arg)
+ elif(option == "-o"):
+ self._output_file_name = arg;
+ elif(option == '-a'):
+ self._accuracy = int(arg);
+ elif(option == "-i"):
+ self._input_file_name = arg;
+ elif(option == "-j"):
+ self._input_file_name2 = arg;
+ elif(option == "-q"):
+ self._once = arg.split(",")
+ elif(option == "-c"):
+ self._checkConditions = True;
+ elif(option == "-m"):
+ self._max_port_rate = float(arg);
+ elif(option == "-k"):
+ self._interCheckDuration = float(arg);
+ elif(option == "-d"):
+ self._debug = True
+ elif(option == '-h'):
+ self.usageAndExit(programName)
+ elif(option == '-b'):
+ self._skipTime = int(arg)
+ elif(option == '-l'):
+ self._testLength = int(arg)
+ elif(option == '-n'):
+ self._dpiCoreList = self.strToList(arg)
+ else:
+ self.usageAndExit(programName);
+
+ def strToList(self, arg):
+ elements = [];
+ tokens = arg.split(",");
+
+ for a in tokens:
+ if (a.count('-') == 0):
+ elements.append(int(a))
+ elif (a.count('-') == 1):
+ beg = int(a.split('-')[0]);
+ end = int(a.split('-')[1]);
+ if (beg > end):
+ raise Exception("Invalid list input format")
+ elements += range(beg, end + 1);
+ else:
+ raise Exception("Invalid list input format")
+ return elements;
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/csvreader.py b/VNFs/DPPD-PROX/helper-scripts/dpi/csvreader.py
new file mode 100644
index 00000000..b0b650dc
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/csvreader.py
@@ -0,0 +1,78 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+from decimal import *
+
+class CsvReaderError:
+ def __init__(self, msg):
+ self._msg = msg;
+
+ def __str__(self):
+ return self._msg;
+
+class CsvReader:
+ def __init__(self, fieldTypes = None):
+ self._file_name = None;
+ self._fieldTypes = fieldTypes;
+
+ def open(self, file_name):
+ self._file = open(file_name, 'r');
+ self._file_name = file_name;
+
+ def read(self):
+ line = "#"
+ while (len(line) != 0 and line[0] == "#"):
+ line = self._file.readline();
+
+ if (len(line) != 0):
+ return self._lineToEntry(line)
+ else:
+ return None;
+
+ def _lineToEntry(self, line):
+ split = line.strip().split(',');
+ if (self._fieldTypes is None):
+ return split;
+ have = len(split)
+ expected = len(self._fieldTypes)
+ if (have != expected):
+ raise CsvReaderError("Invalid number of fields %d != %d" % (have, expected))
+
+ entry = {};
+ for i in range(len(self._fieldTypes)):
+ curFieldType = self._fieldTypes[i][1]
+ curFieldName = self._fieldTypes[i][0];
+ if (curFieldType == "int"):
+ entry[curFieldName] = int(split[i])
+ elif (curFieldType == "Decimal"):
+ entry[curFieldName] = Decimal(split[i])
+ else:
+ raise CsvReaderError("Invalid field type %s" % curFieldType);
+ return entry;
+
+ def readAll(self):
+ ret = []
+ line = self.read();
+ while (line != None):
+ ret.append(line);
+ line = self.read();
+ return ret;
+
+ def close(self):
+ self._file.close();
+ self._file = None;
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/csvwriter.py b/VNFs/DPPD-PROX/helper-scripts/dpi/csvwriter.py
new file mode 100644
index 00000000..a5f055e8
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/csvwriter.py
@@ -0,0 +1,35 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+class CsvWriter:
+ def __init__(self):
+ self._file_name = None;
+
+ def open(self, file_name):
+ self._file = open(file_name, 'w');
+ self._file_name = file_name;
+
+ def write(self, elements):
+ elements_str = map(lambda x: str(x), elements);
+ line = ",".join(elements_str);
+ self._file.write(line + "\n");
+ self._file.flush();
+
+ def close(self):
+ self._file.close();
+ self._file = None;
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/dpi1.py b/VNFs/DPPD-PROX/helper-scripts/dpi/dpi1.py
new file mode 100644
index 00000000..ec3e4a03
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/dpi1.py
@@ -0,0 +1,243 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+from testerset import *
+from time import sleep
+from time import time
+from decimal import *
+import copy
+from os import system
+import socket
+from itertools import chain
+from math import *
+from csvwriter import *
+from config import *
+from progress import *
+from proxmaxssprobe import *
+
+def runTest(minSetupRate, testParam):
+ print "Running test with following parameters:"
+ print testParam.toString();
+
+ testers = testerSet(config._test_systems, config._max_port_rate, testParam);
+
+ thresh = testParam.getConnections();
+ p = Progress(thresh, ["connections", "setup rate", "reTX"], False);
+ loop_count = 0;
+ converged = False;
+
+ testers.startForkJoin();
+ testers.wait_links_up();
+ testers.start_cores();
+
+ print "Running until convergence (%s connections)" % str(thresh)
+ while (not converged):
+ sleep(config._interCheckDuration)
+ testers.update_stats();
+ tot = testers.get_total_connections();
+ tot_retx = testers.get_total_retx();
+ rates = testers.get_rates();
+ curSetupRate = testers.get_setup_rate();
+ ierrors = testers.getIerrors();
+
+ converged = tot >= thresh;
+ if (not converged):
+ if (loop_count > 0 and curSetupRate < minSetupRate):
+ reason = str(curSetupRate) + " < " + str(minSetupRate);
+ print "Current setup rate is lower than min setup rate: " + reason
+ testers.killProx();
+ return False, [];
+ if (not testers.conditionsGood()):
+ print "conditions are bad: " + testers.getReason();
+ testers.killProx();
+ return False, [];
+
+ if (config._debug):
+ p.setProgress(tot, [tot, curSetupRate, tot_retx]);
+ print p.toString();
+ loop_count += 1;
+ print "converged"
+
+ skipTime = config._skipTime
+ print "Connection threshold reached, waiting for " + str(skipTime) + "s, conditions checked = " + str(config._checkConditions)
+ while (skipTime > 0):
+ skipTime -= config._interCheckDuration
+ sleep(config._interCheckDuration)
+ testers.update_stats();
+ if (config._checkConditions and not testers.conditionsGood()):
+ print "conditions are bad: " + testers.getReason();
+ testers.killProx();
+ return False, [];
+
+ testers.tx_rate_meassurement();
+
+ testLength = config._testLength
+ print "Waiting final " + str(testLength) + "s"
+ while (testLength > 0):
+ testLength -= config._interCheckDuration
+ sleep(config._interCheckDuration)
+ testers.update_stats();
+ if (not testers.conditionsGood()):
+ print "conditions are bad: " + testers.getReason();
+ testers.killProx();
+ return False, [];
+
+ rates = testers.tx_rate_meassurement();
+
+ testers.killProx();
+ return True, rates;
+
+def find_ss(tot_conn, maxSetupRate, ss_max):
+ iterationCount = 0;
+ valid_ss = []
+ speed_ss = [];
+
+ # The setup rate must be in [0.2% of total connections, maxSetupRate]
+ # Also, it must not be hihger than 50% of the total connections
+ min_setup_rate = tot_conn / 500;
+
+ if (min_setup_rate > maxSetupRate):
+ print "min setup rate > max setup rate: " + str(min_setup_rate) + " > " + str(maxSetupRate);
+ return valid_ss, speed_ss;
+ if (maxSetupRate > tot_conn / 2):
+ print "maximum setup rate (" + str(maxSetupRate) + ") is more than 50% of " + str(tot_conn)
+ return valid_ss, speed_ss;
+
+ accuracy = 10**config._accuracy
+ ss_lo = 1
+ ss_hi = int(round(ss_max * accuracy,0))
+
+ iterationOverride = [ss_hi, ss_lo];
+ # Binary search for highest speed scaling
+ while (ss_lo <= ss_hi):
+ if (iterationCount < len(iterationOverride)):
+ ss = iterationOverride[iterationCount]
+ else:
+ ss = (ss_lo + ss_hi)/2;
+
+ testParam = TestParameters(maxSetupRate, tot_conn, float(ss)/accuracy);
+
+ success, rates = runTest(min_setup_rate, testParam);
+ print "success = " + str(success) + ", rates = " + str(rates)
+ if (success == True):
+ valid_ss.append(float(ss)/accuracy);
+ speed_ss.append(sum(rates)/len(rates))
+ ss_lo = ss + 1
+ else:
+ ss_hi = ss - 1;
+ iterationCount += 1
+ return valid_ss, speed_ss;
+
+def get_highest_ss_and_speed(valid_ss, speed_ss):
+ highest_ss = None;
+ highest_speed = None;
+
+ for i in range(len(valid_ss)):
+ if(highest_ss == None or highest_ss < valid_ss[i]):
+ highest_ss = valid_ss[i];
+ highest_speed = speed_ss[i];
+ return highest_ss, highest_speed;
+
+def get_max_ss():
+ ts = config._test_systems[0];
+ test_system = ProxMaxSSProbe(ts);
+ max_ss = test_system.getMaxSS();
+
+ return floor((max_ss * (10**config._accuracy)))/(10**config._accuracy)
+
+config = Config();
+config.parse(sys.argv[0], sys.argv[1:])
+
+err = config.getErrorTestOne();
+if (err is not None):
+ print "Invalid configuration: " + err;
+ exit(-1);
+else:
+ print config.toString()
+
+if (config._once is not None):
+ maxSetupRate = int(config._once[0])
+ minSetupRate = maxSetupRate/500
+ connections = int(config._once[1])
+ speedScaling = float(config._once[2])
+
+ testParam = TestParameters(maxSetupRate, connections, speedScaling)
+ success, rates = runTest(minSetupRate, testParam)
+ print "success = " + str(success) + ", port rates = " + str(rates)
+ exit(0);
+
+msr_list = []
+msr_list += range(4000, 20000, 2000)
+msr_list += range(20000, 100000, 20000)
+msr_list += range(100000, 300000, 50000)
+msr_list += range(300000, 800001, 100000);
+
+conn_list = [1*10**5, 2*10**5, 4*10**5, 8*10**5, 1*10**6, 2*10**6]
+
+summary_file = CsvWriter()
+summary_file.open(config._output_file_name)
+
+tot_it = 0;
+for tot_conn in conn_list:
+ for msr in msr_list:
+ if (msr >= tot_conn/2):
+ break;
+ tot_it += 1
+
+cnt = -1;
+print "Search will include " + str(tot_it) + " parameter combinations"
+print "Will search for highest link utilization"
+
+# If the lowest msr was a for n connections, then the lowest msr
+# for n + 1 connections can't be lower than a.
+low_sr = msr_list[0];
+
+max_ss = get_max_ss()
+
+high_ss = Decimal(max_ss)
+
+globalProgress = Progress(tot_it)
+globalProgress.setProgress(0);
+for tot_conn in conn_list:
+ had_success = False;
+ all_ss = []
+ for msr in msr_list:
+ globalProgress.incrProgress();
+
+ if (msr < low_sr):
+ print "skipping " + str(msr) + " since it is lower than " + str(low_sr)
+ continue;
+
+ print globalProgress.toString();
+
+ valid_ss, speed_ss = find_ss(tot_conn, msr, high_ss)
+ print "valid ss = " + str(valid_ss)
+ print "valid speeds = " + str(speed_ss)
+
+ if (len(valid_ss) > 0):
+ highest_ss, highest_speed = get_highest_ss_and_speed(valid_ss, speed_ss);
+ summary_file.write([msr, tot_conn, highest_ss, highest_speed]);
+
+ if (not had_success):
+ low_sr = msr;
+
+ had_success = True;
+ all_ss = all_ss + valid_ss;
+
+ if (len(all_ss) > 0):
+ high_ss = max(all_ss);
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/dpi2.py b/VNFs/DPPD-PROX/helper-scripts/dpi/dpi2.py
new file mode 100644
index 00000000..65473f61
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/dpi2.py
@@ -0,0 +1,229 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+from testerset import *
+from proxdpisut import *
+from statsconsfile import *
+from time import sleep
+from time import time
+from decimal import *
+import copy
+from os import system
+import socket
+from itertools import chain
+from math import *
+from csvwriter import *
+from csvreader import *
+from config import *
+from progress import *
+from resultprocessor import *
+
+def runTest(coreCount, testParam):
+ print "Running test with following parameters:"
+ print testParam.toString();
+
+
+ testers = testerSet(config._test_systems, config._max_port_rate, testParam);
+
+ ret = TestResult(testers.getCount());
+ thresh = testParam.getConnections() * config._threshold;
+ converged = False;
+
+ sut = ProxDpiSut(config._sut, coreCount);
+
+ testers.startFork();
+ sut.startFork();
+ testers.startJoin();
+ sut.startJoin();
+ testers.wait_links_up();
+ sut.startAllCores();
+ sut.waitCmdFinished();
+ testers.start_cores();
+
+ ret.addTimeTS(testers.getTsc());
+ ret.addTimeSUT(sut.getTsc());
+
+ print "Running until convergence (%s connections)" % str(thresh)
+ p = Progress(thresh, ["connections", "setup rate", "reTX"], False);
+ while (not converged):
+ sleep(config._interCheckDuration)
+ testers.update_stats();
+
+ tot = testers.get_total_connections();
+ tot_retx = testers.get_total_retx();
+ rates = testers.get_rates();
+ cur_setup_rate = testers.get_setup_rate();
+ ierrors = testers.getIerrors();
+ converged = tot >= thresh;
+
+ if (not converged and not testers.conditionsGood()):
+ print "conditions are bad: " + testers.getReason();
+ sut.forceQuit();
+ sut.killProx();
+ testers.killProx();
+ return None;
+
+ if (sut.getIerrors() != 0):
+ testers.killProx();
+ print "Sending quit"
+ try:
+ sut.forceQuit();
+ except:
+ print "Sending quit failed"
+ sut.killProx();
+ return None;
+
+ if (config._debug):
+ p.setProgress(tot, [tot, cur_setup_rate, tot_retx]);
+ print p.toString();
+
+ skipTime = config._skipTime
+ print "Connection threshold reached, waiting for " + str(skipTime) + "s, conditions checked = " + str(config._checkConditions)
+ while (skipTime > 0):
+ skipTime -= config._interCheckDuration
+ sleep(config._interCheckDuration)
+ testers.update_stats();
+ if (config._checkConditions and not testers.conditionsGood()):
+ print "conditions are bad: " + testers.getReason();
+ sut.forceQuit();
+ sut.killProx();
+ testers.killProx();
+ return False, [];
+
+ ret.addTimeTS(testers.getTsc());
+ ret.addTimeSUT(sut.getTsc());
+
+ testers.tx_rate_meassurement();
+
+ testLength = config._testLength
+ print "Waiting final " + str(testLength) + "s"
+ while (testLength > 0):
+ testLength -= config._interCheckDuration
+ testers.update_stats();
+ if (not testers.conditionsGood()):
+ print "conditions are bad: " + testers.getReason();
+ sut.forceQuit();
+ sut.killProx();
+ testers.killProx();
+ return None;
+
+ if (sut.getIerrors() != 0):
+ testers.killProx();
+ print "Sending quit"
+ try:
+ sut.forceQuit();
+ except:
+ print "Sending quit failed"
+ sut.killProx();
+ return None;
+
+ sleep(config._interCheckDuration)
+
+ rates = testers.tx_rate_meassurement();
+ ret.addTimeTS(testers.getTsc());
+ ret.addTimeSUT(sut.getTsc());
+
+ print "Quiting Prox on SUT"
+ # make sure stats are flushed
+ sut.quitProx();
+ print "Quiting Prox on test system(s)"
+ testers.quitProx()
+
+ ret.rates = rates
+
+ sutStatsDump = "stats_dump_sut"
+ tsStatsDumpBaseName = "stats_dump_ts"
+
+ sut.scpStatsDump(sutStatsDump);
+ tsStatsDump = testers.scpStatsDump(tsStatsDumpBaseName);
+
+ ret.setTSStatsDump(tsStatsDump);
+ ret.setSUTStatsDump(sutStatsDump);
+ return ret
+
+def meassurePerf(coreCount, maxSetupRate, total_connections, ss_hi):
+ iterationCount = 0;
+ accuracy = 10**config._accuracy
+ ss_lo = 1
+ ss_hi = int(round(ss_hi * accuracy, 0))
+ success = True;
+
+ downrate = float(0)
+ highest_ss = 0
+ iterationOverride = [ss_hi, ss_lo];
+ while (ss_lo <= ss_hi):
+ if (iterationCount < len(iterationOverride)):
+ ss = iterationOverride[iterationCount]
+ else:
+ ss = (ss_lo + ss_hi)/2;
+
+ testParam = TestParameters(maxSetupRate, total_connections, float(ss)/accuracy);
+
+ result = runTest(coreCount, testParam);
+
+ if (result is None):
+ success = False
+ else:
+ rp = ResultProcessor(result)
+ rp.process();
+ success = rp.percentHandled() > 0.99999
+
+ print "test result = " + str(success)
+ if (success):
+ ss_lo = ss + 1;
+ highest_ss = max(highest_ss, ss);
+ print result.rates
+ downrate = sum(result.rates)/len(result.rates)
+ else:
+ ss_hi = ss - 1;
+ iterationCount += 1
+
+ return downrate, float(highest_ss)/accuracy
+
+config = Config();
+config.parse(sys.argv[0], sys.argv[1:])
+
+err = config.getErrorTestTwo();
+if (err is not None):
+ print "Invalid configuration: " + err;
+ exit(-1);
+else:
+ print config.toString()
+
+infileFields = []
+infileFields += [("msr", "int")]
+infileFields += [("conn", "int")]
+infileFields += [("ss", "Decimal")]
+infileFields += [("bw", "Decimal")]
+
+infile = CsvReader(infileFields);
+infile.open(config.getInputFileName())
+inputs = infile.readAll()
+infile.close();
+
+summary = CsvWriter();
+summary.open(config._output_file_name);
+
+print "Will test up SUT config with " + str(config._dpiCoreList) + " DPI cores"
+
+for a in inputs:
+ for coreCount in config._dpiCoreList:
+ downrate, ss = meassurePerf(coreCount, a["msr"], a["conn"], a["ss"]);
+ summary.write([coreCount, a["msr"], a["conn"], ss, downrate]);
+
+summary.close()
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/maketable.py b/VNFs/DPPD-PROX/helper-scripts/dpi/maketable.py
new file mode 100644
index 00000000..f8b7bdc0
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/maketable.py
@@ -0,0 +1,140 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+import sys
+from config import *
+from csvreader import *
+from sets import Set
+from csvwriter import *
+
+class ResultEntry:
+ def __init__(self):
+ self.boundary = None;
+ self.cores = {}
+
+ def setBoundary(self, val):
+ self.boundary = val;
+
+ def addCoreResult(self, core, val):
+ self.cores[core] = val
+
+ def getCoreResult(self, core):
+ if (core in self.cores):
+ return self.cores[core];
+ return None;
+
+ def getBoundary(self):
+ return self.boundary;
+
+ def getCores(self):
+ return self.cores
+
+ def getMsr(self):
+ return self.msr;
+
+class DictEntry:
+ def __init__(self, key):
+ self.dictionary = {}
+ self.entries = []
+ self.key = key;
+
+config = Config();
+config.parse(sys.argv[0], sys.argv[1:])
+
+err = config.getErrorMakeTable();
+
+if (err is not None):
+ print err
+ exit(-1);
+
+if (config._debug):
+ print "Performance data: " + config.getInputFileName2()
+ print "Boundaries: " + config.getInputFileName()
+
+allData = {}
+
+infileFields = []
+infileFields += [("msr", "int")]
+infileFields += [("conn", "int")]
+infileFields += [("ss", "Decimal")]
+infileFields += [("bw", "Decimal")]
+
+boundariesFile = CsvReader(infileFields)
+boundariesFile.open(config.getInputFileName());
+boundaries = boundariesFile.readAll();
+
+cores = Set()
+
+orderedResults = []
+finalResults = {}
+
+for a in boundaries:
+ key = a["conn"]
+ if (key not in finalResults):
+ newDict = DictEntry(key)
+ finalResults[key] = newDict
+ orderedResults.append(newDict)
+
+for a in boundaries:
+ table = finalResults[a["conn"]]
+ key = a["msr"]
+ value = ResultEntry()
+ value.msr = a["msr"]
+ value.conn = a["conn"]
+ value.boundary = a["bw"]
+ table.dictionary[key] = value
+ table.entries.append(value)
+
+infileFields2 = []
+infileFields2 += [("cores", "int")]
+infileFields2 += [("msr", "int")]
+infileFields2 += [("conn", "int")]
+infileFields2 += [("ss", "Decimal")]
+infileFields2 += [("down", "Decimal")]
+
+resultsFile = CsvReader(infileFields2)
+resultsFile.open(config.getInputFileName2())
+
+for a in resultsFile.readAll():
+ table = finalResults[a["conn"]]
+ key = a["msr"]
+ table.dictionary[key].addCoreResult(a["cores"], a["down"])
+ cores.add(a["cores"]);
+
+
+outputFile = CsvWriter()
+
+outputFile.open(config._output_file_name)
+
+title = ["setup rate", "maximum"]
+for e in sorted(cores):
+ title += [str(e)]
+
+for a in orderedResults:
+ outputFile.write(["connections = " + str(a.key)])
+ outputFile.write(title)
+
+ for e in a.entries:
+ line = [str(e.getMsr())]
+ line += [str(e.getBoundary())]
+ for c in sorted(cores):
+ if (e.getCoreResult(c) is not None):
+ line += [str(e.getCoreResult(c))]
+ else:
+ line += [""]
+ outputFile.write(line)
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/progress.py b/VNFs/DPPD-PROX/helper-scripts/dpi/progress.py
new file mode 100644
index 00000000..5e44c678
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/progress.py
@@ -0,0 +1,67 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+from decimal import *
+from time import time
+
+class Progress:
+ def __init__(self, limit, fieldNames = [], overallETA = True):
+ self._fieldNames = fieldNames;
+ self._limit = limit;
+ self._progress = 0;
+ self._prevProgress = 0;
+ self._prevTime = 0;
+ self._progressSetCount = 0;
+ self._time = 0;
+ self._overallETA = overallETA;
+
+ def setProgress(self, progress, fieldValues = []):
+ self._fieldValues = fieldValues;
+ if (self._overallETA == True):
+ self._progress = progress
+ self._time = time();
+ if (self._progressSetCount == 0):
+ self._prevProgress = self._progress;
+ self._prevTime = self._time;
+ else:
+ self._prevProgress = self._progress;
+ self._prevTime = self._time;
+ self._progress = progress;
+ self._time = time();
+ self._progressSetCount += 1
+
+ def incrProgress(self):
+ self.setProgress(self._progress + 1);
+
+ def toString(self):
+ ret = ""
+ ret += str(self._getETA()) + " seconds left"
+ for f,v in zip(self._fieldNames, self._fieldValues):
+ ret += ", %s=%s" % (str(f),str(v))
+ return ret;
+
+ def _getETA(self):
+ if (self._progressSetCount < 2):
+ return "N/A"
+ diff = self._progress - self._prevProgress;
+ t_diff = Decimal(self._time - self._prevTime);
+ if (t_diff < 0.001 or diff <= 0):
+ return "N/A"
+ rate = Decimal(diff)/t_diff
+ remaining = Decimal(self._limit - self._progress);
+ return round(remaining/rate, 2);
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/prox.py b/VNFs/DPPD-PROX/helper-scripts/dpi/prox.py
new file mode 100644
index 00000000..60ef7592
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/prox.py
@@ -0,0 +1,253 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+import threading
+from time import *
+from proxsocket import *
+from remotesystem import *
+
+class ProxStarter:
+ def __init__(self, remoteSystem, cmd):
+ self._remoteSystem = remoteSystem
+ self._cmd = cmd
+ self._thread = None
+ self._prox = None;
+ self._result = None;
+ self._startDuration = None
+
+ def startThreaded(self):
+ self._start_thread = threading.Thread(target = self._run, args = (self, 1))
+ self._start_thread.start();
+
+ def joinThreaded(self):
+ self._start_thread.join();
+ return self._result;
+
+ def getResult(self):
+ return self._result;
+
+ def getStartDuration(self):
+ return self._startDuration;
+ def getProx(self):
+ return self._prox;
+
+ def _run(self, a, b):
+ before = time.time()
+ self._remoteSystem.run("sudo killall -w -q -9 prox")
+
+ self._result = self._remoteSystem.run(self._cmd);
+
+ sleep(1)
+ after = time.time()
+ self._startDuration = after - before;
+
+class StatsCmd(object):
+ def __init__(self, prox):
+ self._cmd = ""
+ self._parts = []
+ self._beforeParts = []
+ self._prox = prox;
+
+ def sendRecv(self):
+ cmd = self.getCmd()
+ reply = self._prox._send(cmd)._recv()
+ self.setReply(reply)
+
+ def add(self, stats):
+ if (len(self._cmd) != 0):
+ self._cmd += ","
+ self._cmd += stats
+
+ if (len(self._parts) == 0):
+ self._beforeParts += [0]
+ else:
+ before = self._parts[-1] + self._beforeParts[-1];
+ self._beforeParts += [before]
+
+ self._parts += [stats.count(",") + 1];
+
+ def getCmd(self):
+ return "stats " + self._cmd;
+
+ def setReply(self, reply):
+ self._reply = reply.split(",");
+
+ def getResult(self, idx):
+ start = self._beforeParts[idx];
+ end = start + self._parts[idx];
+ return self._reply[start:end]
+
+class Prox(object):
+ def __init__(self, systemConfig):
+ self._systemConfig = systemConfig;
+ self._proxStarter = None
+
+ user = self._systemConfig._user
+ ip = self._systemConfig._ip
+ self._remoteSystem = remoteSystem(user, ip);
+
+ self.resetArguments()
+
+ def resetArguments(self):
+ self._args = []
+
+ def addArgument(self, arg):
+ self._args.append(arg);
+
+ def startFork(self):
+ cmd = self.getCmd();
+ self._proxStarter = ProxStarter(self._remoteSystem, cmd)
+ self._proxStarter.startThreaded();
+
+ def startJoin(self):
+ ret = self.startJoinNoConnect();
+ self._connectSocket();
+ self._querySetup();
+ return self._proxStarter.getStartDuration();
+
+ def startJoinNoConnect(self):
+ return self._proxStarter.joinThreaded();
+
+ def getCmd(self):
+ proxDir = self._systemConfig.getProxDir();
+ cfgFile = self._systemConfig.getCfgFile();
+
+ cmd = "cd " + proxDir + "; "
+ cmd += "sudo ./build/prox "
+ cmd += "-f " + cfgFile
+
+ for arg in self._args:
+ cmd += " " + arg
+ return cmd
+
+ def getLog(self):
+ proxDir = self._systemConfig.getProxDir()
+ cmd = "cat " + proxDir + "/prox.log";
+ return self._remoteSystem.run(cmd)["out"];
+
+ def getIP(self):
+ return self._systemConfig._ip;
+
+ def getHz(self):
+ return self._hz;
+
+ def getBeg(self):
+ return self._beg;
+
+ def getPorts(self):
+ return self._ports;
+
+ def getIerrors(self):
+ sc = StatsCmd(self)
+ sc.add(self._buildIerrorsCmd());
+ sc.sendRecv()
+ return self._parseIerrorsReply(sc.getResult(0));
+
+ def _parseIerrorsReply(self, rep):
+ tot_ierrors = 0;
+ for e in rep:
+ tot_ierrors += int(e);
+ return tot_ierrors;
+
+ def _buildIerrorsCmd(self):
+ cmd = ""
+ for port in self._ports:
+ if (len(cmd)):
+ cmd += ","
+ cmd += "port(%s).ierrors" % str(port)
+ return cmd;
+
+ def waitCmdFinished(self):
+ self._send("stats hz")._recv();
+
+ def waitAllLinksUp(self):
+ link_down = True;
+ while (link_down):
+ link_down = False;
+ for port in self._ports:
+ cmd = "port link state %s" % str(port)
+ link_state = self._send(cmd)._recv();
+ if (link_state == "down"):
+ link_down = True;
+ print "Link down on port " + str(port) + ", waiting one second"
+ break;
+ sleep(1);
+
+ def startAllCores(self):
+ self._send("start all");
+
+ def stopAllCores(self):
+ self._send("stop all");
+
+ def forceQuit(self):
+ self._send("quit_force")._recv();
+
+ def killProx(self):
+ self._remoteSystem.run("sudo killall -w -q -9 prox")
+
+ def getTsc(self):
+ return self._getTsc();
+
+ def _getTsc(self):
+ return int(self._send("stats global.tsc")._recv());
+
+ def scpStatsDump(self, dst):
+ proxDir = self._systemConfig.getProxDir()
+
+ src = proxDir + "/stats_dump";
+ print "Copying " + src + " to " + dst
+ self._remoteSystem.scp(src, dst);
+
+ def _querySetup(self):
+ print "Query setup on " + str(self.getIP())
+ self._queryHz()
+ self._queryBeg()
+ self._queryPorts()
+ self._querySetup2()
+
+ def _querySetup2(self):
+ print "running query 2"
+ pass
+
+ def quitProx(self):
+ self._send("quit")._recv();
+
+ def _queryHz(self):
+ self._hz = int(self._send("stats hz")._recv());
+
+ def _queryBeg(self):
+ self._beg = self._getTsc();
+
+ def _queryPorts(self):
+ self._ports = []
+ port_info_all = self._send("port info all")._recv();
+ port_info_list = port_info_all.split(',');
+
+ for port_info in port_info_list:
+ if (len(port_info) > 0):
+ self._ports.append(int(port_info.split(":")[0]));
+
+ def _connectSocket(self):
+ self._proxSocket = ProxSocket(self.getIP())
+
+ def _send(self, msg):
+ self._proxSocket.send(msg);
+ return self
+
+ def _recv(self):
+ return self._proxSocket.recv();
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/proxdpisut.py b/VNFs/DPPD-PROX/helper-scripts/dpi/proxdpisut.py
new file mode 100644
index 00000000..aae900b0
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/proxdpisut.py
@@ -0,0 +1,61 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+from prox import *
+from remotesystem import *
+from time import *
+from decimal import *
+
+class ProxDpiSut(Prox):
+ def __init__(self, ts, coreCount):
+ super(ProxDpiSut, self).__init__(ts)
+
+ self._setDefaultArguments();
+ self._setDpiCoreCount(coreCount);
+
+ def _setDefaultArguments(self):
+ self.addArgument("-e");
+ self.addArgument("-t");
+ self.addArgument("-k");
+ self.addArgument("-d");
+ self.addArgument("-r 0.01");
+
+ def _setDpiCoreCount(self, count):
+ self.addArgument("-q dpi_core_count=" + str(count))
+
+ def _querySetup2(self):
+ self._query_cores();
+
+ def _query_cores(self):
+ print "querying cores"
+ self._wk = self._get_core_list("$wk");
+
+ def _get_core_list(self, var):
+ ret = []
+ result = self._send("echo " + var)._recv();
+ for e in result.split(","):
+ ret += [e];
+ return ret;
+
+ def getTsc(self):
+ cmd = "stats task.core(%s).task(0).tsc" % self._wk[-1]
+ res = int(self._send(cmd)._recv());
+ if (res == 0):
+ return self._getTsc();
+ else:
+ return res;
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/proxdpitester.py b/VNFs/DPPD-PROX/helper-scripts/dpi/proxdpitester.py
new file mode 100644
index 00000000..19b08c92
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/proxdpitester.py
@@ -0,0 +1,258 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+from prox import *
+from remotesystem import *
+from time import *
+from decimal import *
+from timeseriespoint import *
+
+class TestParameters:
+ def __init__(self, max_setup_rate, total_connections, ss):
+ self.max_setup_rate = max_setup_rate;
+ self.total_connections = total_connections;
+ self.ss = ss;
+
+ def toString(self):
+ ret = ""
+ ret += "\tMaximum setup rate = %d\n" % self.max_setup_rate
+ ret += "\tTotal number of connections = %d\n" % self.total_connections
+ ret += "\tSpeed scaling = %s\n" % str(self.ss)
+ return ret;
+
+ def getPerSystem(self, count):
+ msr = self.max_setup_rate / count
+ cnn = self.total_connections / count
+ return TestParameters(msr, cnn, self.ss);
+
+ def getConnections(self):
+ return self.total_connections;
+
+class ProxDpiTester(Prox):
+ TENGIGABITBYTESPERSECOND = 1250000000
+
+ def __init__(self, ts, testParam, ID):
+ super(ProxDpiTester, self).__init__(ts)
+
+ self._sc = None
+ self._lastTot = None
+ self._prevTot = None;
+ self._prevBytesClient = None
+ self._lastBytesClient = None
+ self._prevBytesTxMeassurement = None
+ self._lastBytesTxMeassurement = None
+
+ self._setDefaultArguments();
+ self._setMsr(testParam.max_setup_rate)
+ self._setConnections(testParam.total_connections);
+ self._setSpeedScaling(testParam.ss);
+ self._setID(ID);
+
+ def _setDefaultArguments(self):
+ self.addArgument("-e")
+ self.addArgument("-t")
+ self.addArgument("-k")
+ self.addArgument("-d")
+ self.addArgument("-r 0.01");
+
+ def _setMsr(self, msr):
+ self.addArgument("-q max_setup_rate=" + str(msr))
+
+ def _setConnections(self, connections):
+ self.addArgument("-q connections=" + str(connections))
+
+ def _setID(self, ID):
+ self.addArgument("-q test_system_id=" + str(ID))
+
+ def _setSpeedScaling(self, ss):
+ self.addArgument("-q ss=" + str(ss))
+
+ def _querySetup2(self):
+ self._query_client_ports();
+ self._query_server_ports();
+ self._query_cores();
+
+ def _query_client_ports(self):
+ self._client_ports = []
+ for i in range(0, len(self._ports), 2):
+ self._client_ports.append(self._ports[i]);
+
+ def _query_server_ports(self):
+ self._server_ports = []
+ for i in range(1, len(self._ports), 2):
+ self._server_ports.append(self._ports[i]);
+
+ def _query_cores(self):
+ self._query_ld();
+ self._query_servers();
+ self._query_clients();
+
+ def _query_ld(self):
+ self._ld = self._get_core_list("$all_ld");
+
+ def _query_servers(self):
+ self._servers = self._get_core_list("$all_servers")
+
+ def _query_clients(self):
+ self._clients = self._get_core_list("$all_clients")
+
+ def _get_core_list(self, var):
+ ret = []
+ result = self._send("echo " + var)._recv();
+ for e in result.split(","):
+ ret += [e];
+ return ret;
+
+ def start_all_ld(self):
+ self._send("start $all_ld");
+
+ def start_all_workers(self):
+ self._send("start $all_workers");
+
+ def stop_all_ld(self):
+ self._send("stop $all_ld");
+
+ def stop_all_workers(self):
+ self._send("stop $all_workers");
+
+ def update_stats(self):
+ if (self._sc is None):
+ self._sc = StatsCmd(self)
+ self._sc.add(self._buildTotalConnectionsCmd())
+ self._sc.add(self._buildReTXCmd())
+ self._sc.add(self._buildIerrorsCmd())
+ self._sc.add(self._buildBytesPerPortCmd(self._client_ports, "rx"));
+
+ self._sc.sendRecv()
+
+ self._updateTotalConnections(self._sc.getResult(0))
+ self._updateReTX(self._sc.getResult(1))
+ self._updateIerrors(self._sc.getResult(2))
+ self._update_rates_client_ports(self._sc.getResult(3));
+
+ def _buildTotalConnectionsCmd(self):
+ cmd = "l4gen(%s).tsc" % str(self._clients[0])
+
+ for core in self._clients:
+ if (len(cmd) > 0):
+ cmd += ","
+ cmd += "l4gen(%s).created,l4gen(%s).finished" % (str(core), str(core))
+ return cmd;
+
+ def _updateTotalConnections(self, rep):
+ instant = Decimal(int(rep[0]) - self._beg)/self._hz
+ rep = rep[1:]
+ tot = 0;
+ for i in range(0,len(rep), 2):
+ tot += int(rep[i]) - int(rep[i + 1]);
+
+ prev = self._lastTot;
+ last = TimeSeriesPoint(tot, instant);
+
+ if (prev == None):
+ prev = last;
+
+ self._prevTot = prev
+ self._lastTot = last;
+
+ def _buildReTXCmd(self):
+ cmd = ""
+ for core in self._clients + self._servers:
+ if (len(cmd) > 0):
+ cmd += ","
+ cmd += "l4gen(%s).retx" % str(core)
+ return cmd;
+
+ def _updateReTX(self, rep):
+ retx = 0;
+ for i in rep:
+ retx += int(i);
+ self._retx = retx;
+
+ def _updateIerrors(self, rep):
+ self._ierrors = self._parseIerrorsReply(rep)
+
+ def get_total_connections(self):
+ return self._lastTot.getValue()
+
+ def getCurrentSetupRate(self):
+ return int(self._lastTot.getRateOfChange(self._prevTot));
+
+ def get_total_retx(self):
+ return self._retx
+
+ def get_rates_client_ports(self):
+ return self._calcLinkUtilization(self._prevBytesClient, self._lastBytesClient);
+
+ def getIerrorsCached(self):
+ return self._ierrors;
+
+ def _update_rates_client_ports(self, rep):
+ prevBytes = self._lastBytesClient
+ lastBytes = self._parseTimeSeries(rep);
+
+ if (prevBytes == None):
+ prevBytes = lastBytes;
+
+ self._prevBytesClient = prevBytes;
+ self._lastBytesClient = lastBytes;
+
+ def _getBytesPerPort(self, ports, rxOrTx):
+ sc = StatsCmd(self);
+ sc.add(self._buildBytesPerPortCmd(ports, rxOrTx))
+ sc.sendRecv();
+
+ rep = sc.getResult(0);
+
+ return self._parseTimeSeries(rep);
+
+ def _buildBytesPerPortCmd(self, ports, rxOrTx):
+ cmd = ""
+ for port in ports:
+ if (len(cmd) > 0):
+ cmd += ","
+ cmd += "port(%s).%s.bytes,port(%s).tsc" % (str(port), rxOrTx, str(port));
+ return cmd
+
+ def tx_rate_meassurement(self):
+ prev = self._lastBytesTxMeassurement
+ last = self._getBytesPerPort(self._server_ports, "tx");
+
+ if (prev == None):
+ prev = last;
+
+ self._prevBytesTxMeassurement = prev
+ self._lastBytesTxMeassurement = last
+
+ return self._calcLinkUtilization(prev, last);
+
+ def _parseTimeSeries(self, rep):
+ ret = []
+ for i in range(0, len(rep), 2):
+ val = int(rep[0])
+ instant = Decimal(int(rep[1]) - self._beg)/self._hz
+ ret.append(TimeSeriesPoint(val, instant));
+ return ret;
+
+ def _calcLinkUtilization(self, prev, last):
+ ret = []
+ for i in range(0, len(prev)):
+ bytesPerSecond = last[i].getRateOfChange(prev[i]);
+ linkFraction = Decimal(bytesPerSecond)/self.TENGIGABITBYTESPERSECOND
+ ret.append(round(linkFraction,2));
+ return ret;
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/proxmaxssprobe.py b/VNFs/DPPD-PROX/helper-scripts/dpi/proxmaxssprobe.py
new file mode 100644
index 00000000..27c470c4
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/proxmaxssprobe.py
@@ -0,0 +1,34 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+from decimal import *
+from prox import *
+
+class ProxMaxSSProbe(Prox):
+ def __init__(self, ts):
+ super(ProxMaxSSProbe, self).__init__(ts)
+
+ def getMaxSS(self):
+ self.addArgument("-q max_ss_and_quit=true");
+ self.addArgument("-q test_system_id=0");
+ self.startFork();
+ ret = self.startJoinNoConnect();
+ last_occur = ret["out"].rfind("\n") + 1;
+ last_line = ret["out"][last_occur:];
+
+ return Decimal(last_line.split("=")[1])
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/proxsocket.py b/VNFs/DPPD-PROX/helper-scripts/dpi/proxsocket.py
new file mode 100644
index 00000000..fd4cc737
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/proxsocket.py
@@ -0,0 +1,54 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+import socket
+
+class ProxSocket:
+ def __init__(self, ip):
+ self._ip = ip;
+ self._dat = ""
+
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ try:
+ sock.connect((self._ip, 8474))
+ except:
+ raise Exception("Failed to connect to prox on " + self._ip)
+ self._sock = sock;
+
+ def send(self, msg):
+ self._sock.sendall(msg + "\n");
+ return self
+
+ def recv(self):
+ ret_str = "";
+ done = 0;
+ while done == 0:
+ if (len(self._dat) == 0):
+ self._dat = self._sock.recv(256);
+ if (self._dat == ''):
+ return '';
+
+ while(len(self._dat)):
+ if (self._dat[0] == '\n'):
+ done = 1
+ self._dat = self._dat[1:]
+ break;
+ else:
+ ret_str += self._dat[0];
+ self._dat = self._dat[1:]
+ return ret_str;
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/ratedistribution.py b/VNFs/DPPD-PROX/helper-scripts/dpi/ratedistribution.py
new file mode 100644
index 00000000..41d8ad53
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/ratedistribution.py
@@ -0,0 +1,69 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+import sys
+from decimal import *
+
+def usage(progName):
+ print "usage: " + progName + " config [up|down]"
+ print " The script reads a lua configuration "
+ print " and outputs a histogram wit 21 buckets."
+ print " The first 20 buckets contain 70th percentile."
+ print " The last bucket contains the remaining items."
+ exit(-1);
+
+if (len(sys.argv) != 3):
+ usage(sys.argv[0])
+
+if (sys.argv[2] == "down"):
+ match = "dn_bps"
+elif (sys.argv[2] == "up"):
+ match = "up_bps"
+else:
+ usage(sys.argv[0])
+
+values = []
+for line in open(sys.argv[1]).readlines():
+ line = line.strip();
+
+ if line.find(match) != -1:
+ v = line.split(" = ")[1].strip(",")
+ values.append(Decimal(v));
+
+values = sorted(values)
+
+treshold = values[int(len(values)*0.7)]
+
+buckets = [0]*21;
+
+for v in values:
+ if (v > treshold):
+ buckets[20] += 1
+ else:
+ buckets[int(v * 20 / treshold)] += 1
+
+stepSize = treshold / 20;
+
+print "# bucket range, count"
+for i in range(len(buckets) - 1):
+ beg = str(int(i * stepSize))
+ end = str(int((i + 1) * stepSize - 1))
+ print beg + "-" + end + "," + str(buckets[i])
+
+i = len(buckets) - 1
+print beg + "+," + str(buckets[i])
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/remotesystem.py b/VNFs/DPPD-PROX/helper-scripts/dpi/remotesystem.py
new file mode 100644
index 00000000..adbb288c
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/remotesystem.py
@@ -0,0 +1,58 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+import os
+import time
+import socket
+
+def ssh(user, ip, cmd):
+ # print cmd;
+ ssh_options = ""
+ ssh_options += "-o StrictHostKeyChecking=no "
+ ssh_options += "-o UserKnownHostsFile=/dev/null "
+ ssh_options += "-o LogLevel=quiet "
+ running = os.popen("ssh " + ssh_options + " " + user + "@" + ip + " \"" + cmd + "\"");
+ ret = {};
+ ret['out'] = running.read().strip();
+ ret['ret'] = running.close();
+ if (ret['ret'] == None):
+ ret['ret'] = 0;
+
+ return ret;
+
+def ssh_check_quit(obj, user, ip, cmd):
+ ret = ssh(user, ip, cmd);
+ if (ret['ret'] != 0):
+ obj._err = True;
+ obj._err_str = ret['out'];
+ exit(-1);
+
+class remoteSystem:
+ def __init__(self, user, ip):
+ self._ip = ip;
+ self._user = user;
+
+ def run(self, cmd):
+ return ssh(self._user, self._ip, cmd);
+
+ def scp(self, src, dst):
+ running = os.popen("scp " + self._user + "@" + self._ip + ":" + src + " " + dst);
+ return running.close();
+
+ def getIP(self):
+ return self._ip
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/resultprocessor.py b/VNFs/DPPD-PROX/helper-scripts/dpi/resultprocessor.py
new file mode 100644
index 00000000..ad196035
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/resultprocessor.py
@@ -0,0 +1,210 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+from sutstatsconsfile import *
+from tsstatsconsfile import *
+from csvwriter import *
+
+class TestResult:
+ class Times:
+ def __init__(self):
+ self.serie = []
+ def addTime(self, val):
+ self.serie.append(val)
+ def getTime(self, i):
+ return self.serie[i]
+
+ def __init__(self, testSystemCount):
+ self.rates = None;
+ self.tsStatsDump = [];
+ self.tsTimes = [];
+ for i in range(testSystemCount):
+ self.tsStatsDump.append("");
+ self.tsTimes.append(TestResult.Times());
+
+ self.sutStatsDump = None;
+ self.sutTime = TestResult.Times();
+
+ def getTSCount(self):
+ return len(self.tsTimes)
+
+ def setTSStatsDump(self, filePaths):
+ self.tsStatsDump = filePaths;
+
+ def setSUTStatsDump(self, filePath):
+ self.sutStatsDump = filePath;
+
+ def getTSStatsDump(self):
+ return self.tsStatsDump;
+
+ def getSUTStatsDump(self):
+ return self.sutStatsDump;
+
+ def addTimeTS(self, times):
+ for i in range(len(times)):
+ self.tsTimes[i].addTime(times[i])
+
+ def addTimeSUT(self, time):
+ self.sutTime.addTime(time);
+
+
+class ResultProcessor:
+ def __init__(self, testResult):
+ self._testResults = testResult;
+
+ def process(self):
+ self._readStatsConsLogs();
+ self._mergeTsStats();
+ self._calcSetupRate();
+
+ def percentHandled(self):
+ converged_tsc = self._testResults.sutTime.getTime(1) - self._testResults.sutTime.getTime(0)
+ end_tsc = self._testResults.sutTime.getTime(2) - self._testResults.sutTime.getTime(0)
+
+ converged = converged_tsc/Decimal(self._sutHz)
+ end = end_tsc/Decimal(self._sutHz);
+
+ rx_converged = -1
+ tx_converged = -1
+ rx_end = -1
+ tx_end = -1
+
+ for entry in self._sutStats:
+ timeStamp = entry[3]
+ if (rx_converged == -1):
+ if (timeStamp > converged):
+ rx_converged = entry[0]
+ tx_converged = entry[1] - entry[2]
+ else:
+ continue;
+ else:
+ if (timeStamp > end):
+ rx_end = entry[0]
+ tx_end = entry[1] - entry[2]
+ break;
+ return (tx_end - tx_converged)/Decimal(rx_end - rx_converged)
+
+ def toFile(self, fileName):
+ outFile = CsvWriter();
+
+ outFile.open(fileName)
+
+ for entry in self._sutStats:
+ timeStamp = round(entry[3], 3);
+ rx = entry[0]
+ tx = entry[1]
+ drop = entry[2]
+
+ outFile.write([timeStamp, rx, tx, drop, "", ""])
+
+ for entry in self._tsStats:
+ timeStamp = round(entry[-1], 3);
+ connections = entry[0]
+ setupRate = entry[3]
+ outFile.write([timeStamp,"","","", connections, setupRate]);
+ outFile.close();
+
+ def _readStatsConsLogs(self):
+ print "Reading SUT stats"
+ self._sutStats = self._readSutStats();
+ print "Reading TS stats"
+ self._tsAllStats = self._readAllTSStats();
+
+ def _mergeTsStats(self):
+ # The first test system is the reference system. The totals
+ # will be accumulated by repeatedly taking the closest
+ # available data from other systems
+ ret = []
+ for entry in self._tsAllStats[0]:
+ ret.append(entry)
+
+ interSampleTime = ret[1][-1] - ret[0][-1];
+
+ mergedSampleCount = 0;
+ if (len(self._tsAllStats) == 1):
+ mergedSampleCount = len(ret)
+
+ for i in range(0, len(self._tsAllStats) - 1):
+ prev = 0;
+ for entry in ret:
+ timeStamp = entry[-1]
+ found = False;
+
+ for idx in range(prev, len(self._tsAllStats[i])):
+ diff = abs(self._tsAllStats[i][idx][-1] - timeStamp)
+ if (diff < interSampleTime):
+ found = True;
+ prev = idx;
+ break;
+
+ if (found):
+ entry[0] += self._tsAllStats[i][prev][0]
+ entry[1] += self._tsAllStats[i][prev][1]
+ mergedSampleCount += 1;
+ else:
+ break;
+
+ self._tsStats = ret[0: mergedSampleCount];
+
+ def _calcSetupRate(self):
+ for i in range(0, len(self._tsStats)):
+ prevCreated = 0
+ prevTime = 0
+ if (i > 0):
+ prevCreated = self._tsStats[i - 1][1];
+ prevTime = self._tsStats[i - 1][-1];
+ curCreated = self._tsStats[i][1];
+ curTime = self._tsStats[i][-1];
+
+ setupRate = (curCreated - prevCreated)/(curTime - prevTime)
+
+ self._tsStats[i].append(setupRate);
+
+
+ def _readSutStats(self):
+ ret = []
+ fileName = self._testResults.getSUTStatsDump();
+ beg = self._testResults.sutTime.getTime(0);
+ f = SutStatsConsFile(fileName, beg);
+ entry = f.readNext();
+ self._sutHz = f.getHz();
+ while (entry is not None):
+ ret.append(entry);
+ entry = f.readNext();
+ f.close();
+ return ret;
+
+ def _readAllTSStats(self):
+ stats = []
+ for i in range(self._testResults.getTSCount()):
+ fileName = self._testResults.getTSStatsDump()[i]
+ beg = self._testResults.tsTimes[i].getTime(0)
+ tsStat = self._readTSStats(fileName, beg)
+ stats.append(tsStat);
+ return stats;
+
+ def _readTSStats(self, fileName, beg):
+ ret = []
+ f = TSStatsConsFile(fileName, beg)
+
+ entry = f.readNext()
+ while (entry is not None):
+ ret.append(entry);
+ entry = f.readNext();
+ f.close()
+ return ret;
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/statsconsfile.py b/VNFs/DPPD-PROX/helper-scripts/dpi/statsconsfile.py
new file mode 100644
index 00000000..a25c1232
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/statsconsfile.py
@@ -0,0 +1,84 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+import os
+import struct
+
+class StatsConsFile:
+ def __init__(self, file_name, tsc = None):
+ self._file = open(file_name, "rb");
+ try:
+ data = self._file.read(4*8);
+ dataUnpacked = struct.unpack("<qqqq", data);
+
+ self._hz = dataUnpacked[0]
+ if (tsc is None):
+ self._tsc = dataUnpacked[1]
+ else:
+ self._tsc = tsc;
+
+ self._entryCount = dataUnpacked[2]
+ fieldCount = dataUnpacked[3]
+
+ data = self._file.read(fieldCount);
+ fmt = "b" * fieldCount;
+
+ dataUnpacked = struct.unpack("<" + fmt, data);
+ self._entryFmt = "<";
+ self._entrySize = 0;
+
+ for e in dataUnpacked:
+ if (e == 4):
+ self._entryFmt += "i"
+ elif (e == 8):
+ self._entryFmt += "q"
+ else:
+ raise Exception("Unknown field format: " + str(e))
+ self._entrySize += e
+ except:
+ print "except"
+ self._file.close();
+
+ def setBeg(self, tsc):
+ self._tsc = tsc
+
+ def getBeg(self):
+ return self._tsc;
+
+ def getHz(self):
+ return self._hz
+
+ def readNext(self):
+ ret = []
+ for i in range(self._entryCount):
+ entry = self._readNextEntry()
+ if (entry == None):
+ return None;
+ ret.append(entry);
+ return ret;
+
+ def _readNextEntry(self):
+ try:
+ entry = self._file.read(self._entrySize);
+ entryUnpacked = struct.unpack(self._entryFmt, entry);
+ return list(entryUnpacked)
+ except:
+ return None;
+
+ def close(self):
+ self._file.close();
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/sutstatsconsfile.py b/VNFs/DPPD-PROX/helper-scripts/dpi/sutstatsconsfile.py
new file mode 100644
index 00000000..82bca9a8
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/sutstatsconsfile.py
@@ -0,0 +1,61 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+from statsconsfile import *
+from decimal import *
+
+class SutStatsConsFile:
+ def __init__(self, fileName, offset):
+ self.offset = offset;
+ self.statsConsFile = StatsConsFile(fileName)
+
+ def readNext(self):
+ entry = self._readNextEntry();
+
+ if (entry is None):
+ return None;
+
+ while (entry is not None and entry[-1] <= 0):
+ entry = self._readNextEntry();
+ return entry;
+
+ def getHz(self):
+ return self.statsConsFile.getHz();
+
+ def _readNextEntry(self):
+ entry = self.statsConsFile.readNext();
+ if (entry is None):
+ return None;
+
+ rx = 0;
+ tx = 0;
+ drop = 0;
+ last_tsc = 0;
+
+ for i in range(0, len(entry), 2):
+ rx += entry[i][2]
+ tx += entry[i][3]
+ drop += entry[i][4]
+ last_tsc = entry[i][5]
+
+ last_tsc -= self.offset;
+ last_tsc = Decimal(last_tsc) / self.statsConsFile.getHz();
+ return [rx, tx, drop, last_tsc];
+
+ def close(self):
+ self.statsConsFile.close();
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/systemconfig.py b/VNFs/DPPD-PROX/helper-scripts/dpi/systemconfig.py
new file mode 100644
index 00000000..9e35576f
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/systemconfig.py
@@ -0,0 +1,73 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+class SystemConfig:
+ _user = None
+ _ip = None
+ _proxDir = None
+ _cfgFile = None
+ def __init__(self, user, ip, proxDir, configDir):
+ self._user = user;
+ self._ip = ip;
+ self._proxDir = proxDir;
+ self._cfgFile = configDir;
+ def __init__(self, text):
+ self._user = text.split("@")[0];
+ text = text.split("@")[1];
+ self._ip = text.split(":")[0];
+ self._proxDir = text.split(":")[1];
+ self._cfgFile = text.split(":")[2];
+
+ def getUser(self):
+ return self._user;
+
+ def getIP(self):
+ return self._ip;
+
+ def getProxDir(self):
+ return self._proxDir;
+
+ def getCfgFile(self):
+ return self._cfgFile;
+
+ @staticmethod
+ def checkSyntax(text):
+ split = text.split("@");
+ if (len(split) != 2):
+ return SystemConfig.getSyntaxError(text);
+ after = split[1].split(":");
+ if (len(after) != 3):
+ return SystemConfig.getSyntaxError(text);
+ return ""
+ def toString(self):
+ ret = "";
+ ret += " " + self._user + "@" + self._ip + "\n"
+ ret += " " + "prox dir: " + self._proxDir + "\n"
+ ret += " " + "cfg dir: " + self._cfgFile + "\n"
+ return ret;
+
+ @staticmethod
+ def getSyntaxError(text):
+ ret = "Invaild system syntax"
+ ret += ", got: " + str(text)
+ ret += ", expected: " + str(SystemConfig.expectedSyntax())
+ return ret;
+
+ @staticmethod
+ def expectedSyntax():
+ return "user@ip:proxDir:cfgFile"
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/testerset.py b/VNFs/DPPD-PROX/helper-scripts/dpi/testerset.py
new file mode 100644
index 00000000..fe3dce72
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/testerset.py
@@ -0,0 +1,176 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+from proxdpitester import *
+
+class testerSet:
+ def __init__(self, test_systems, maxRate, testParam):
+ self._test_systems = [];
+ self._reason = ""
+ self._maxRate = maxRate
+
+ testParamPerSystem = testParam.getPerSystem(len(test_systems));
+
+ for i in range(len(test_systems)):
+ ts = test_systems[i];
+ to_add = ProxDpiTester(ts, testParamPerSystem, i);
+ self.add_test_system(to_add);
+
+ def getCount(self):
+ return len(self._test_systems);
+
+ def add_test_system(self, test_system):
+ self._test_systems.append(test_system);
+
+ def startFork(self):
+ print "Starting test systems:"
+ for ts in self._test_systems:
+ print "\t" + str(ts.getIP())
+ ts.startFork();
+
+ def startJoin(self):
+ for ts in self._test_systems:
+ elapsed = ts.startJoin();
+ if (elapsed == None):
+ print "Failed to start on " + str(ts.getIP())
+ else:
+ print "Started on " + str(ts.getIP())
+ sleep(1);
+
+ def startForkJoin(self):
+ self.startFork();
+ self.startJoin();
+
+ def update_stats(self):
+ for ts in self._test_systems:
+ ts.update_stats();
+
+ def wait_links_up(self):
+ for ts in self._test_systems:
+ ts.waitAllLinksUp();
+ sleep(1);
+
+ def start_cores(self):
+ for ts in self._test_systems:
+ ts.start_all_ld();
+ ts.waitCmdFinished();
+ for ts in self._test_systems:
+ ts.start_all_workers();
+ for ts in self._test_systems:
+ ts.waitCmdFinished();
+
+ def stop_cores(self):
+ for ts in self._test_systems:
+ ts.stop_all_workers();
+ ts.stop_all_ld();
+
+ for ts in self._test_systems:
+ ts.waitCmdFinished();
+
+ def getTsc(self):
+ ret = []
+ for ts in self._test_systems:
+ ret += [ts.getTsc()]
+ return ret;
+
+ def get_setup_rate(self):
+ total = 0;
+ for ts in self._test_systems:
+ total += ts.getCurrentSetupRate();
+ return total
+
+ def get_total_connections(self):
+ total = 0;
+ for ts in self._test_systems:
+ ts_tot_conn = ts.get_total_connections();
+ total += ts_tot_conn
+
+ return total;
+
+ def get_total_retx(self):
+ total = 0;
+ for ts in self._test_systems:
+ total += ts.get_total_retx();
+ return total;
+
+ def getIerrors(self):
+ total = 0;
+ for ts in self._test_systems:
+ total += ts.getIerrorsCached();
+ return total;
+
+ def get_rates(self):
+ rates = [];
+ for ts in self._test_systems:
+ rates += ts.get_rates_client_ports();
+ return rates;
+
+ def tx_rate_meassurement(self):
+ rates = []
+ for ts in self._test_systems:
+ rates += ts.tx_rate_meassurement();
+ return rates;
+
+ def scpStatsDump(self, dst):
+ ret = []
+ for i in range(len(self._test_systems)):
+ dstFileName = dst + str(i);
+ ret.append(dstFileName);
+ self._test_systems[i].scpStatsDump(dstFileName)
+ return ret;
+
+ def conditionsGood(self):
+ tot_retx = self.get_total_retx();
+ rates = self.get_rates();
+ ierrors = self.getIerrors();
+
+ if (tot_retx > 100):
+ self._reason = "Too many reTX (" + str(tot_retx) + ")"
+ return False;
+ if (ierrors > 0):
+ self._reason = "Too many ierrors (" + str(ierrors) + ")"
+ return False;
+ for i in range(0, len(rates)):
+ if (rates[i] > self._maxRate):
+ self._setReason(i, rates)
+ return False;
+ return True;
+
+ def _setReason(self, port, rates):
+ portStr = str(port);
+ rateStr = str(rates[port])
+ maxRateStr = str(self._maxRate);
+ allRatesStr = str(rates);
+
+ fmt = "Rate on port %s = %s > %s, rate on all = %s"
+ self._reason = fmt % (portStr, rateStr, maxRateStr, allRatesStr)
+
+ def getReason(self):
+ return self._reason;
+
+ def quitProx(self):
+ for ts in self._test_systems:
+ ts.quitProx();
+
+ def killProx(self):
+ for ts in self._test_systems:
+ ts.stop_all_workers();
+ for ts in self._test_systems:
+ ts.stop_all_ld();
+ for ts in self._test_systems:
+ ts.killProx();
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/timeseriespoint.py b/VNFs/DPPD-PROX/helper-scripts/dpi/timeseriespoint.py
new file mode 100644
index 00000000..521a0893
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/timeseriespoint.py
@@ -0,0 +1,39 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+from decimal import *
+
+class TimeSeriesPoint:
+ def __init__(self, value, instant):
+ self._value = value;
+ self._instant = instant;
+
+ def getValue(self):
+ return self._value;
+
+ def getInstant(self):
+ return self._instant;
+
+ def getRateOfChange(self, other):
+ diff = self.getValue() - other.getValue();
+ t_diff = self.getInstant() - other.getInstant();
+
+ if (diff == 0 or abs(t_diff) <= 0.00001):
+ return Decimal(0)
+ else:
+ return Decimal(diff)/t_diff
diff --git a/VNFs/DPPD-PROX/helper-scripts/dpi/tsstatsconsfile.py b/VNFs/DPPD-PROX/helper-scripts/dpi/tsstatsconsfile.py
new file mode 100644
index 00000000..10e48a68
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/dpi/tsstatsconsfile.py
@@ -0,0 +1,60 @@
+#!/bin/env python
+
+##
+## Copyright (c) 2010-2017 Intel Corporation
+##
+## 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.
+##
+
+from statsconsfile import *
+from decimal import *
+
+class TSStatsConsFile:
+ def __init__(self, fileName, offset):
+ self.offset = offset;
+ self.statsConsFile = StatsConsFile(fileName)
+
+ def readNext(self):
+ entry = self._readNextEntry();
+ if (entry is None):
+ return None;
+
+ while (entry is not None and entry[-1] <= 0):
+ entry = self._readNextEntry();
+
+ return entry;
+
+ def _readNextEntry(self):
+ entry = self.statsConsFile.readNext();
+ if (entry is None):
+ return None;
+
+ rx = 0;
+ tx = 0;
+ active = 0;
+ created = 0;
+ last_tsc = 0;
+ for i in range(0, len(entry), 2):
+ active += entry[i][2]
+ created += entry[i][3]
+ rx += entry[i][4]
+ tx += entry[i][5]
+ last_tsc = entry[i][6]
+
+ last_tsc -= self.offset;
+ last_tsc = Decimal(last_tsc) / self.statsConsFile.getHz();
+
+ return [active, created, rx, tx, last_tsc];
+
+ def close(self):
+ self.statsConsFile.close();